C++——C++异常处理

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常用于程序中无法避免的恶性错误

相关推荐
FRing0326 分钟前
JavaScript入门到精通二十六(变量提升、函数剩余参数、展开运算符、ES6箭头函数)
开发语言·前端·javascript·es6·箭头函数
云深麋鹿29 分钟前
C++ | 基于红黑树实现mymap与myset
开发语言·c++
weixin_417396831 小时前
桌面云终端PXE启动失败怎么排查?从DHCP Option到镜像下发
开发语言·前端·php·技术·酒店·综合布线·弱电
某不知名網友2 小时前
ROS2进阶:服务通信、自定义SRV接口、参数服务器与基于服务的参数通信详解
java·开发语言·microsoft
傲世仙尊2 小时前
string增删查改-insert-erase-replace与find加substr组合技
c++
java_nnnn2 小时前
LeetCode刷题滑动窗口(水果成篮+找到字符串中所有字母的异位词)Java
java·开发语言·leetcode
qetfw2 小时前
Bash 字符串处理:参数展开、序列与脚本执行方式
linux·开发语言·chrome·bash
小羊没烦恼!2 小时前
异步编程:线程概述及使用
java·开发语言·mysql·算法·c#
学Linux的语莫3 小时前
python中类的常见写法
开发语言·python·状态模式
需要8263 小时前
容器化 Java:镜像瘦身与 JVM 容器感知(cgroup)
java·开发语言·jvm