我最近开始使用std::exception
作为我所有异常的基类。如果不将what()
关键字放在前面,我就无法正确覆盖virtual
。如果没有virtual
关键字,它似乎总是调用基类的what()
函数std::exception
。
它让我感到困惑,因为我认为在覆盖它时(here is a post似乎证实了这一点),我永远不需要将virtual
放在函数前面。但我决定让它继续前进。
然后今天在阅读O'Reilly的“安全C ++”时,我发现作者还用虚拟关键字覆盖了what()
。他写道......
virtual const char* what() const throw () { /* stuff */ }
为什么他会覆盖某个功能并使用virtual
关键字?它只是用于我在上面引用的帖子中建议的“文档”吗?
答案 0 :(得分:3)
你做不必须将virtual关键字放在what()的覆盖之前,以便调用子类实现。也许当您发现它正在调用基类实现时,您引用的异常对象已经通过异常的异常传递进行了切片?例如,我总是通过引用捕获(根据Scott Meyers的建议),但是如果我抓住异常值并将catch声明为可能抛出的子类的超类,那么当我捕获它时,对象将被切片。换句话说,如果我声明了这个异常子类:
class my_exception : public std::exception
...
我抓住了它的一个实例:
try
{
...
throw my_exception("Some message");
}
catch (std::exception e)
{
...
}
catch块中的 e
将是一个切片对象。您应该捕获这样的异常:
try
{
...
throw my_exception("Some message");
}
catch (std::exception& e)
{
...
}