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

The type of the exception object created by an exception expression

本文关键字:异常 类型 对象 创建 表达式      更新时间:2023-10-16

我从C++Primer(第5版,第18.1.1节)中读到以下内容:"当我们抛出一个表达式时,该表达式的静态编译时类型决定了异常对象的类型。">

作者所说的"异常对象的类型"是指异常对象的动态类型还是静态类型?

这里有一个相关的问题:异常对象的静态类型

我认为您在一般情况下难以掌握动态和静态类型。因此,让我们来解决这个问题,并将例外情况放在边线上。

首先,静态和动态类型什么时候开始发挥作用?答案是运行时多态性。现在,虽然你可能听说过"多态类型"这个词,但你应该知道根本没有。类型不是多态的。

但它们可以被多晶型地使用!这种区别很重要,我希望你很快就会明白原因。让我们来看一个简单的案例研究:

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与它结合,这当然是允许的。它是"真实的",动态的类型,是Derived。但是fooBase&来指代它。这就是多态用法。即使函数看到一种类型,但实际上它是另一种类型。由于间接性,它是通过虚拟函数机制操作的"其他"类型。

现在让我们将其应用于您的问题。投掷将生成对象的副本。复制对象的类型由它所给定的表达式决定。因此,当您给它一个Base&时,它将创建一个Base对象。事实上,它可能真的是对Derived的引用,这是无关紧要的。引发异常不是多态用法。

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