0x02虚函数分析

来源:互联网 发布:网络空间的定义 编辑:程序博客网 时间:2024/06/06 02:29
#include <iostream>using namespace std;class Base1 {public:    virtual void fun()    {        cout << "Base1::fun" << endl;    }    virtual void foo()    {        cout << "Base1::foo" << endl;    }    Base1()    {        printf("Base1\n");    }    ~Base1()    {        printf("~Base1\n");    }};class Base2 {public:    virtual void fun()    {        cout << "Base2::fun" << endl;    }    virtual void foo()    {        cout << "Base2::foo" << endl;    }    Base2()    {        printf("Base2\n");    }    ~Base2()    {        printf("~Base2\n");    }};class Derive : public Base1, public Base2{public:    virtual void fun()    {        cout << "Derive::fun" << endl;    }    virtual void foo1()    {        cout << "Derive::foo1" << endl;    }    Derive()    {        printf("Derive\n");    }    ~Derive()    {        printf("~Derive\n");    }};int main(){    Derive d;    Base1 *b1 = &d;    b1->fun();    b1->foo();    Base2 *b2 = &d;    b2->fun();    b2->foo();    return 0;}

这里写图片描述
根据继承关系的顺序,首先调用了基类Base1的构造函数。在调用另一个基类Base2时, 并不是直接将对象的首地址作为this指针传递,而是向后调整了基类Base1的大小,以调整后的地址值作为this指针,最后再调用基类Base2的构造函数。
由于有了两个基类,因此子类在继承时也将他们的虚表指针一起继承了过来,也就有了两个虚表指针。在多继承中,派生类虚表指针的个数取决于所继承的基类个数。
这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述
在转换Base2指针时,je short 001A65E5会调整首地址并跳过第一个基类所占用的空间。
这里写图片描述

这里写图片描述
由于具有多个同级的基类,因此早派生类中产生了多个虚表指针。在对基类进行析构时,需要设置this指针,用于调用基类的析构函数。由于具有多个基类,当在析构的过程中调用各个基类的析构函数时,传递的首地址将有所不同,编译器会根据每个基类在对象中占用的空间位置,对应地传入各个基类部分首地址作为this指针。

总结:

单继承:

  1. 在类对象占用的内存空间中,只保存一份虚表指针。
  2. 由于只有一个虚表指针,对应的也只有一个虚表。
  3. 虚表中各项保存了类中各虚函数的首地址。
  4. 构造时先构造基类,在构造自身,并且只调用一次基类构造函数。
  5. 析构时先析构自身,在析构基类,并且只调用一次基类析构函数。

多重继承类:

  1. 在类对象中所占的内存空间中,根据继承基类的个数保存对应的虚表指针。
  2. 根据所保存的虚表指针的个数,对应产生相应个数的虚表。
  3. 构造时需要调用多个基类构造函数。
  4. 转换基类指针时,需要调转到对应的首地址。
  5. 构造时先构造继承列表中第一个基类,然后依次调用到最后一个继承的基类构造函数
  6. 析构时先析构自身,然后以与构造函数相反的顺序调用所有基类的析构函数。
0 0
原创粉丝点击