1.C++内置了异常处理的语法元素 try...catch...
try语句处理正常代码逻辑
catch语句处理异常情况
try语句的异常由对应的catch语句处理
C++通过throw语句抛出异常信息
2.C++异常处理分析
throw抛出的异常必须被catch处理
(1)当前函数能够处理异常,程序继续向下执行
(2)当前函数无法处理异常,则函数停止执行并返回
#include<iostream>
#include<string>
using namespace std;
double divide(double a, double b) {
const double delta = 0.0000000000001;
double ret = 0;
if (!((-delta < b) && (b < delta))) {
ret = a / b;
}
else {
throw 0;
}
return ret;
}
int main() {
try {
double r = divide(1, 1);
cout << "r=" << r << endl;
}
catch (...) {
cout << "除数为0" << endl;
}
return 0;
}
3.同一个try语句可以跟上多个catch语句
(1)catch语句可以定义具体处理的异常类型
(2)不同类型的异常由不同的catch语句负责处理,类型必须严格匹配,不进行任何的类型转换
(3)try语句中可以抛出任何类型的异常
(4)catch(...)用于处理所有类型的异常
(5)任何异常都只能被捕获(catch)一次
#include<iostream>
#include<string>
using namespace std;
void demo1() {
try {
throw 1;
}
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 (int c) {
cout << "catch (int c)" << endl;
}
catch (...) { //只能放在最后
}
}
int main() {
demo1(); //catch (int c)
return 0;
}
4.catch语句块中可以抛出异常
#include<iostream>
#include<string>
using namespace std;
int main() {
try {
throw 0;
}
catch (int i) {
// 专门捕获 int 类型的异常,并将抛出的异常值赋值给变量 i。
//程序在执行 throw i 时,会直接跳出当前 catch 块,不会回头执行同一个 try 后的其他 catch;
throw i; //i=0,执行 throw i,再次抛出 int 类型异常(值为 0),但没人处理
}
catch (...) {
throw;
}
return 0;
}
运行结果:

#include<iostream>
#include<string>
using namespace std;
int main() {
try {
try {
throw 0;
}
catch (int i) {
cout << "in:catch (int i)" << endl;
// 专门捕获 int 类型的异常,并将抛出的异常值赋值给变量 i。
//程序在执行 throw i 时,会直接跳出当前 catch 块,不会回头执行同一个 try 后的其他 catch;
throw i; //i=0,执行 throw i,再次抛出 int 类型异常(值为 0),但没人处理
}
catch (...) {
cout << "in:catch (...) " << endl;
throw;
}
}
catch (...) {
cout << "out:catch (...) " << endl;
}
return 0;
}
运行结果:
in:catch (int i)
out:catch (...)
示例:
#include<iostream>
#include<string>
using namespace std;
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 "1";
break;
case -2:
throw "2";
break;
case -3:
throw "3";
break;
}
}
}
int main() {
try {
Myfunc(11);
}
catch (const char* cs) {
cout << cs << endl;
}
return 0;
}
运行结果:3
5.异常的类型可以是自定义类型
(1)对于类类型异常的匹配依旧是自上而下严格匹配
(2)一般匹配子类异常的catch放在上部;匹配父类异常的catch放在下部
#include<iostream>
#include<string>
using namespace std;
class Base {
};
class Exception :public Base {
int m_id; //异常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) {
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,"1");
break;
case -2:
throw Exception(-2, "2");
break;
case -3:
throw Exception(-3, "3");
break;
}
}
}
int main() {
try {
Myfunc(11);
}
catch (const Exception& e) {
cout << e.id() << endl;
cout << e.description() << endl;
}
return 0;
}
运行结果:
-3
3
若在子类的catch分支前加上父类的catch分支:
#include<iostream>
#include<string>
using namespace std;
class Base {
};
class Exception :public Base {
int m_id; //异常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) {
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,"1");
break;
case -2:
throw Exception(-2, "2");
break;
case -3:
throw Exception(-3, "3");
break;
}
}
}
int main() {
try {
Myfunc(11);
}
catch (const Base& b) {
cout << "catch (const Base& b)" << endl;
}
catch (const Exception& e) {
cout << e.id() << endl;
cout << e.description() << endl;
}
return 0;
}
运行结果:catch (const Base& b)
6.C++标准库中提供了实用异常类族,标准库中的异常都是从exception类派生的,exception类有两个主要的分支
(1)logic_error常用于程序中的可避免逻辑错误
(2)runtime_error常用于程序中无法避免的恶性错误