c++ - 为什么人们将 virtual 关键字放在 std::exception::what() 前面?

标签 c++ inheritance virtual

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

这让我有点困惑,因为我认为在覆盖函数时永远不需要将 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 block 中的

e 将是一个切片对象。你应该捕获这样的异常:

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

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

相关文章:

c++ - 单链表段错误问题

c++ - MSVC++ 2010 Express 链接器错误 LNK2005

linux - 在 Linux 中创建一个虚拟文件

C++:如何从外部调用父类函数

C++重载虚拟+运算符

c++ - 如何检测在 Windows 窗体消息框中按下了哪个按钮?

java - 是否可以通过方法的返回值将数组从 Java 返回到 C++?

Java 继承和访问修饰符

javascript - 如何通过继承向现有功能添加功能

c++ - 将数字附加到枚举以获得其他枚举