异常表达式创建的异常对象的类型

The type of the exception object created by an exception expression

我从 C++ Primer(第 5 版,第 18.1.1 节)中阅读了以下内容:"When we throw an expression, the static, compile-time type of that expression determines the type of the exception object."

作者"the type of the exception object"是指动态类型还是静态类型[=异常对象的 20=]?

这是一个相关问题:

我认为您一般在掌握动态类型和静态类型方面有困难。因此,让我们解决这个问题,暂时将例外情况放在一边。

首先,静态类型和动态类型何时发挥作用?答案是运行次多态。现在,虽然您可能听说过表达式 "polymorphic types",但您应该知道没有这样的东西。类型不是多态的。

但它们可以多态使用!这种区别很重要,我希望您很快就会明白为什么。让我们看一个简单的案例研究:

struct Base {
  virtual void print() const { std::cout << "Base"; }
};

struct Derived : Base {
  void print() const override { std::cout << "Derived"; }
};

void foo(Base& b) {
  b.print();
}

int main() {
  Derived d;
  foo(d);
}

foo 中,我们可以使用绑定到某个 Base 对象的引用 b。表达式 b 的类型是什么?是 Base。因为如果我们要创建引用对象的副本,我们会得到一个 Base。这就是所谓的对象的静态类型。写在声明中的类型,简单明了。此外,在 main 中, d 的类型是什么?也是Derived,同理

但是当你将 d 传递给 foo 时会发生什么?

引用b绑定到它,当然这是允许的。是"real",动态类型,是Derived。但是 fooBase& 引用它。这就是多态用法。尽管该函数看到一种类型,但它实际上是另一种类型。由于间接性,它是通过虚函数机制操作的 "other" 类型。

现在让我们把它应用到你的问题上。投掷将复制该对象。复制对象的类型由给定的表达式决定。所以当你给它一个 Base& 时,它会创建一个 Base 对象。它可能真的是对 Derived 的引用这一事实并不重要。抛出异常不是多态用法。

可能 是多态用法,是 catch 子句。如果我们通过引用捕获,那么所引用的异常对象实际上可能与我们拥有的引用具有不同的类型。