我从 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* 吗?
当我们抛出一个表达式时,该表达式的静态编译时类型决定了异常对象的类型
以上内容完全属实。你忘记的是,指针也是对象。当你抛出一个指针时,那是你的异常对象.
The object you should have dynamically1 allocated is still pointed to by that Base*
pointer. And no slicing occurs on it, because there is no attempt to copy it. As such, dynamic dispatch via-pointer accesses a Derived
object, and that object will use the overriding function.
这种“差异”就是为什么通常最好在 throw 表达式本身中构造异常对象。
1 That pointer points to a local object, you did a big no no there and got yourself a dangling pointer.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)