3

我最近开始将std::exception所有异常用作基类。what()如果不将virtual关键字放在它前面,我将无法正确覆盖。如果没有virtual关键字,它似乎总是调用what()基类的函数std::exception.

这让我有点困惑,因为我认为virtual在覆盖函数时永远不需要放在函数前面(这是一篇似乎证实了这一点的帖子)。但我决定放手,继续前进。

然后今天在阅读 O'Reilly 的“Safe C++”时,我发现作者也what()使用了 virtual 关键字。他写了...

virtual const char* what() const throw () { /* stuff */ }

为什么他要覆盖一个函数并使用virtual关键字?正如我在上面引用的帖子中所建议的那样,它只是为了“文档”吗?

4

1 回答 1

3

为了调用子类实现,您不必将virtual 关键字放在覆盖 what() 的前面。也许当您发现它正在调用基类实现时,您引用的异常对象已通过异常的不适当传递而被切片?例如,我总是通过引用捕获(根据 Scott Meyers 的建议),但是如果我通过异常值捕获并将捕获声明为可能被抛出的子类的超类,那么当我捕获它时对象将被切片。换句话说,如果我声明了这个异常子类:

class my_exception : public std::exception
...

我像这样抓住了它的一个实例:

try
{
    ...
    throw my_exception("Some message");
}
catch (std::exception e)
{
    ...
}

e在 catch 块中将是一个切片对象。您应该捕获这样的异常:

try
{
    ...
    throw my_exception("Some message");
}
catch (std::exception& e)
{
    ...
}
于 2012-11-07T11:21:44.767 回答