一、C++ 异常处理
1.1 要点归纳
C++ 异常处理涉及到三个关键字:try、catch、throw。在c++程序中,任何需要检测异常的语句,都必须在try 语句块中执行,异常必须由紧跟着try语句后面的catch语句来捕获并处理,因此try与catch总是结合使用。
语法如下:
throw [表达式];
try
{
//try语句块
}
catch(类型 n 参数n)
{
//异常处理语句
}
1.2 异常类型
C++ 的异常类型可以分为基本类型和聚合类型:
- 基本类型:int、char、float
- 聚合类型:指针、数组、字符串、结构体
C++ 语言本身以及标准库中的函数抛出的异常,都是 exception 类或其子类的异常。也就是说,抛出异常时,会创建一个 exception 类或其子类的对象。
try{
//可能抛出异常的语句
}catch(exception &e){
//处理异常的语句
}
之所以使用引用,是为了提高效率。如果不使用引用,就要经历一次对象拷贝(要调用拷贝构造函数)的过程。
定义新的异常:
通过继承和重载 exception 类来定义新的异常。
1.3 throw用作异常规范
(异常规范是 C++98 新增的一项功能,但是后来的 C++11 已经将它抛弃了,不再建议使用。)
throw 关键字除了可以用在函数体中抛出异常,还可以用在函数头和函数体之间,指明当前函数能够抛出的异常类型,这称为异常规范(Exception specification)
(1)声明了一个名为 func 的函数,它的返回值类型为 double,有一个 char 类型的参数,并且只能抛出 int 类型的异常。如果抛出其他类型的异常,try 将无法捕获,只能终止程序:
double func (char param) throw (int);
(2)函数可抛出多种类型的异常,用逗号隔开:
double func (char param) throw (int, char, exception);
(3)如果函数不会抛出任何异常,那么( )
中什么也不写:
double func (char param) throw ();
如此,func() 函数就不能抛出任何类型的异常了,即使抛出了,try 也检测不到。
1.4 异常层次
- 同一个try语句块可以对应多个catch语句块,catch语句块可以定义具体处理的异常类型,不同的类型的异常由不同的catch语句块处理;
- try语句块可以抛出任何类型的异常,catch(...)用于处理所有类型的异常,任何异常都只能被捕获一次;
- throw抛出的异常必须被catch处理,如果当前函数能够处理异常,继续执行;如果当前函数不能处理异常,函数停止执行并返回;
- 未被处理的异常会顺着函数调用栈向上传递,直到被处理为止,否则程序将停止执行。
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;
}
二、C++ 异常使用案例
2.1 普通类型异常
division() 在 try 块中被调用,它抛出的异常会被 try 检测到,进而被 catch 捕获。
#include <iostream>
using namespace std;
double division(int a, int b)
{
if (b == 0)
{
throw "Division by zero condition!";
}
return (a / b);
}
int main() {
int x = 50;
int y = 0;
double z = 0;
try {
z = division(x, y);
cout << z << endl;
}
catch (const char* msg) {
cerr << msg << endl;
}
return 0;
}
抛出了一个类型为 const char* 的异常,因此,当捕获该异常时,我们必须在 catch 块中使用 const char*
若发生异常后,程序的执行流会沿着函数的调用链往前回退,直到遇见 try 才停止。
2.2 自定义新的异常
#include <iostream>
using namespace std;
struct MyException : public exception
{
const char* what() const throw ()
{
return "C++ Exception";
}
};
int main() {
try
{
throw MyException();
}
catch (MyException & e)
{
std::cout << e.what() << std::endl;
}
catch (std::exception & e)
{
//其他的错误
}
return 0;
}
what() 是异常类提供的一个公共方法,它已被所有子异常类重载 。
2.3 标准异常
#include <iostream>
#include <stdexcept>
using namespace std;
int main(int argc, char *argv[])
{
int array[5] = {0};
for(int i = 0; i < 5; i++)
{
array[i] = i;
}
try
{
for(int i = 0; i < 10; i++)
{
if(i >= 5)
{
throw out_of_range("out of range");
}
else
{
cout << array[i] <<endl;
}
}
}
catch(const out_of_range& e)
{
cout << e.what() << endl;
}
return 0;
}
参考文献:
【1】C++ 异常处理: https://www.runoob.com/cplusplus/cpp-exceptions-handling.html
【2】C++异常处理入门,C++ try catch入门:http://c.biancheng.net/view/2330.html
【3】C++语言学习(十八)——异常处理: https://blog.51cto.com/9291927/2164586