Is a dynamic_cast<> limited to direct casts along the inheritance hierarchy?

半城伤御伤魂 提交于 2020-01-03 19:07:23

问题


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?

Note that I have left out the virtual details to keep the code simple.

If dynamic_cast<> is limited to direct casts along the inheritance hierarchy, then I expect the code above to fail at run-time (because B& is unrelated to A&).

However, if it is more generic/flexible, the code should work, because the true-type of the referred to object is of C type (and C can be referred to as B& or A&).

What do the C++ specifications say about this case?


回答1:


Right now, the code won't compile because none of the classes has any virtual functions -- a requirement to use dynamic_cast. If you add at least one virtual function (e.g., a virtual dtor to B, then yes, since a C is derived publicly from B, the cast will succeed.

Here's a bit of quick demo code:

#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();
}

The output (with both VC++ and g++, and this isn't cutting edge, so I'd expect anything but a truly ancient compiler to get it right) is:

A
C

Showing that the a has a static type of A, but a dynamic type of C.




回答2:


dynamic_cast<T>(v) may go down to the most derived object of which v is a sub-object, then up (possibly a different branch) to find an unambiguous base class to which T is a pointer or a reference. From the standard:

5.2.7/8 If C is the class type to which T points or refers, the run-time check logically executes as follows:

  • If, in the most derived object pointed (referred) to by v, v points (refers) to a public base class subobject of a C object, and if only one object of type C is derived from the subobject pointed (referred) to by v the result points (refers) to that C object.
  • Otherwise, if v points (refers) to a public base class subobject of the most derived object, and the type of the most derived object has a base class, of type C, that is unambiguous and public, the result points (refers) to the C subobject of the most derived object.
  • Otherwise, the run-time check fails.


来源:https://stackoverflow.com/questions/20015309/is-a-dynamic-cast-limited-to-direct-casts-along-the-inheritance-hierarchy

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!