[C++]C++异常处理try、throw、catch

本文详细介绍了C++中的异常处理机制,包括abort函数的局限性、try-catch结构的使用方法(如抛出异常的不同写法和捕获异常的类型/返回值/其他异常处理),以及故障码在程序控制中的优势。
摘要由CSDN通过智能技术生成

1.引子

程序在运行时,总是会遇到一些错误,这些错误或者是导致程序无法运行,例如操作空指针,或是不符合正常运行的规律,例如除以0。

因此,在C++程序当中就必须添加对应异常处理机制,在检测到指定的程序异常时,为保证程序正常运行,需要跳转至异常处理程序当中。

常规的错误处理有以下解决方案:

2.abort()

在遇到错误时,可以调用abort函数

abort函数位于标准库的头文件cstdlib当中,它会向标准错误流发送一个程序异常终止消息,然后终止程序。

int main() {
	abort();
    return 0;
}

当然,这种方式实际上并不灵活,abort的调用会直接终止程序,并不是我们所想要的结果。通常我们都会建立故障诊断机制,所以abort的使用频率比较低。

3.try throw catch

C++自带有异常处理机制,提供了将控制权从程序的一个部分转移到另一个部分的途径,这种对异常的处理方法包含三部分:

try:标识其中特定的异常可能被激活的代码块。

throw:当出现异常时抛出异常,跳转至处理部分。

catch:捕获异常,针对不同的异常类型采取对应的措施

基本写法为:

try{
    //Error e("error!");
	//throw e;
	throw 1;
	//throw 1.5;
	//throw Error ("error!");
}
catch (double){

}
catch (int){

}
catch (Error& e){

}

其中,抛出异常和捕获异常有多种写法,可以适用于不同的情况。

3.1.抛出异常

异常抛出有以下几种写法:

直接抛出数值,会根据值的类型自动做隐式转换,例如int和double,这种用法弊端比较大,一般不怎么使用:

throw 1;    // 相当于throw (int)1;
throw 1.5;     // 相当于throw (double)1.5;

构造并抛出异常值,如果异常被封装为类,则会用构造函数对异常进行构造。当然也可以先构造一个类出来,然后将这个类抛出,两种做法是一样的。

class Error{
	public:
		Error(const char* message) 
			: m_message(message)
		{ };
private:
		string m_message;
};

throw Error("error!");    // 1.调用构造函数后抛出

Error e("error!");
throw e;    // 2.抛出构造后的值

3.2.捕获异常

异常捕获有以下几种写法:

类型捕获,依据throw抛出的类型进行选择最终进入哪一个catch模块,多个catch连成一片类似于else if,只不过catch检测的是类型。如果没有抛出异常,那么不会进入任何一个catch块当中。

catch (int){ 
}
catch (double){ 
}
catch (Error){ 
}

类型+返回值捕获,返回的不只是类型,实际上还隐藏了返回值,可以自定义返回值的名称将其显式表示,并将其运用到catch模块当中。

catch (Error& error){ 
 cout << error << endl;
}

捕获其它异常,"..."这种写法相当于else,任何其它类型的异常都会被该catch捕获。

同理,如果没有写catch(...)就相当于没有写else,那么当程序因为异常抛出,但是没有找到对应类型的异常时,则不会执行任何catch内的操作。

catch (...){
}

3.3.嵌套

多个异常模块可以嵌套使用,但在任意位置抛出异常时,程序会逐级选择catch模块,直到找到对应的catch块或者跳出所有嵌套的try块为止,中间其它try当中的内容,都会被忽略。

例如下面的程序:

输出double异常时,跳转至catch(double)中,继续运行外层try当中的内容,从而输出1、2、3、4、6;

输出int异常时,跳转至catch(int)中,无视了外层try块剩下的内容,从而输出1、2、5 2、6;

int main() {

	try {
		std::cout << "1..." << endl;
		try {
			std::cout << "2..." << endl;
			//double error = 2;    //如果抛出double,则输出1、2、3、4、6
			int error = 2;    //如果抛出int,则输出1、2、5 2、6
			throw error;    
		}
		catch (double ) {
			std::cout << "3..." << endl;
		}
		std::cout << "4..." << endl;
	}
	catch (int& error) {
		std::cout << "5..." << error << endl;
	}
    std::cout << "6..." << error << endl;
	return 0;
}

4.故障码

虽然这一节主要想讲的是try throw catch,但实际上这种异常解决方案用的还是不算多,最常使用的依然是故障码。

故障码不是啥新鲜的东西,设置一个全局或较高层级的故障类,用以记录故障的类型。在每个程序模块运行时对故障进行检测,同时在运行过程中出现异常时对故障进行对应的填充。

在C语言当中,只能用结构体指针的方式进行传输,不够方便,而C++以类的形式进行封装更有利于这种方式的异常处理。

其伪代码如下所示:

Error e;

if(e == null){
    ...
    if(){
        e = error;
    }
}
...

故障码有个优势,那就是相比于try catch的结构,可以比较容易地对程序进行控制,对于异常的处理更加的精细化,因此很多时候用的比较多的反而是这种解决方案。

  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FL1768317420

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值