2012-07-16 56 views
11

Scott Meyer在他的书Effective C++dynamic_cast是用来执行安全的强制转换或继承层次结构。也就是说,您可以使用dynamic_cast将指针或对基类对象的引用转换为指向派生或同级基类对象的指针或引用,以便您可以确定转换是否成功。如何使用dynamic_cast运算符来识别失败的转换?

失败转换由空指针(转换指针时)或异常(转换引用时)表示。

我想得到两个代码片段,显示在铸造指针失败的情况下可以指示铸造参考。

+4

您是否要求提供测试指针是否为空以及捕获异常的代码的代码示例? – 2012-07-16 18:18:28

+0

不,我不明白斯科特提到演员如何失败。代码片段肯定会有所帮助。 – 2012-07-16 18:21:25

+1

http://en.wikipedia.org/wiki/Dynamic_cast – 2012-07-16 18:22:08

回答

21

对于三分球,这是一个简单的空检查:

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 
} 
+0

@LinuxPenseur该检查假设“a”具有有效值。你必须首先检查(分配)。 dynamic_cast检查是检查A是否可以安全地转换为“B” - 所以检查是针对'NULL'的'b' - 即:b是null并且a不为null。 – 2012-07-16 18:28:51

+0

@ReedCopsey:什么是我的'安全演员'。在哪种情况下可以变成NULL? – 2012-07-16 18:30:59

+1

当一个类是多态的时候使用'dynamic_cast'(具有'virtual'函数),它执行运行时检查,返回一个'NULL'指针。通过使用'dynamic_cast',您可以告诉它在尝试各种类型的转换时完成您想要的功能而不是C-Style转换。当您不知道要转换的对象时,也会使用'dynamic_cast',而不是'static_cast'用于非多聚类,并且转换中的两种类型都是已知的 – 2012-07-16 18:31:44

3

基础上OP的评论(”我不知道如何强制转换可能失败,因为“),这里真正的问题是这样的:”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以使其指向B时,失败。在第二次尝试中,我们再次有一个指针,不仅,而且指向B类型的对象。既然如此,dynamic_cast到B *就成功了。

的基本情况不改变(多)为参考的情况下,只是abc成为引用,而不是指针,我们通过捕获异常注意故障(其中@ReedCopsey已经证明不够好,我不认为我有什么新的补充)。

3

下面是一个完整的示例,显示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例如。