抛出子类对象作为异常

时间:2019-07-15 15:44:20

标签: c++ c++11

在阅读异常的同时,我知道抛出对象时,对象总是基于静态类型信息构造的。如果发生异常,我们如何抛出子类对象?以下是《更有效的C ++》书中的几行内容:

class Widget{...};

class SpecialWidget: public Widget {...};

void passAndThrowWidget()
{
    SpecialWidget localSpecialWidget;
    ...
    Widget& rw = localSpecialWidget;
    throw rw; // this throws an exception of type widget!
}
     

即使rw引用SpecialWidget,也会引发Widget异常。那是因为rw的静态类型是Widget,而不是Special-Widget。 rw实际上是指S pecialWidget,您的编译器无需担心;他们只关心rw的静态类型。

This解释了为什么会发生这种情况,但没有提供解决问题的方法。

2 个答案:

答案 0 :(得分:5)

您需要添加

virtual void throwYourself() = 0;

到Widget类。并使用

void SpecialWidget::throwYourself() override { throw *this; }

然后,您可以在基本指针对象上调用throwYourself()。这是否是一个好的设计是另一个我没有答案的问题。

答案 1 :(得分:0)

您不能,这对于编译器而言非常重要。必须确保throwcatch匹配。 throw的限制意味着编译器至少知道抛出对象的静态类型。

现在,您可能会想到,“但是catch确实支持RTTI”。有一个简单的解释。 catch (Foo&)需要捕获引发的类型和数量有限的基类。但是,如果throw需要在运行时处理派生类,则存在无限数量的可能派生类。