首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

c++多态深入分析-单继承

2013-01-27 
c++多态深入分析--单继承编译器在编译的时候,发现基类中有虚函数,此时编译器会为每个包含虚函数的类创建一

c++多态深入分析--单继承

编译器在编译的时候,发现基类中有虚函数,此时编译器会为每个包含虚函数的类创建一个虚表(vtable),该表是一个一维数组,

在这个数组中存放每个虚函数地址,这张表解决了继承、覆盖的问题,保证其真实放映实际的函数。编译器会为基类与继承类都建

立一个虚表(即便继承类中没有virtual函数,但是基类中有,那么继承类也就是有)。一般编译器将指向虚表指针存放在实例对象

中第一个地址。那么其实我们只要获得这个类的实例对象的地址,就获得了指向该虚表的指针的地址。如图:

c++多态深入分析-单继承

举例分析:首先验证是否实例化的第一个地址是虚表,输出虚表第一个函数。

通过这段代码可以肯定结构如果所示,因为该对象的大小就是4,所以只有一个指针。

c++多态深入分析-单继承

情况一:一般继承,无覆盖


由上图我们可以证明,不是虚函数的函数是绝对不会进入虚函数表的。去掉下面两行代码即可:

如果只是一般继承,没有发生覆盖,那么其结果如下图

c++多态深入分析-单继承


情况二:一般继承有覆盖

class base{    public:        vritual void first( );        virtual void second( );};void base::first( ){    std::cout<<"In base the first virtual function "<<std::endl;}void base::second( ){    std::cout<<"In base the second virtual function "<<std::endl;}class derived:public base{    public:        void first( );        virtual void fourth( );};void derived::first( ){    std::cout<<"In derived the first function "<<std::endl;}void derived::fourth( ){    std::cout<<"In derived the fourth function"<<std::endl;}int main( ){    derived d;    typedef void(*fun)(void);    std::cout<<"vtptr address is"<<&d<<std::endl;    std::cout<<"vt address is"<<(int *)*(int *)&d<<std::endl;    f=(fun)*(int *)*(int *)&b;    f( );    f=(fun)*( (int *)*(int *)&b + 1 );    f( );    f=(fun)*( (int *)*(int *)&b + 2 );    f( );    f=(fun)*( (int *)*(int *)&b + 3 );    f( );    return 0;}

结果如下

c++多态深入分析-单继承

这个结果说明超出了虚表的地址范围,虚表里只有三个虚函数,所以同上的操作,去掉下面代码


那么我们就可以得到如下结构图

c++多态深入分析-单继承

虚表指针在什么时候和什么地方初始化呢?
在构造函数中进行虚表的创建和虚表指针的初始化。根据构造函数的调用顺序,在构造继承类构造函数时,先调用基类的构造函数,此时编译器只知道基类,并不知道后面继承类。它初始化基类对象的虚表指针,该虚表指针指向基类的虚表。当执行子类的构造函数时,子类对象的虚表指针被初始化,指向自身的虚表。
所以在在将各种继承类对象地址赋值给基类指针的时候,指向虚表的指针是不一样的,当调用其有覆盖的函数的时候,就能实现其多态效果。

热点排行