异常是否需要虚拟继承?

Is Virtual Inheritance necessary for Exceptions?

本文关键字:继承 虚拟 是否 异常      更新时间:2023-10-16

我理解在使用多重继承时需要虚拟继承——它解决了可怕的菱形问题。

但是如果我没有使用多重继承呢?是否需要虚拟继承?

我似乎记得听说过它对异常很重要(抛出派生类,通过基类引用捕获)。但是,虚析构函数不就足够了吗?

我试着搜索我曾经在这个上面看到的参考页面,但是我似乎找不到它。

您可能正在考虑这个Boost。异常指南,为了完整起见,我将复制到这里:


在异常类型中使用虚拟继承

当从其他异常类型派生时,

异常类型应该使用虚拟继承。这是Andrew Koenig的见解。使用虚拟继承可以防止异常处理程序中的歧义问题:

#include <iostream>
struct my_exc1 : std::exception { char const* what() const throw(); };
struct my_exc2 : std::exception { char const* what() const throw(); };
struct your_exc3 : my_exc1, my_exc2 {};
int
main()
    {
    try { throw your_exc3(); }
    catch(std::exception const& e) {}
    catch(...) { std::cout << "whoops!" << std::endl; }
    }

以上程序输出"whoops!"因为转换到std::exception是有歧义的。

在异常处理上下文中,虚拟继承带来的开销总是可以忽略不计的。请注意,虚基是由派生最多的类型的构造函数直接初始化的(在发生异常的情况下,传递给throw语句的类型)。然而,当使用boost::exception时,通常不关心这个细节,因为它使异常类型成为没有成员的平凡结构(没有什么可初始化的)。参见异常类型作为简单语义标记

如果你的异常类涉及多重继承,

虚拟继承的唯一代价是虚函数表,这不是很大的代价。使用虚拟继承意味着以后人们从各种事物继承后,双钻石问题不会意外地出现。这只是意味着你的类将成为一个很好的基类。

不需要,除非是为了解决钻石问题。你一定是在胡思乱想!

我理解在使用多重继承时需要虚拟继承——它解决了可怕的钻石问题。

但是如果我没有使用多重继承呢?

问题(主要是反问句):你怎么知道MI永远不会被使用?

答案:你不可能知道。(直到你证明你知道。)

我似乎记得听说过它对异常很重要(抛出派生类,通过基类引用捕获)。但是,虚析构函数不就足够了吗?

问题(修辞):为什么这里需要虚析构函数?

答案:不是。