std :: bad_cast指针vs参考情况

时间:2012-02-23 19:19:39

标签: c++ exception

我注意到关于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示例时抛出异常?我认为这个决定背后有一个很好的动机,而且由于我不理解这种动机,我误用了一些东西。

2 个答案:

答案 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&>操作必须返回一个有效的内存地址以绑定到引用变量,那么如果动态转换失败,则它不能返回“非值”...唯一的选择是抛出异常。