是dynamic_cast<>仅限于继承层次结构中的直接强制转换?

时间:2013-11-16 05:57:44

标签: c++ c++11 casting

CODE

struct A { };           // virtual details there, but left out
struct B { };           // virtual details there, but left out
struct C : A, B { };    // virtual details there, but left out

C c;
B& b = c;
A& a = dynamic_cast<A&>( b );  // will this cast succeed at run-time?

请注意,我遗漏了虚拟细节以保持代码简单。

如果dynamic_cast&lt;&gt;仅限于继承层次结构中的直接强制转换,然后我希望上面的代码在运行时失败(因为B&amp;与A&amp;无关)。

但是,如果它更通用/更灵活,则代码应该起作用,因为引用对象的真实类型是C类型(并且C可以称为B&amp;或A&amp;)。

C ++规范对此案例的评价是什么?

2 个答案:

答案 0 :(得分:6)

dynamic_cast<T>(v)可以归结为v是子对象的最派生对象,然后向上(可能是不同的分支)以找到T的明确基类是指针或引用。从标准:

  

5.2.7 / 8 如果CT指向或引用的类类型,则运行时检查按逻辑执行如下:

     
      
  • 如果在v指向(引用)的最派生对象中,v指向(引用)C对象的公共基类子对象,并且   如果只有一个C类型的对象是从指向的子对象派生的   (引用)v结果点(引用)C对象。
  •   
  • 否则,如果v指向(引用)最派生对象的公共基类子对象,以及最派生对象的类型   有一个类型为C的基类,它是明确的,公开的,   结果点(引用)到派生最多的C子对象   对象。
  •   
  • 否则,运行时检查将失败。
  •   

答案 1 :(得分:3)

目前,代码无法编译,因为没有类具有任何虚函数 - 需要使用dynamic_cast。如果您添加至少一个虚拟函数(例如,虚拟dtor到B),则是,因为C是从B公开派生的,所以演员会成功。

以下是一些快速演示代码:

#include <iostream>

struct A {
    virtual void junk() { std::cout << "A"; }
    void trash() { std::cout << "A"; }
    virtual ~A() {}
};

struct B { 
    virtual ~B(){} 
    void trash() { std::cout << "B"; }
    void junk() { std::cout << "B"; }
};

struct C : virtual A, virtual B { 
    void trash()  { std::cout << "C"; }
    void junk() { std::cout << "C"; }
};    

int main() {
    C c;
    B& b = c;
    A& a = dynamic_cast<A&>(b); 
    a.trash();
    std::cout << "\n";
    a.junk();
}

输出(使用VC ++和g ++,这不是最先进的,所以我希望除了真正古老的编译器以外的任何东西都能正确):

A
C

显示a的静态类型为A,但动态类型为C