【发布时间】:2017-10-22 07:33:22
【问题描述】:
我从 C++ Primer(第 5 版,第 18.1.1 节)中阅读了以下内容: “当我们抛出一个表达式时,该表达式的静态编译时类型决定了异常对象的类型。”所以我尝试了以下代码:
#include <iostream>
class Base{
public:
virtual void print(std::ostream& os){os << "Base\n";}
};
class Derived: public Base{
public:
void print(std::ostream& os){os << "Derived\n";}
};
int main(){
try{
Derived d;
Base &b = d;
b.print(std::cout); //line 1
throw b;
}
catch(Base& c){
c.print(std::cout); //line 2
}
return 0;
}
这给了我以下输出:
Derived
Base
我想我理解为什么会出现这个输出:在第 1 行,我们有动态绑定。现在我们抛出b,它是基于b的静态类型,也就是说c的静态类型和动态类型都是Base&,所以我们在第2行看到结果。
但是,如果我使用指针而不是引用:
int main(){
try{
Derived d;
Base *b = &d;
b->print(std::cout); //line 1
throw b;
}
catch(Base* c){
c->print(std::cout); //line 2
}
return 0;
}
现在的输出变成:
Derived
Derived
这似乎暗示c的静态类型是Base*,而c的动态类型是Derived*,为什么? c的静态和动态类型不应该都是Base*吗?
【问题讨论】:
-
第一种情况,对象被切片。
-
@StoryTeller 谢谢!第二种情况下表达式 b 的静态类型和动态类型是什么? Base* 和 Derived* 分别是?
-
表达式没有动态类型,只有对象有。
-
本书试图为新手简化一些非常复杂的语言原理。表达式可以评估为命名对象的内容。对象的静态类型是表达式的类型(有时会调整)。但正式地,只有对象具有动态类型。
-
@StoryTeller 总而言之,每个表达式都有静态类型但没有动态类型,我是否走在正确的轨道上?如果是这样,表达式 b 的静态类型是什么?是 Base* 吗?
标签: c++ try-catch throw static-typing dynamic-binding