我从C ++ Primer(第5版,第18.1.1节)中读到以下内容:“当我们抛出一个表达式时,该表达式的静态编译时类型决定了异常对象的类型。”
通过“异常对象的类型”,作者是指意外对象的动态类型还是静态类型?
以下是相关问题: Static type of the exception object
答案 0 :(得分:2)
我认为你在掌握动态和静态类型方面遇到了麻烦。因此,让我们解决这个问题,并将例外情况留在旁边,暂时停止。
首先,静态和动态类型何时发挥作用?答案是运行时多态性。现在,虽然您可能已经听过表达式"多态类型"扔到身边,你应该知道没有这样的事情。类型不是多态的。
但是他们可以多态地使用!这种区别很重要,我希望你很快就会明白为什么。让我们来看一个简单的案例研究:
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
内,我们可以使用绑定到某个b
对象的引用Base
。表达式b
的类型是什么?它是Base
。因为如果我们要创建引用对象的副本,我们就会获得Base
。这就是所谓的对象的静态类型。声明中写的类型,简单明了。此外,在main
内,d
的类型是什么?它的Derived
也是出于同样的原因。
但是当您将d
传递给foo
时会发生什么?
引用b
绑定到它,当然是允许的。它的真实&#34;动态类型是Derived
。但foo
引用了Base&
。这就是多态用法。即使函数看到一种类型,它实际上是另一种类型。而且由于间接性,它是&#34;其他&#34;通过虚函数机制操作的类型。
现在让我们将它应用到您的问题中。投掷将复制该对象。复制对象的类型由给定的表达式决定。因此,当您给它Base&
时,它将创建一个Base
对象。它可能真的是对Derived
的引用这一事实并不重要。抛出异常不是多态用法。
可以是多态用法,是catch
子句。如果我们通过引用捕获,那么引用的异常对象实际上可能具有与我们所具有的引用不同的类型。