对于C++的学习,我看了C++ Primer之后,进阶的书为深入理解C++对象模型,这本书讲解了C++类在内存中是如何布局以及成员函数是怎么调用,有助于理解C++多态是如何实现的.总之,受益匪浅.

 

 

无多态的对象布局

单个类:

假设有以下一个类的定义:

【C++札记】C++对象模型之内存布局

如果类没有虚函数,那么class的布局和c语言的struct布局一样,只有成员变量.对象内存布局如图1左所示.

继承类

如果有一个类B继承上面的类A,定义如下:

【C++札记】C++对象模型之内存布局

子类的构造函数是先构造父类,再构造子类,所以类B对象内存布局只要在A成员之后加上B的成员即可,示意图如图1右所示:

【C++札记】C++对象模型之内存布局

                                                       (图一)


多态下对象内存布局

单个类:

首先定义一个类,带有虚函数:

【C++札记】C++对象模型之内存布局

因为class A带有虚函数,所以A对象的内存布局就要增加一个虚函数表指针,它是一个指针,指向类A的虚函数表.对象模型如图2上所示.深入理解C++对象模型将指针放在了对象的末尾,但是现在主流的编译器都将指针放在了对象的首位置.

单继承:

单继承类的定义如下:

【C++札记】C++对象模型之内存布局

当父类有虚函数时,子类继承父类的虚函数表,而且虚函数的顺序是先父类的虚函数,再子类的虚函数;当父类的虚函数被子类重写时,则虚函数表中的父类虚函数指针要替换为子类的虚函数指针,示意图如图2下.

【C++札记】C++对象模型之内存布局

                                                (图二)

 

实例验证

为了验证之前的对象模型是否正确,我写了如下程序进行验证:

【C++札记】C++对象模型之内存布局

【C++札记】C++对象模型之内存布局

稍微解释下

【C++札记】C++对象模型之内存布局

  • (long*)bp,将对象的指针类型转换为(long*)类型,用于取出虚函数表的地址.

  • *(long*)bp,*为取出指针指向的值.此式子即虚函数表的地址,也就是第一个虚函数的地址.

  • (long*)*(long*)bp,将虚函数表的地址指针转换为(long*),用于后续迭代.

  • *(long*)*(long*)bp,*求指针值,即为第一个虚函数的地址,最后转换为pfun指针.

该程序输出结果为:

【C++札记】C++对象模型之内存布局

输出顺序和上述一样.


多重继承

理论讲解:

多重继承,顾名思义,就是继承关系大于2,即至少有父类,子类,孙子类三代关系,先定义以下三个类:

【C++札记】C++对象模型之内存布局

【C++札记】C++对象模型之内存布局

类B公有继承A,类C公有继承B,图一是类C的内存布局

【C++札记】C++对象模型之内存布局

                                                       (图一)

其实多重继承和单继承很类似,就是在父类的基础上添加成员变量和更新虚函数表.

实例讲解

编写了以下程序进行验证:

【C++札记】C++对象模型之内存布局

【C++札记】C++对象模型之内存布局

该程序的输出结果为:

【C++札记】C++对象模型之内存布局

程序的输出顺序和上述给出的图一样,这就证明了我给出的内存布局图是正确的.


多继承

理论讲解:

多继承,顾名思义就是说一个子类的父类不止一个.定义以下三个类,以及他们的继承关系:

【C++札记】C++对象模型之内存布局

【C++札记】C++对象模型之内存布局

定义了三个类,类C分别继承类A和类B,类C的内存布局图二所示:

【C++札记】C++对象模型之内存布局

多继承的内存布局和单继承和多重继承不一样,子类继承一个父类,子类就有一个虚函数表,当子类继承两个父类时,子类就有两个虚函数表;而且子类自己定义的虚函数,放在了第一个继承类的虚函数表里.

实例讲解

编写以下程序来验证上述理论:

【C++札记】C++对象模型之内存布局

【C++札记】C++对象模型之内存布局

该程序输出的结果为:

【C++札记】C++对象模型之内存布局

相关文章:

  • 2021-08-24
  • 2021-08-02
  • 2022-12-23
  • 2022-02-13
  • 2021-12-25
  • 2021-06-14
猜你喜欢
  • 2022-12-23
  • 2021-05-20
  • 2021-07-30
  • 2021-12-10
  • 2021-10-06
  • 2021-04-17
相关资源
相似解决方案