我注意到关于std :: bad_cast异常,引用和指针似乎没有相同的行为。例如:
class A { public: ~A() {} };
class B : public A {};
//Case #1
int main()
{
A a;
B& b = dynamic_cast<B&>(a); //Would throw std::bad_cast.
}
//Case #2
int main()
{
A* a = new A;
B* b = dynamic_cast<B*>(a); //Would not throw std::bad_cast.
}
在第一种情况下,生成了std :: bad_cast的异常,在第二种情况下,没有生成异常 - 相反,b指针只被赋值为NULL。
有人可以向我解释为什么只有前者在两个都是bad_cast示例时抛出异常?我认为这个决定背后有一个很好的动机,而且由于我不理解这种动机,我误用了一些东西。
答案 0 :(得分:6)
有人可以向我解释为什么只有前者抛出异常吗?
这就是dynamic_cast
指定行为的方式:涉及指针的错误dynamic_cast
会产生空指针,但是没有空引用,因此涉及引用的错误dynamic_cast
会引发{ {1}}。
涉及指针的失败的bad_cast
产生空指针的事实很有用,因为它允许更简洁的类型检查,并允许以下习语:
dynamic_cast
使用这个习语,if (B* b = dynamic_cast<B*>(a))
{
// The dynamic_cast succeeded and 'b' is non-null.
}
在范围内,当且仅当它是非空时才可用。
答案 1 :(得分:2)
引用必须绑定到包含有效内存地址的对象...它们不能是“未初始化”,也不能具有默认的非绑定初始化值。请注意,C ++ 11标准中的第8.5 / 8节说明了
调用引用类型实体的默认初始化或值初始化的程序格式不正确。
另一方面,指针变量只是包含指向其他内存地址的值的内存地址,因此可以具有NULL
值。
因此,如果按照标准,dynamic_cast<T&>
操作必须返回一个有效的内存地址以绑定到引用变量,那么如果动态转换失败,则它不能返回“非值”...唯一的选择是抛出异常。