在阅读异常的同时,我知道抛出对象时,对象总是基于静态类型信息构造的。如果发生异常,我们如何抛出子类对象?以下是《更有效的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实际上是指SpecialWidget
,您的编译器无需担心;他们只关心rw的静态类型。
This解释了为什么会发生这种情况,但没有提供解决问题的方法。
答案 0 :(得分:5)
您需要添加
virtual void throwYourself() = 0;
到Widget类。并使用
void SpecialWidget::throwYourself() override { throw *this; }
然后,您可以在基本指针对象上调用throwYourself()。这是否是一个好的设计是另一个我没有答案的问题。
答案 1 :(得分:0)
您不能,这对于编译器而言非常重要。必须确保throw
和catch
匹配。 throw
的限制意味着编译器至少知道抛出对象的静态类型。
现在,您可能会想到,“但是catch
确实支持RTTI”。有一个简单的解释。 catch (Foo&)
需要捕获引发的类型和数量有限的基类。但是,如果throw
需要在运行时处理派生类,则存在无限数量的可能派生类。