当 A 和 B 没有共同祖先时,通过 dynamic_cast 从 A* 转换为 B* 是否有效?

Is it valid to cast from A* to B* via dynamic_cast when A and B haven't a common ancestor?

本文关键字:cast 转换 是否 有效 dynamic 祖先 通过      更新时间:2023-10-16

clang 3.5.0g++4.9.0fine编译以下代码(使用-std=c++11 -Wall -Wextra -pedantic-errors),程序输出true:

#include <iostream>
struct A
{
    virtual ~A() = default;
};
struct B
{
    virtual ~B() = default;
};
struct C : A, B
{
    virtual ~C() = default;
};
int main()
{
    C c;
    A* ap = &c;
    B* bp = dynamic_cast<B*>(ap);
    std::cout << std::boolalpha << (bp != nullptr) << std::endl;
}

是。这有时被称为交叉投射,如果它们都是同一派生对象的基子对象,就会成功,就像这里一样。

dynamic_cast是必要的,因为转换需要运行时信息,这两者都是C对象的一部分。要进行静态转换,必须先显式转换为C*

是的,根据§5.2.7[expr.dynamic.cast],对于dynamic_cast<T>(v)(强调矿):

如果C是T指向或引用的类类型,则运行时检查逻辑执行如下:

--如果在v指向(引用)的最派生对象中,v指向(参考)公共基类C对象的子对象,并且如果只有一个类型为C的对象是从v指向(引用)的子对象派生的,则结果指向(参考)该C对象。

--否则,如果v指向(引用)最派生对象的公共基类子对象,并且派生次数最多的对象的类型有一个C类型的基类,它是明确的和公共的,结果指向(引用)派生次数最多对象的C子对象

--否则,运行时检查将失败。

在您的案例中,v引用了一个派生程度最高的对象,该对象是C的实例,但v的静态类型是指向公共基类A的指针。报价单中提到的C基类就是您的B