C++ 中的异常处理

目录

1、C++异常处理 

2、异常的重新解释 

3、类类型的异常

4、标准库中的异常

5、函数异常声明


 

1、C++异常处理 

C++内置了异常处理的语法元素 try… catch… 

       -try语句处理正常代码逻辑 ,catch语句处理异常情况 ,try语句中的异常由对应的catch语句处理

C++通过throw语句抛出异常信息 ,throw抛出的异常必须被catch处理 

       -若当前函数能够处理异常,程序继续往下执行 ,若当前函数无法处理异常,则函数停止执行,并返回 

同—个try语句可跟上多个catch语句 

       -catch语句可以定义具体处理的异常类型 ,不同类型的异常由不同的catch语句负责处理 

       -try语句中可以抛出任何类型的异常,catch(…) 用于处理所有类型的异常 ,任何异常都只能被捕获(catch)—次 

异常处理的匹配规则:异常抛出后,从上而下严格匹配每一个catch语句处理的类型。异常处理匹配时,不进行任何的类型转换

未被处理的异常会顺着函数调用栈向上传播,直到被处理为止,否则程序将停止执行。 

 

#include <iostream>  

using namespace std;  
  
double divide(double a, double b)  
{  
    const double delta = 0.000000000000001;  
    double ret = 0;  
      
    if( !((-delta < b) && (b < delta)) )  
    {  
        ret = a / b;  
    }  
    else  
    {  
        throw 0;  
    }  
      
    return ret;  
}  
  
int main(int argc, char *argv[])  
{      
    try  
    {  
        double r = divide(1, 0);  
              
        cout << "r = " << r << endl;  
    }  
    catch(...)  
    {  
        cout << "Divided by zero..." << endl;  
    }  
      
    return 0;  
}  

#include <iostream>  
using namespace std;  
  
void Demo1()  
{  
    try  
    {     
        throw 'c';  
    }  
    catch(char c)  
    {  
        cout << "catch(char c)" << endl;  
    }  
    catch(short c)  
    {  
        cout << "catch(short c)" << endl;  
    }  
    catch(double c)  
    {  
        cout << "catch(double c)" << endl;  
    }  
    catch(...)  
    {  
        cout << "catch(...)" << endl;  // ‘...’ handler must be the last handler for its try block [-fpermissive]
    }  
}  
  
void Demo2()  
{  
    throw "Demo2";  
}  
  
int main(int argc, char *argv[])  
{      
    Demo1();  
      
    try  
    {  
        Demo2();  
    }  
    catch(char* s)  
    {  
        cout << "catch(char *s)" << endl;  
    }  
    catch(const char* cs)  // 超级严格的类型匹配
    {  
        cout << "catch(const char *cs)" << endl;  
    }  
    catch(string ss)  
    {  
        cout << "catch(string ss)" << endl;  
    }  
      
    return 0;  
}  

 

 当 throw string("Demo2"); 

2、异常的重新解释 

catch语句块中可以抛出异常(捕获异常并重新抛出异常),catch中抛出的异常需要外层的try catch捕获

catch中捕获的异常可以被重新解释后抛出 ,工程开发中使用这样的方式统—异常类型 

#include <iostream>  
  
using namespace std;  
  
/* 
    假设: 当前的函数是第三方库中的函数,因此,我们无法修改源代码 
     
    函数名: void func(int i) 
    抛出异常的类型: int 
                        -1 ==》 参数异常 
                        -2 ==》 运行异常 
                        -3 ==》 超时异常 
*/  
void func(int i)  
{  
    if( i < 0 )  
    {  
        throw -1;  
    }  
      
    if( i > 100 )  
    {  
        throw -2;  
    }  
      
    if( i == 11 )  
    {  
        throw -3;  
    }  
      
    cout << "Run func..." << endl;  
}  

// 私有库函数 
void MyFunc(int i)  
{  
    try  
    {  
        func(i);  
    }  
    catch(int i)  
    {  
        switch(i)  
        {  
            case -1:  
                throw "Invalid Parameter";  // catch中重新抛出异常
                break;  
            case -2:  
                throw "Runtime Exception";  
                break;  
            case -3:  
                throw "Timeout Exception";  
                break;  
        }  
    }  
}  
  
int main(int argc, char *argv[])  
{    
    try  
    {  
        MyFunc(11);  // 既获得func函数的功能又统一异常信息
    }  
    catch(const char* cs)  
    {  
        cout << "Exception Info: " << cs << endl;  
    }  
      
    return 0;  
}  

 

