RTTI及多态的实现机制

                           C++ RTTI及多态的实现机制

 

RTTI中无论是dynamic_cast还是typeid,都是只对引用和指针有效。

 

 

假设实现多态的继承体系:

class Base

{

    public:

    virtual void Fun() ;

}

class Derived ;

Base* pp = new Derived() ;

Derived* pp2 = dynamic_cast< Derived*>(pp) ;

pp->Fun() ;

delete pp ;

 

先看看RTTI 如何实现:Derived* pp2 = dynamic_cast< Derived*>(pp) ;

当执行此语句时,首先找到pp指向的内存,取出此内存中头四个字节的内容,它即是vptr的值,然后找到vptr指向的内存,此处存放的是vtbl,而vtbl的第一个元素就是关于pp所指向实体的类型信息(可以通过此信息来解释pp指向的内存的内容)。到此,就可以决定dynamic_cast< Derived*>(pp)是返回NULL,还是转换成功。

 

在看多态调用实现: pp->Fun() ;

Fun函数指针在vtbl中的位置是在编译期就确定了的,因为Base类的各虚函数声明后,其vbtl的内容和格式就基本确定了。

原理同上差不多。首先找到pp指向的内存,取出此内存中头四个字节的内容,它即是vptr的值,然后找到vptr指向的内存,此处存放的是vtbl,而vtbl的第二个元素即vptr[1]就是所需要调用的函数的函数指针。

 

注意:

(1)       各个类的vtbl是在编译期就安排好了的,只是直到运行期才知道某个vbtl占用的内存地址。

(2)       各个vtbl中的函数指针指向的函数是在编译期确定的,但是函数指针的值是在运行期确定的,因为只有到运行期,才会知道函数的代码在内存空间中存放的地址。也可以将各个函数当作一个singleton类来理解。

(3)       vptr是由编译器插入到class定义中的,一般作为类的第一个成员。

(4)       vptr是在构造函数中被初始化的(这条代码也是编译器加上去了),所以vptr的值是在运行期确定的。可以这样理解:vptr = vtbl.createInstance() ;vtbl实际上是一个singleton类。即一个类对应一个vtbl,改类的所有对象都使用同一个vtbl。

你可能感兴趣的:(C++,null,delete,Class,编译器,fun)