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

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

本文关键字:层次结构 继承 转换 lt cast gt 是否 dynamic 于沿      更新时间:2023-10-16

>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<>仅限于沿继承层次结构的直接强制转换,那么我希望上面的代码在运行时失败(因为 B& 与 A&无关)。

但是,如果它更通用/灵活,代码应该可以工作,因为引用对象的 true 类型是 C 类型(C 可以称为 B& 或 A&)。

C++规范对这种情况有什么看法?

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

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

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

现在,代码无法编译,因为没有一个类有任何虚函数 - 这是使用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