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

这让我有点困惑,因为我认为在覆盖函数时永远不需要将 virtual 放在函数前面(而 here is a post 似乎证实了这一点)。但我决定放手继续前进。

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

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

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

最佳答案

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

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)
{
    ...
}

关于c++ - 为什么人们把 virtual 关键字放在 std::exception::what() 前面?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13257932/

10-13 08:23