Scott Meyer
在他的书中Effective C++
说dynamic_cast
用于执行向下或跨继承层次结构的安全强制转换。也就是说,您使用 dynamic_cast 将指向基类对象的指针或引用转换为指向派生或同级基类对象的指针或引用,这样您就可以确定转换是否成功。
失败的转换由空指针(转换指针时)或异常(转换引用时)指示。
我想得到两个代码片段,在可以指示转换指针和转换引用的情况下显示失败的转换。
Scott Meyer
在他的书中Effective C++
说dynamic_cast
用于执行向下或跨继承层次结构的安全强制转换。也就是说,您使用 dynamic_cast 将指向基类对象的指针或引用转换为指向派生或同级基类对象的指针或引用,这样您就可以确定转换是否成功。
失败的转换由空指针(转换指针时)或异常(转换引用时)指示。
我想得到两个代码片段,在可以指示转换指针和转换引用的情况下显示失败的转换。
对于指针,这是一个简单的空检查:
A* a = new A();
B* b = dynamic_cast<B*>(a);
if (b == NULL)
{
// Cast failed
}
作为参考,您可以捕获:
try {
SomeType &item = dynamic_cast<SomeType&>(obj);
}
catch(const std::bad_cast& e) {
// Cast failed
}
根据 OP 的评论(“我不明白 Scott 提到的演员阵容如何失败。”),这里真正的问题实际上是:“怎么会dynamic_cast
失败?”
失败的时间是目标类型与对象的动态类型不匹配。举个简单的例子:
struct A {
virtual ~A() {}
};
class B : public A {};
int main() {
A *a = new A;
B *b = dynamic_cast<B *>(a); // should fail
if (b == NULL)
std::cout << "First cast failed.\n";
A *c = new B;
b = dynamic_cast<B *>(c); // should succeed
if (b == NULL)
std::cout << "Second cast failed.\n";
return 0;
}
这里虽然a
可以指向一个类型的对象B
,但它实际上确实指向了一个类型的对象A
。当我们尝试做一个 dynamic_cast 让它指向 aB
时,它失败了。在第二次尝试中,我们再次有一个指针,它不仅可以而且确实指向 type 的对象B
。既然这样做了,那么B *
在这种情况下,dynamic_cast 就会成功。
对于参考案例,基本情况并没有改变(很多),只是a
,b
并c
成为引用而不是指针,我们通过捕获异常来记录失败(@ReedCopsey 已经很好地证明了这一点,我认为我没有任何要添加的新内容)。
这是一个完整的示例,显示了如何dynamic_cast
无法生成指针。
class A
{
public:
virtual void Foo();
};
class B: public A
{
};
class C: public A
{
};
void test()
{
A a;
B b;
A* pA = &b;
B* pB = dynamic_cast<B*>(pA); // this works OK, returns the expected pointer
C* pC = dynamic_cast<C*>(pA); // this returns NULL because B isn't a C
}
在现实世界中,您将尝试投射并非如此直接创建的指针,也许它们来自一个vector
示例。