如何正确使用C++中的异常机制?

前言

在程序运行的时候有时会遇到错误导致程序崩溃无法运行下去。比如申请过多的内存,进行除零的操作。因此最好以一种受控的方法来运行代码,这里就用到了异常处理机制。
异常处理机制可以避免程序终止,而是可以返回一个异常的值来告诉开发人员是哪里发生了错误,以更好地定位错误。

异常处理

在C++中,当异常发生时,会将程序的控制权从这一部分传到另一部分上。

  1. 引发异常
  2. 使用处理程序捕捉异常
  3. 使用try块
    程序是通过excetion handler作为异常处理程序来捕获异常,这个异常处理程序就要位于要处理问题的程序块中,并使用catch来捕获。
    try标识可能存在异常被激活的代码块,一般来说它的后面会跟上一个或多个catch块,如果没有,那么这个try则会出错。就好比没有else的if出现在程序中。
    或者当我们想要抛出一个异常,来看程序会作出怎么样的应答,就可以使用throw来抛出一个异常。
double hmean(double a, double b) {
	if (a == -b)
		throw "bad hmean() arguments : a = -b  not allowed!!!";
	return 2.0 * a * b / (a + b);
}


int main() {
	double x = 1, y = -1, z;
	try {
		z = hmean(x, y);
	}
	catch (const char* s) {
		std::cout << s << std::endl;
		
	}
	std::cout << "the result of hmean function is :  " << z << std::endl;
	return 0;
}

栈解退

假设try没有直接调用引发异常的函数,而是调用了引发异常的函数所调用的函数,那么程序的流程就会从引发异常的函数跳到包含try和处理程序所在的函数中。
现在假设函数由于出现异常而终止,那么程序就需要释放栈中的内存,但不会再释放栈的第一个返回地址后就停止,而是继续释放,不断返回被调用的函数地址,直到找到一个try块。

class bad_hmean
{
private:
	double v1;
	double v2;

public:
	bad_hmean(double a = 0, double b = 0) : v1(a), v2(b) {}
	void mesg();
};

inline void bad_hmean::mesg(){
	std::cout << "gmean" << v1 << "   " << v2 << "invalid arguments: a= -b" << std::endl;
}

class bad_gmean
{
public:
	double v1;
	double v2;
	bad_gmean(double a = 0, double b = 0) : v1(a), v2(b) {}
	const char* mesg();
};

inline const char*  bad_gmean::mesg() {
	return "gmen() arguments should be >= 0";
}

double hmean(double a, double b) {
	if (a == -b)
		throw bad_hmean(a, b);
	return 2.0 * a * b / (a + b);
}

double gmean(double a, double b) {
	if (a < 0 || b < 0)
		throw bad_gmean(a, b);
	return std::sqrt(a * b);
}

int main() {
	double x = 5, y = -1, z;
	try {
		z = hmean(x, y);
		std::cout << "harmonic mean of " << x << "   " << y << "is " << z << std::endl;
		std::cout << "geometric mean of " << x << "   " << y << "is " << gmean(x, y) << std::endl;
	}
	catch (bad_hmean &bg) {
		bg.mesg();
		std::cout << "try again!!!" << std::endl;
	}
	catch (bad_gmean &hg) {
		std::cout << hg.mesg() << std::endl;
		std::cout << "value used ::  " << hg.v1 << "   " << hg.v2 << std::endl;
	}
	std::cout << "the result is   " << z << std::endl;
	return 0;
}

exception类

在C++中定义了exception类,它里面有一个名为what()的虚拟成员函数,以一个字符串返回。此外,exception可作为其他异常类型的基类,如:

  • length_error 字符串长度超过了最大允许长度
  • out_of_bounds 索引错误
  • invalid_argument 无效的入参
  • bad_alloc 申请内存发生的异常

最后

异常处理对于项目来说极为重要,因为它可以避免程序的崩溃,当发生错误的时候可以让用户重新输入来让程序继续运行下去。一方面这也增加了编程的工作量,增大程序,降低运行速度,另一方面,这也可以使开发人员了解是什么异常被引发的,以及知道它们背后的原因,发生的时间等等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值