一个例子演示了C++异常的推荐用法
再读《More Effective C++》异常部分,觉得异常应该这样用:
在throw语句里构造异常;通过引用(reference)捕获异常;禁止自定义异常的拷贝构造函数;
稍啰嗦些的结论如下:
1.总是使用引用(Reference)捕获异常!2.推荐抛出异常的做法:throw my_exception_class()3.也可以先定义一个局部异常对象,然后再抛出它: throw my_exception_instance_local4.在抛出异常的时候不要使用new,不要使用指针捕获异常;5.也不要使用传值的方式捕获异常,会造成slicing问题。6.按照上面推荐的做法,我们自定义的异常应该明确禁止拷贝构造函数!7.使用语句 throw ; 将异常再抛出!
更多内容详见《More Effective C++》条款12和条款13, 条款12解释了如何抛出异常,条款13解释了如何捕获异常!
以下例子演示了正确的做法! 会说话的代码需要你把它跑起来:)
#include <iostream>
#include <string>
#include <stdexcept>
using namespace std;
//异常类
class my_validation_error : public runtime_error
{
public:
my_validation_error(const string& msg) : runtime_error(msg)
{
cout << "my_validation_error construction" << endl;
}
virtual ~my_validation_error()
{
cout << "my_validation_error destruction" << endl;
}
//拷贝构造函数,推荐的做法是将该函数设为 private !
my_validation_error(const my_validation_error& other) : runtime_error(other)
{
cout << "my_validation_error copy construction" << endl;
}
public:
virtual const char* what() throw()
{
return "my_validation_error: ";
}
};
void SomeFunction()
{
//do something
if (true) //validation error
{
throw my_validation_error("validation error in SomeFunction!"); //推荐做法
}
}
void DoSomething()
{
try
{
SomeFunction();
}
catch (exception& ex)
{
cerr << ex.what() << endl;
}
}
void DoSomething2();
int main()
{
string comment;
{
comment = "test case 1: 在throw语句里构造对象并抛出!这是较好的做法,比起下面的做法,效率略好,省略了一次拷贝操作!";
cout << comment << endl;
DoSomething();
cout << endl;
}
{
comment = "test case 2: 抛出局部对象, C++规范要求被做为异常抛出的对象必须被复制。";
cout << comment << endl;
DoSomething2();
cout << endl;
}
comment = "结论:\n1.总是使用引用(Reference)捕获异常!\n"
"2.推荐抛出异常的做法:throw my_exception_class()\n"
"3.也可以先定义一个局部异常对象,然后再抛出它: throw my_exception_instance_local\n"
"4.在抛出异常的时候不要使用new,不要使用指针捕获异常;\n"
"5.也不要使用传值的方式捕获异常,会造成slicing问题。\n"
"6.按照上面推荐的做法,我们自定义的异常应该明确禁止拷贝构造函数!\n"
"\n更多内容详见《More Effective C++》条款12和条款13。\n"
;
cout << comment << endl;
return 0;
}
void SomeFunction2()
{
//do something
if (true) //validation error
{
my_validation_error temp("validation error in SomeFunction!");
throw temp; //不用担心,局部变量可以放在throw语句里被抛出,它会被复制!C++规范要求被做为异常抛出的对象必须被复制!
}
}
void DoSomething2()
{
try
{
SomeFunction2();
}
catch (exception& ex)
{
cerr << ex.what() << endl;
}
}
运行结果: