【问题标题】:Throwing a child class object as exception将子类对象作为异常抛出
【发布时间】:2019-07-15 15:44:20
【问题描述】:

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

class Widget{...};

class SpecialWidget: public Widget {...};

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

这里会抛出一个 Widget 异常,即使 rw 引用了 SpecialWidget。那是因为 rw 的静态类型是 Widget,而不是 Special-Widget。 rw 实际上指的是 SpecialWidget 与您的编译器无关;他们只关心 rw 的静态类型。

This 解释了它发生的原因,但没有提供问题的解决方案。

【问题讨论】:

标签: c++ c++11


【解决方案1】:

你需要添加

virtual void throwYourself() = 0;

到 Widget 类。并用

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

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

【讨论】:

    【解决方案2】:

    你不能,这对编译器来说相当重要。它必须确保throwcatch 匹配。对throw的限制意味着编译器至少知道抛出对象的静态类型。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多