频道栏目
首页 > 资讯 > 其他 > 正文

C++异常

16-12-28        来源:[db:作者]  
收藏   我要投稿
C++异常:编程开发时碰见异常了怎么办?有什么方法解决吗?希望下面的文章对大家有所帮助。
int Divide(int a,int b)
{
    if(b == 0)
    {
        cout << "b is zero" << endl;
        std::abort(); // 这句执行会直接退出程序,而不是回到main函数
    }
    return a / b;
}

int main()
{
    cout << Divide(1, 0) << endl;
    cout << "main end" << endl;
    return 0;
}

在使用Divide之前应当判断a,b值的,依靠程序员来执行检查是不安全的

异常处理之返回错误码

根据函数的返回值,来判断是否异常
例如可以定义很多error值,返回不同就表示不同的error

C++异常机制

异常提供了将控制权从程序的一部分传递到另一部分的途径
对异常处理有3个组成部分

引发异常 使用处理程序捕获异常 使用try块

throw语句类似跳转,throw关键字引发异常,并且其随后的值指出了异常的特征

处理异常用catch捕获

执行throw语句类似执行返回语句,因为它也将终止函数的执行;但是throw不是将控制权返回给调用程序,而是导致程序沿着函数调用序列后退,,直到找到包含try块的函数

如果函数引发异常,而没有try块或没有匹配的处理函数,程序最终降调用abort()函数。


垃圾程序

int Divide(int a,int b)
{
    if(b == 0)
    {
        throw "b is zero";
    }
    return a / b;
}

void fun()
{
    try{
        cout << "fun()" << endl;
    }catch(const char* err){
        cout << err << endl;
    }
}

void fun2()
{
    try{
        cout << "fun2()" << endl;
    }catch(const char* err){
        puts(err);
    }
}

int main()
{
    try{
        cout << "main()" << endl;
    }catch(const char* err){
        puts(err);
    }
    fun();
    fun2();
    cout << Divide(1, 0) << endl;
    cout << "main end" << endl;
    return 0;
}

必须是 try{}catch(){}捕获异常

try{
    Divide(1, 0);
}catch(const char* err){
    puts(err);
}

异常匹配

void myStrcpy(char *to, char *from) 
{ 
    if (from == NULL) { 
        throw  "源buf出错"; // 这里抛出的异常是char *
    } 
    if (to == NULL) { 
        throw "目的buf出错"; 
    } 

    while (*from != '\0') { 
        *to = *from; 
        to++; 
        from++; 
    } 
    *to = '\0'; 

    return; 
} 

int main() 
{ 
    //异常被抛出后,从进入try块起,到异常被抛掷前,这期间在栈上的构造的所有对象, 
    //都会被自动析构。析构的顺序与构造的顺序相反。 
    //这一过程称为栈的解旋(unwinding) 
    try
    { 
        myStrcpy(NULL,NULL);
        // 接下去的语句都不执行
        //myStrcpy(NULL,"source");
    }
    catch(char* s)
    {
        puts(s);
    }
    catch(string &e)
    {   
        cout << e << endl;
    } 
    catch (...) 
    { 
        cout << "未知类型异常" << endl; 
    }

    return 0;
}

使用异常类

class MyException {
public:
    void pf(){
        cout << "error" << endl;
    };
}; 

class Test 
{ 
public: 
  Test(int a = 0, int b = 0) 
  { 
    this->a = a; 
    this->b = b; 
    cout << "Test 构造函数执行" << "a:" << a << " b: " << b << endl; 
  } 
  void printT() 
  { 
    cout << "a:" << a << " b: " << b << endl; 
  } 
  ~Test() 
  { 
    cout << "Test 析构函数执行" << "a:" << a << " b: " << b << endl; 
  } 
private: 
  int a; 
  int b; 
}; 

void myFunc() // throw (MyException) 
{ 
  Test t1(1,1); //
  Test t2(2,2); // 

  cout << "定义了两个栈变量,异常抛出后测试栈变量的如何被析构" << endl; 

  throw MyException(); 
} 

int main() 
{ 
    //异常被抛出后,从进入try块起,到异常被抛掷前,这期间在栈上的构造的所有对象, 
    //都会被自动析构。析构的顺序与构造的顺序相反。 
    //这一过程称为栈的解旋(unwinding) 
    try
    { 
        myFunc(); 
    } 
    catch(MyException &e) 
    //catch (MyException)
    {
        e.pf();
        //这里不能访问异常对象 
        cout << "接收到MyException类型异常" << endl; 
    } 
    catch (...) 
    { 
        cout << "未知类型异常" << endl; 
    }

    return 0;
}

异常捕获的几个例子

例子1

int Divide(int a,int b)
{
    if(b == 0)
    {
        throw "b is zero";
    }
    return a / b;
}

void fun2()
{
    try{
        Divide(1, 0);
    }catch(const char err){
        cout << "fun2 catch exception" << endl;
        printf("%c\n",err);
    }
    catch(const char* err){
        cout << "fun2 catch exception" << endl;
        puts(err);
    }
    cout << "end fun2()" << endl;
}

int main()
{
    try{
        fun2();
    }catch(const char* err){
        cout << "main catch exception" << endl;
        puts(err);
    }
    cout << "main end" << endl;
    return 0;
}

上述代码中, fun2将不捕获到 (const char* err)的异常,那么fun2继续执行完成,main中将捕获不到异常

例子2

int Divide(int a,int b)
{
    if(b == 0)
    {
        throw "b is zero";
    }
    return a / b;
}

void fun2()
{
    try{
        Divide(1, 0);
    }catch(const char err){
        cout << "fun2 catch exception" << endl;
        printf("%c\n",err);
    }
    cout << "end fun2()" << endl;
}

int main()
{
    try{
        fun2();
    }catch(const char* err){
        cout << "main catch exception" << endl;
        puts(err);
    }
    cout << "main end" << endl;
    return 0;
}

fun2捕获不到(const char* err)的异常, fun2函数将不会正常的执行完全,会退到main函数中,main捕获到异常

例子3

例子2中 若main也不捕获(const char* err)异常,那么程序将调用abort(main函数退出之前就abort)

例子4(C++ primer中的栈解退例子)

class Demo{
public:
    Demo(){
        cout << "Demo::Demo()" << endl;
    }
    ~Demo(){
        cout << "Demo::~Demo()" << endl;
    }
};

int Divide(int a,int b)
{
    Demo d1;
    if(b == 0)
    {
        throw "b is zero";
    }
    return a / b;
}

void fun2()
{
    Demo d2;
    try{
        Divide(1, 0);
    }catch(const char err){
        cout << "fun2 catch exception" << endl;
        printf("%c\n",err);
    }
    cout << "end fun2()" << endl;
}

int main()
{
    try{
        fun2();
    }catch(const char* err){
        cout << "main catch exception" << endl;
        puts(err);
    }
    cout << "main end" << endl;
    return 0;
}

函数由于异常没能执行完,但是函数中的栈仍被释放,一直查找到最终的catch,中间的栈的自动变量都将被释放。

例子5 (异常中的动态内存需要合理释放)

class Demo{
public:
    Demo(){
        cout << "Demo::Demo()" << endl;
    }
    ~Demo(){
        cout << "Demo::~Demo()" << endl;
    }
};

int Divide(int a,int b)
{
    Demo *d1 = new Demo();
    if(b == 0)
    {
        delete d1;
        throw "b is zero";
    }
    delete d1;
    return a / b;
}
相关TAG标签
上一篇:ThinkPHP中自动验证
下一篇:MongoDB启动方式
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站