c++ - dynamic_cast 向下转型 : How does the runtime check whether Base points to Derived?

标签 c++ rtti abi dynamic-cast downcast

我有兴趣了解,一般来说,运行时在使用dynamic_cast应用向下转型时如何检查基类是否实际上指向派生类。 我知道多态类的每个虚拟表也包含 RTTI(以 type_info 指针的形式)。

最佳答案

每个编译器在实现上都会略有不同,但我将使用 MSVC 作为引用,因为它们可以轻松地使用 VS 提供源代码。

您可以通过转到 Visual Studio 安装并转到 /Community/VS/Tools/MSVC/${VERSION}/crt/src/vcruntime/rtti 来查看有关 MSVC 如何执行此操作的所有详细信息。 .cpp

编译器将在内部转换dynamic_cast来调用函数__RTDynamicCast(如果尝试转换为void,则调用__RTCastToVoid *),这将获取目标类型和源类型的 RTTI 信息。 _RTTITypeDescriptor 结构中的关键元素是完全修饰的名称。然后,它将根据输入类型是否具有单继承、多重继承或虚拟继承来分派(dispatch)到 3 种不同实现之一。

对于单继承FindSITargetTypeInstance将遍历基类类型列表,如果通过指针比较找到匹配项,它将返回类描述符。如果它无法通过指针比较找到匹配项,它将使用字符串比较再次尝试。

对于多重继承,FindMITargetTypeInstance 将以深度优先、从左到右的顺序遍历类层次结构,直到看到源类型和目标类型的描述符。每次比较都是通过 TypeidsEqual 完成的,它将首先尝试进行指针比较,但会立即回退到字符串比较,这与单继承不同,因为单继承很可能在 2 个单独的循环中执行此操作指针会匹配。

对于虚拟继承,FindVITargetTypeInstance 将遍历整个类层次结构。这是三者中最慢的,因为由于潜在的菱形继承(钻石问题),它无法提前退出。每次比较都是通过 TypeidsEqual 完成的。

一旦找到类型的描述符,它将使用它来计算从源指针到目标指针的偏移量。

总体而言,代码相当简单,并且文档记录得非常好,尽管我确实遗漏了一些细微差别,例如检查基类是否是公开派生的,或者区分向下转换、向上转换和交叉转换。

关于c++ - dynamic_cast 向下转型 : How does the runtime check whether Base points to Derived?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70865904/

相关文章:

c++ - GCC 的 -Wpsabi 选项到底有什么作用?压制它有什么影响?

c++ - 链表析构函数 C++

c++ - 在统一的内联初始化中使用不可复制的值初始化静态 std::map

c++ - 关于维基百科上的 RTTI 定义

java - 我的困惑: reflection in Java

c++ - 在 Mac OS X 上将带和不带 RTTI 的库与 GCC 混合使用?

python - 为什么 2019 年我们仍然不能使用 ctypes 从 Python 调用 C++?

c++ - 逗号运算符的局限性

c++ - 继承和析构函数 - 理论问题 - C++

c++ - 什么是从虚基类继承的虚函数的 "virtual thunk"?