异常需要虚拟继承吗?

发布于 2024-11-05 01:02:57 字数 180 浏览 2 评论 0原文

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

但是如果我不使用多重继承怎么办? 是否需要虚拟继承?

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

我尝试搜索我曾经看到过的参考页面,但似乎找不到。

I understand the need for virtual inheritance when using multiple inheritance -- it solves the Dreaded Diamond Problem.

But what if I'm not using multiple inheritance? Is there a need for virtual inheritance at all?

I seem to recall hearing that it was important for exceptions (throw a derived class, catch by base class reference). But shouldn't virtual destructors be sufficient for that?

I've tried searching for the reference page I once saw on this, but I can't seem to find it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

浊酒尽余欢 2024-11-12 01:02:58

您可能正在考虑这个 Boost.Exception 指南,为了完整起见,我将在此处复制该内容:


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

从其他异常类型派生时,异常类型应使用虚拟继承。这一见解源自安德鲁·科尼格 (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; }
    }

上面的程序输出“哎哟!”因为到 std::exception 的转换是不明确的。

在异常处理的上下文中,虚拟继承引入的开销始终可以忽略不计。请注意,虚拟基由最派生类型的构造函数直接初始化(在发生异常的情况下,传递给 throw 语句的类型)。但是,当 boost::exception ,因为它使异常类型成为简单的结构没有成员(没有任何需要初始化的内容。) 将异常类型视为简单的语义标签

You're probably thinking about this Boost.Exception guideline, which I'll copy here for completeness:


Using Virtual Inheritance in Exception Types

Exception types should use virtual inheritance when deriving from other exception types. This insight is due to Andrew Koenig. Using virtual inheritance prevents ambiguity problems in the exception handler:

#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; }
    }

The program above outputs "whoops!" because the conversion to std::exception is ambiguous.

The overhead introduced by virtual inheritance is always negligible in the context of exception handling. Note that virtual bases are initialized directly by the constructor of the most-derived-type (the type passed to the throw statement, in case of exceptions.) However, typically this detail is of no concern when boost::exception is used, because it enables exception types to be trivial structs with no members (there's nothing to initialize.) See Exception Types as Simple Semantic Tags.

夏九 2024-11-12 01:02:58

是的,如果您的异常类涉及多重继承。

Yes if your exception classes involve multiple inheritance.

山田美奈子 2024-11-12 01:02:58

虚拟继承的唯一成本是 vtable,但成本并不高。使用虚拟继承意味着,当人们从各种事物继承之后,双菱形问题就不会意外地出现。这只是意味着你的班级将成为一个很好的基础班。

The only cost of virtual inheritance is the vtable which is not much of a cost. Using virtual inheritance means that later after people inherit from various things that the double diamond problem won't unexpectedly rear their ugly head. It just means that your class will make a good base class.

夜雨飘雪 2024-11-12 01:02:58

不,除了解决钻石问题之外不需要它。你一定是在想象一些事情!

No, it isn't needed except to resolve the diamond problem. You must be imagining things!

失眠症患者 2024-11-12 01:02:58

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

但是如果我不使用多重继承怎么办?

问题(主要是修辞性的):
您怎么知道 MI 永远不会被使用?

回答:你不可能知道这一点。 (直到你证明你做到了。)

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

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

答:不是的。

I understand the need for virtual inheritance when using multiple inheritance -- it solves the Dreaded Diamond Problem.

But what if I'm not using multiple inheritance?

Question (mostly rhetorical):
How would you know that MI won't ever be used?

Answer: You can't know that. (Until you prove you do.)

I seem to recall hearing that it was important for exceptions (throw a derived class, catch by base class reference). But shouldn't virtual destructors be sufficient for that?

Question (rhetorical):
Why would a virtual destructor be necessary here?

Answer: It isn't.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文