3、类类型的异常

异常的类型可以是自定义类类型 ,对于类类型异常的匹配依旧是至上而下严格匹配 ,赋值兼容原则在异常匹配中依然适用 

一般而言 匹配子类异常的catch放在上部 ,匹配父类异常的catch放在下部

在工程中会定义—系列的异常类 ,每个类代表工程中可能出现的—种异常类型 ,代码复用时可能需要重解释不同的异常类 

在定义catch语句块时推荐使用引用作为参数

#include <iostream>  
  
using namespace std;  
  
class Base  
{  
};  
  
class Exception : public Base  
{  
    int m_id;  
    string m_desc;  
public:  
    Exception(int id, string desc)  
    {  
        m_id = id;  
        m_desc = desc;  
    }  
      
    int id() const  
    {  
        return m_id;  
    }  
      
    string description() const  
    {  
        return m_desc;  
    }  
};  
  
  
/* 
    假设: 当前的函数式第三方库中的函数,因此,我们无法修改源代码 
     
    函数名: void func(int i) 
    抛出异常的类型: int 
                        -1 ==》 参数异常 
                        -2 ==》 运行异常 
                        -3 ==》 超时异常 
*/  
void func(int i)  
{  
    if( i < 0 )  
    {  
        throw -1;  
    }  
      
    if( i > 100 )  
    {  
        throw -2;  
    }  
      
    if( i == 11 )  
    {  
        throw -3;  
    }  
      
    cout << "Run func..." << endl;  
}  
  
void MyFunc(int i)  
{  
    try  
    {  
        func(i);  
    }  
    catch(int i)  
    {  
        switch(i)  
        {  
            case -1:  
                throw Exception(-1, "Invalid Parameter");  
                break;  
            case -2:  
                throw Exception(-2, "Runtime Exception");  
                break;  
            case -3:  
                throw Exception(-3, "Timeout Exception");  
                break;  
        }  
    }  
}  
  
int main(int argc, char *argv[])  
{  
    try  
    {  
        MyFunc(11);  
    }  
    catch(const Exception& e)  
    {  
        cout << "Exception Info: " << endl;  
        cout << "   ID: " << e.id() << endl;  
        cout << "   Description: " << e.description() << endl;  
    }  
    catch(const Base& e)  
    {  
        cout << "catch(const Base& e)" << endl;  
    }  
      
    return 0;  
}  

 

需要注意的是抛出的异常对象并没有立即析构而是在catch块结束后才析构

4、标准库中的异常

C++标准库中提供了实用异常类族 ,标准库中的异常都是从exception类派生的 

exception类有两个主要的分支 

      - logic_error :常用于程序中的可避免逻辑错误 

      - runtime_error :常用于程序中无法避免的恶性错误

    

#include <stdexcept>  
  
using namespace std;  
  
template  
< typename T, int N >  
T& Array<T, N>::operator[] (int index)  
{  
    if( (0 <= index) && (index < N) )  
    {  
        return m_array[index];  
    }  
    else  
    {  
        throw out_of_range("T& Array<T, N>::operator[] (int index)");  
    }  
}  

5、函数异常声明

int func(int i) try
{
	return i;
} 
catch(...)
{
	return -1;
}

int func(int i, int j) throw(int)
{
	return i + j;
}

try…catch用于分隔正常功能代码异常处理代码 ,try…catch可以直接将函数实现分隔为 2 部分

函数声明和定义时可以直接指定可能抛出的异常类型 ,异常声明成为函数的—部分可以提高代码可读性 

函数异常声明是—种与编译器之间的契约 ,函数声明异常后就只能抛出声明的异常 ,抛出其它异常将导致程序运行终止 

可以直接通过异常声明定义无异常函数 

#include <iostream>  
  
using namespace std;  
  
int func(int i, int j) throw(int, char)  // 可能抛出整形和字符型异常
{  
    if( (0 < j) && (j < 10) )  
    {  
        return (i + j);  
    }  
    else  
    {  
        throw '0';  
    }  
}  
  
void test(int i) try  
{  
    cout << "func(i, i) = " << func(i, i) << endl;  
}  
catch(int j)  
{  
    cout << "Exception: " << j << endl;  
}  
catch(...)  
{  
    cout << "Exception..." << endl;  
}  
  
  
int main(int argc, char *argv[])  
{  
    test(5);  
      
    test(10);  
      
    return 0;  
}  

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值