C++类(三)——不要在析构函数中抛出异常

如果类中没有写析构函数,则系统生成一个内联的不会抛出异常的的析构函数,如下:

class B {
public:
	B(){}
	inline ~B()noexcept {  //inline意味着这个函数会展开,这会造成的问题是代码会变大
		try {
                        //一些清理工作
		}
		catch (...) {
			std::terminate();
		}
	}
};

当B的析构函数执行完毕,还会调用B的成员函数的析构。比如他有个string类型的数据成员,则执行完 ~B()之后会执行~string()。

在执行完成员的析构函数之后,会调用基类的析构函数。

 

析构函数抛出异常是一个坑,例如下面的代码,我们让B类析构函数抛出异常:

class A {
public:
	~A() {
		cout << "A" << endl;
	}
};

class B :public A {
public:
	~B() {
		throw string("error");
	}
};

void test() {
	try {
		B b;
	}
	catch (...) {
		cout << "catch U evil" <<  endl;
	}
}
int main() {
	test();

	return 0;	
}

对于析构函数,如果我们不指出来析构函数的声明类型,则析构函数默认的是 noexcept类型的

class B :public A {
public:
	~B() noexcept {
		throw string("error");
	}
};

因此析构函数抛出异常会导致程序崩溃

 

如果你就是想让析构函数抛出异常,可以这样设置吗?

~B() noexcept(false) {
        throw string("error");
}

运行一下修改后的代码,似乎没有问题

class A {
public:
	~A() {
		cout << "hi A" << endl;
	}
};

class B :public A {
public:
	~B() {
		cout << "hi B" << endl;
	}
};
class C :public B {
public:
	~C() noexcept(false) {
		throw string("error");
	}
};

void test() {
	try {
		C c;
	}
	catch (...) {
		cout << "catch U evil" <<  endl;
	}
}

答案是——不可以!!!!!

假如B类中也抛出一个异常

class A {
public:
	~A() {
		cout << "hi A" << endl;
	}
};

class B :public A {
public:
	~B() noexcept(false) {
		cout << "hi B" << endl;
		throw string("error");
	}
};
class C :public B {
public:
	~C() noexcept(false) {
		throw string("error");
	}
};

void test() {
	try {
		C c;
	}
	catch (...) {
		cout << "catch U evil" <<  endl;
	}
}

      

执行一次try,C和B两个类都抛出了异常,C++在一次try时只能处理一个异常

 

如果小杠精说:我保证写的基类和派生类中只有一个异常,总可以了吧?答案依然是——不可以

class A {
public:
	~A() {
		cout << "hi A" << endl;
	}
};

class B :public A {
public:
	~B() {
		cout << "hi B" << endl;
	}
};
class C :public B {
public:
	~C() noexcept(false) {
		throw string("error");
	}
};

void test() {
	try {
		C b;
		C c;
	}
	catch (...) {
		cout << "catch U evil" <<  endl;
	}
}

还是因为只能处理一个异常。

这就是为什么析构函数默认是noexcept的原因

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值