C++中的异常处理机制以及异常规范

以下代码运行环境为64位系统下的VS2013
C++中的异常情况:
语法错误(编译错误):比如变量未定义、括号不匹配、关键字拼写错误等等编译器在编译时能发现的错误,这类错误可以及时被编译器发现,而且可以及时知道出错的位置及原因,方便改正。
运行时错误:比如数组下标越界、系统内存不足等等。这类错误不易被程序员发现,它能通过编译且能进入运行,但运行时会出错,导致程序崩溃。
为了有效处理程序运行时错误,C++中引入异常处理机制来解决此问题。
C++异常处理机制:
异常处理基本思想:执行一个函数的过程中发现异常,可以不用在本函数内立即进行处理, 而是抛出该异常,让函数的调用者直接或间接处理这个问题。
C++异常处理机制由3个模块组成:try(检查)、throw(抛出)、catch(捕获)
抛出异常的语句格式为:throw 表达式;如果try块中程序段发现了异常则抛出异常。
try
{
可能抛出异常的语句;(检查)
}
catch(类型名[形参名])//捕获特定类型的异常
{
//处理1;
}
catch(类型名[形参名])//捕获特定类型的异常
{
//处理2;
}
catch(…)//捕获所有类型的异常
{
}
栈展开:
有四个函数f1(),f2(),f3(),f4(),在f2()中调f1(),f3调()f2(),f4()调f3(),main()调f4(),并在f1()抛出一个异常,在main()用catch语句捕获。栈展开过程如下:
C++中的异常处理机制以及异常规范_第1张图片
参考代码:

void f1(int i)
{
    if (i<0)
    throw 1;
}
void f2()
{
    f1(-45);
}
void f3()
{
    f2();
}
void f4()
{
    f3();
}
int main()
{
    try{
        f4();
    }
    catch (int i)
    {
        cout <<"error code:"<< i <<"\n"<< endl;
    }
    system("pause");
    return 0;
}

运行结果:
这里写图片描述
异常捕获的匹配规则:
try 块里面抛出那种类型的异常,则catch里面捕获哪种类型的异常,一般情况下,类型必须完全匹配,但以下3种情况可以进行类型转换:
1、允许从非const对象到const的转换。
即throw1个非const对象,catch1个const对象
2、允许从派生类类型到基类类型的转换。
即throw1个派生类对象,catch1个基类对象
3、将数组转换为指向数组类型的指针,函数转换为指向函数类型的指针。
异常的重新抛出:
参考代码如下:

void fun(int i)
{
    if (i < 0)
        throw - 1;
}
void fun2()
{
    try
    {
        fun(-23);
    }
    catch (int i)
    {
        cout << "errcode:" << i << "\n";
    }
}
int main()
{
    fun2();
    system("pause");
    return 0;
}

运行结果:
这里写图片描述
运行上述代码,我们只能知道程序有错,重新抛出后,我们不仅知道程序有错还可以知道错误原因,这样便于及时改正。
参考代码如下:

void fun(int i)
{
    if (i < 0)
        throw - 1;
}
void fun2(int i)
{
    try
    {
        fun(i);
    }
    catch (int i)
    {
        switch (i)
        {
        case -1;
            throw "数据越界";//重新抛出
        }
    }
}
int main()
{
    try
    {
        fun2(-34);
    }
    catch (const char *s)
    {
        cout << "error code:" << s<<"\n" << endl;
    }
    system("pause");
    return 0;
}

运行结果:
这里写图片描述
异常规范:
函数声明之后,列出该函数可能抛出异常类型,并保证该函数不会抛出其他类型的异常。
1、参考代码如下:

void fun1()throw(int)//表明只能抛出int型异常
{
    throw '1';
}
int main()
{
    fun1();
    system("pause");
    return 0;
}

编译时出现警告:忽略异常
C++中的异常处理机制以及异常规范_第2张图片
2、如果以常规范为throw(),表示不得抛出任何异常。
异常与构造函数和析构函数:
1、保证不在构造函数中抛出异常,因为构造函数的作用是构造对象并初始化,一旦抛出异常,有可能导致对象不完整或没有完全初始化。
2、保证不在析构函数中抛出异常,因为析构函数的作用是完成资源的清理,一旦抛出异常,有可能导致资源泄漏(内存泄漏等等)。

你可能感兴趣的:(C/C++)