dynamic_cast实现
dynamic_cast是C++语言的一部分,并不是STL
dynamic_cast is built in to the language. It does require an implementation, but there is no standardised location for the http:// implementation.In the gcc tool-chain, you can find some helper functions for the implementation in libsupc++.
对dynamic_cast进行反汇编,可以看到dynamic_cast会调用一个runtime library中的函数__dynamic_cast,
0x0000000000401800
库函数__dynamic_cast需要四个参数:
extern
__dynamic_cast的一个版本的代码见:这里 代码大概看了一下,可以分为这么几步,以下图的继承为例(不考虑虚继承)
![7f6176d6b0a334a6968cf6250efe5697.png](https://img-blog.csdnimg.cn/img_convert/7f6176d6b0a334a6968cf6250efe5697.png)
假设B* pb = &c, v = pb, src = typeinfo of B, dst =X, E, A, D,不考虑src2dst_offset这个参数。
- - 获得most_derived_object,即v所指对象本质上是什么对象,即c。这通过pb + top_offset即可做到。
- - 在most_derived_object的继承树中查找dst类型(walk_object函数)这个函数是一个递归函数,本质上是递归当前结点(C)的所有子结点。复杂度为O(n),n为继承树中结点数量。
- - 如果没找到dst,那就返回NULL
- - 一般来说可以找到dst,那就通过offset(即虚函数表第一项)将指针从pb调整到所希望的位置
- 比如: - dst = X, 则返回值指向c中的x部分 - dst = E,E不在以c为根的继承树中,返回NULL - dst = A, A是ambiguous的,返回NULL - dst = D,D在以c为根的继承树中,返回NULL
总结一下dynamic_cast:
dynamic_cast(src )实现继承树中的向上或向下转化,从target->src;
- - 当发生向上转化时,比如dynamic_cast(C),这种转化是确保有效的,编译器通过加上offset即可完成,此时相当于static_cast(C*)
- - 当发生向下转化时,要查看指针所指对象的实际类型,target在不在该对象的继承树内。
- - 指针转化失败返回NULL,引用返回失败throw bad_cast 异常
参考资料:
[1] C++ RTTI的dynamic_cast函数 https://www.jianshu.com/p/778e5a4e4f29
[2] 多重继承中,每个虚表第一个槽中的type_info是对应base class还是全是derived class的类型? https://www.zhihu.com/search?type=content&q=typeinfo
[3] C++对象模型的规范 https://itanium-cxx-abi.github.io/cxx-abi/abi.html#rtti
typeinfo类
https://docs.microsoft.com/en-us/cpp/cpp/run-time-type-information?view=vs-2019docs.microsoft.com最后附上一张C++对象模型图:
![4d94fb86700c5a6114f46a00cba434cf.png](https://img-blog.csdnimg.cn/img_convert/4d94fb86700c5a6114f46a00cba434cf.png)
- [1] typeinfo也是一个多态类,所以第一个条目为虚函数表。
- [2] _ZThn16_N7Class_C2fbEv 用于调整this指针
- [3] 根据[Itanium ABI](
https://web.archive.org/web/20100315072857/http://www.codesourcery.com/public/cxx-abi/abi.html#mangling)规定的符合命名规范:
> <ctor-dtor-name> ::= C1 # complete object constructor
::= C2 # base object constructor
::= C3 # complete object allocating constructor
::= D0 # deleting destructor
::= D1 # complete object destructor
::= D2 # base object destructor
_ZN10__cxxabiv121__vmi_class_type_infoD0Ev 和_ZN10__cxxabiv121__vmi_class_type_infoD2Ev分别为该类的deleting destructor和base object destructor。具体的作用这里不作讨论。
相关代码如下:
#include