【发布时间】:2010-12-14 04:00:08
【问题描述】:
假设我有类型 A 和派生类型 B。当我执行从 A* 到 B* 的动态转换时,环境执行什么样的“运行时检查”?它怎么知道演员表是合法的?
我假设在 .Net 中可以在对象的标头中使用附加的元数据,但是在 C++ 中会发生什么?
【问题讨论】:
标签: c++ casting polymorphism oop
假设我有类型 A 和派生类型 B。当我执行从 A* 到 B* 的动态转换时,环境执行什么样的“运行时检查”?它怎么知道演员表是合法的?
我假设在 .Net 中可以在对象的标头中使用附加的元数据,但是在 C++ 中会发生什么?
【问题讨论】:
标签: c++ casting polymorphism oop
动态转换执行运行时检查这是否是有效且可行的转换;当无法执行强制转换时,它将返回 NULL。
【讨论】:
动态投射是一个两步过程:
给定指向对象的指针的 vtable,使用偏移量恢复指向完整类的指针。 (然后将从此指针进行所有调整。)这相当于向下转换为整个类。
在整个类的 type_info 中搜索我们想要的类型 - 换句话说,浏览所有基的列表。如果我们找到一个,使用偏移量再次调整指针。如果第 2 步搜索失败,则返回 NULL。
【讨论】:
参考您最喜欢的 RTTI 书籍。
【讨论】:
确切的算法是编译器特定的。以下是它根据Itanium C++ ABI (2.9.7) 标准(写在 GCC 之后编写)的工作原理。
指向基类的指针是指向“大”类主体中间的指针。 “大”类的主体以这样一种方式组装,即无论您的指针指向什么基类,您都可以统一访问该“大”类的 RTTI,而您的“基”类实际上是时间>。这个 RTTI 是一个特殊的结构,它与“大”类信息相关:它是什么类型,它有什么基础以及它们的偏移量。
其实就是类的“元数据”,只是更“二进制”的风格。
V instance;
Base *v = &instance;
dynamic_cast<T>(v);
动态转换利用了这样一个事实,即当您编写 dynamic_cast<T>(v) 时,编译器可以立即识别 v 的“大”类的元数据——即 V!当你编写它时,你认为T比Base更派生,因此编译器将很难进行base-to-drived cast。但是编译器可以立即(在运行时)确定最衍生的类型--V--然后它只需要遍历元数据中包含的继承图来检查它是否可以将V 向下转换为T。如果可以,它只检查偏移量。如果它不能或不明确 - 返回NULL。
【讨论】: