处理错误, 特别是在library中, 一直是一件麻烦的事情.
library知道错误发生了, user知道如何处理这种错误, 但是问题是,
library的作者不知道 user 想如何处理错误的. 通过返回值, 抛异常, 直接abort?
一般来说, 抛异常是最常用的一种方法, 但是某些情况下并不合适. 例如当发生错误是可以预计的, 并不是一个"异常事件"时, 或者简单的就是不能使用异常.
一种更好的方式是, library将这个问题留给user, 让user自己决定错误发生时应该如何处理.也就是一种policy的设计.
例如;假设有一个class utility, 其中有一个run方法可能发生错误,
class utility
{
public:
void run()
{
if(...)
error(); //如何处理??
}
};
user 如何干预错误发生时的处理呢?
我们可以提供一个模板成员函数
template<class Handler>
void run( Handler h)
{
if(...)
h(); //调用用户提供的函数
}
或者给用户提供一个重载的函数版本提供默认的实现:
void default_error_handler()
{
throw "Ooops..";
}
void run()
{
//调用成员模板
run ( default_error_handler);
}
这样user的使用就可以:
try
{
utility u;
u.run(); //默认, 失败抛出异常
}
catch(const char * sz)
{
...
}
或者
void empty_error_handler()
{
}
utility u;
u.run( empty_error_handler ); //装糊涂
或者
struct set_error_flag
{
set_error_flag(bool* b)
: flags(b)
{
}
void operator()()
{
*flags_ = !(*flags_); //设置标志位
}
bool * flags_;
}
utility u;
bool err = false;
u.run( set_error_flag(&err)); //设置标志位
if(error)
{
// ......
}
甚至更多方式.
另外一种方式就是定义一个interface, 来几个虚函数.例如:
class error_handler
{
virtual void on_error() = 0;
};
这种方式基本上最是"纯OO"的, 也是"面向对象的", 在C++中也最不好用, 大部分情况下可以不须考虑这种方式.