---- 整理自狄泰软件唐佐林老师课程
1. C++异常处理
1.1 try catch内容一
- C++内置了异常处理的语法元素 try catch
- try语句用于处理正常代码逻辑
- catch语句用于处理异常情况
- try语句中的异常由对应的catch语句处理
1.2 C++通过throw语句抛出异常信息
1.3 C++异常处理分析
- throw抛出的异常必须被 catch 处理
- 当前函数 能够处理异常,程序继续往下执行
- 当前函数 无法处理异常,则函数停止运行,并返回
- 未被处理的异常 会顺着 函数调用栈 向上传播,直到被处理为止,否则程序将停止执行
1.4 编程实验:C++异常处理初探
#include <iostream>
#include <string>
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;
}
1.5 try catch内容二
- 同一个try语句 可以跟上 多个catch语句
- catch语句可以定义 具体处理的异常类型
- 不同类型的异常由 不同的catch语句 负责处理
- try语句中可以抛出 任何类型 的异常
- catch(…) 用于处理 所有类型的异常(只能放在最后)
- 任何异常都 只能被捕获(catch) 一次
1.6 异常处理的匹配规则
- 异常处理匹配时,不进行任何的类型转换
1.7 编程实验:异常类型匹配
#include <iostream>
#include <string>
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;
}
}
void Demo2()
{
throw string("D.T.Software");
}
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;
}
- 字符串相关:
1.8 catch语句块中可以抛出异常
- 问题:为什么要在catch中 重新 抛出异常?
- catch中捕获的异常可以被重新解释后抛出
- 工程开发中使用这样的方式统一异常类型,如下:
1.9 实验:异常的重新解释
- 直接调用第三方库中的函数,得到的异常是 -3,然后去找文档或者是代码中注释或者是分析代码,知道是超时异常,不够直观,效率较低:
- 改进后:
#include <iostream>
#include <string>
using namespace std;
void Demo()
{
try
{
try
{
throw 'c';
}
catch(int i)
{
cout << "Inner: catch(int i)" << endl;
throw i;
}
catch(...)
{
cout << "Inner: catch(...)" << endl;
throw;
}
}
catch(...)
{
cout << "Outer: catch(...)" << endl;
}
}
/*
假设: 当前的函数式第三方库中的函数,因此,我们无法修改源代码
函数名: 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";
break;
case -2:
throw "Runtime Exception";
break;
case -3:
throw "Timeout Exception";
break;
}
}
}
int main(int argc, char *argv[])
{
// Demo();
try
{
MyFunc(11);
}
catch(const char* cs)
{
cout << "Exception Info: " << cs << endl;
}
return 0;
}
1.10 异常的类型可以是自定义类类型
- 对于类类型异常的匹配依旧是至上而下严格匹配
- 赋值兼容性原则在异常匹配中依然适用
- 一般而言:
- 匹配子类异常的catch放在上部
- 匹配父类异常的catch放在下部
- 在工程开发中会定义一系列的异常类
- 每个类代表工程中可能出现的一种异常类型
- 代码复用时可能需要重新解释不同的异常类
- 在定义catch语句块时推荐使用引用作为参数
1.11 编程实验:类类型的异常
#include <iostream>
#include <string>
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;
}
1.12 C++标准库中提供了实用异常类族
- 标准库中的异常都是从 exception类 派生的
- exception类有两个主要的分支:
- logic_error:常用语程序中的可避免逻辑错误
- runtime_error:常用语程序中无法避免的恶性错误
1.13 标准库中的异常
2. 小结
- C++中直接支持异常处理的概念
- try catch是C++中异常处理的专用语句
- try语句处理正常代码逻辑,catch语句处理异常情况
- 同一个try语句可以跟上多个catch语句
- 异常处理必须严格匹配,不尽进行任何的类型转换
- catch语句块可以抛出异常