深入探索C++对象模型之C++对象(vs,gcc,clang测试)

日期更新内容
2020.12.17上午之前虚继承部分有问题,重新进行了测试,更新了结构图
2020.12.17下午添加了gcc测试
2020.12.17晚上添加了clang测试

1 C++对象模型

  C中表示结构化数据一般是使用struct,其中操作数据和具体的数据定义时分开的。C++中的对象是将数据和操作方式包装在一起的ADT(抽象数据类型)。在C++中数据成员分为static,nonstatic,而成员函数分为三种:static,nonstatic,virtual
  现在假定有类base,base的声明如下:

class base
{
public:
    base(int val = 0){}
    virtual ~base(){}
    
    static int count_object(){ return _count; };
    int get_x(){ return _x; };

protected:
    virtual ostream& print(ostream &) const;

protected:
    int _x;
    char _ch;
    static int _count;
};

  那么在不同的C++模型中具体的结构不尽相同。

下面的对象模型图,只是示意图,每一个单元并不表示具体的内存大小

1.1 简单对象模型

  简单对象模型就是对象中的内存单元存储一系列指针,每个指针指向对应的成员函数或者成员变量。当需要访问对象的成员时,需要进行多次寻址才能访问到,并且每个元素都会有一个对应的指针,势必有空间上的浪费。这种方式是通过牺牲空间和执行效率换取编译器设计上的简单性。
.drawio.svg)]

1.2 表格驱动对象模型

  表格驱动模型将成员变量和成员函数分开两个表格存储,对象中只保存两个表格的指针。直观上看每个对象的大小基本是固定的,就是两个指针的大小,但是问题是在访问数据是需要进行多次间接寻址,相比简单对象模型成员变量只需一次寻址,而成员函数需要两次寻址。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AFoajr2b-1608209419796)(深入探索C-对象模型之C-对象/atom.drawio.svg)]

1.3 C++实现对象模型

  在实际的C++实现中,具体的方案是将nonstatic的成员变量保存在类中,而static的成员变量,所有成员函数都被存放在类外。同时虚函数的只是使用一个虚函数表,虚函数表中保存了当前对象中虚函数地址,在实现多态时会对相应的地址进行替换。并且类所关联的type_info存放在虚函数表中的第一个单元中。而虚函数表的设置,重置等工作大部分完成于构造函数,拷贝构造函数,析构函数等中。
  当前模型的有点事在空间和执行效率上都能够兼顾,缺陷时类相关的任何nonstatic的成员变量的修改都需要重新编译程序。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UZB5VhMv-1608209419798)(深入探索C-对象模型之C-对象/com.drawio.svg)]

2 C++和C之间的数据模型差异

2.1 结构化数据

  C中的结构化数据模型struct基本都是按照所声明的内存布局进行分配。而因为C++支持继承,也意味着C++中的结构化数据类型structclass无法完全保证其数据存储方式能够完全按照用户预想的那样存储。
  最直观的例子是,在C中通常在结构体结尾声明一个char buf[],即柔性数组来保证数据上的连续性,但是在C++中由于子类父类之间的内存布局破坏了这一简单有效的方式。
  但是C++在某种程度上是兼容C的,因此可以通过C方式声明数据,然后通过组合的方式将C声明的数据使用C++中的class包裹起来,这种基本等于给C代码添加了一个C++的壳,但是不会破坏C中的数据声明的空间布局。

class cpp_shell
{
public:
    //C数据
    C_data _c_data;

    //操作函数
}

2.2 设计模型

  程序模型:C++兼容C语言的程序模型,即面向过程程序设计。
  抽象数据模型:将数据和具体的操作函数通过C++的class进行绑定,并且重载一些数据常用的操作符,比如+,==,+=等。比较常见的如:std::string
  面向对象模型:面向对象模型基本就是通过一个抽象的基类进行公共接口的抽象,而其派生的子类中实现具体的方法,在运行期通过RTTI进行类型推断,实现多态。

3 C++对象模型测试

  这里会测试visual studio cl,g++,clang三种编译器的测试结果,一切以visual studio cl的测试结果为准,如果后面测试的结构和visual studio相同则不会再重新画结构图,只贴出测试结果。

3.1 Visual Studio CL

  内存模测试Visual Studio使用的cl编译器上的情况。
  另外这里也会尝试使用cl.exe查看内存模型和虚函数表,会使用到的命令如下:

cl /d1 reportSingleClassLayout[class_name] [filename]

  其中class_name为需要查看的类名,filename为要查看的文件名。
  另外下面的示意图中,只会显示在对象内存中的内容,诸如静态成员函数等不在对象中的内容不会再进行绘制。并且图中的一个单元格严格表示一个字节。
  完整测试代码见grayondream/github

3.1.1 简单对象

class base
{
public:
	base();
	~base();

	static void static_func();
	void nonstatic_func();
public:
	int _nonstatic_x;
	static int _static_x;
	char _nonstatic_ch;
};

  上面的简单类型包含静态成员函数,非静态成员函数,静态成员变量和非静态成员变量。测试得到的不同。具体的测试结果如下:

对象base的实例b的大小为:                          8
对象base的实例b的地址:                            000000B0282FF618
对象base的实例b的成员变量_nonstatic_x的地址:      base::_nonstatic_x       000000B0282FF618
对象base的实例b的成员变量_nonstatic_ch的地址:     base::_nonstatic_ch      000000B0282FF61C
对象base的静态成员变量_static_x的地址:            base::_static_x          00007FF6FE9CD000
对象base的成员函数static_func地址:                base::static_func        00007FF6FE9C1127
对象base的成员函数nonstatic_func的地址:           base::nonstatic_func     1

  cl查看得到的内存布局如下:

class base      size(8):
        +---
 0      | _nonstatic_x
 4      | _nonstatic_ch
        | <alignment member> (size=3)
        +---

  基本可以看到对象中占用对象大小的只有非静态变量和相关的内存对齐(当然虚函数表指针也会占用空间,但是当前类没有虚函数表)。另外从上面的输出能够看到静态函数和静态变量存放在相离不远的内存区域,并不在对象中。同时获取到的非静态成员函数地址并未成功打印,一个可靠的可能是如何获取成员函数地址?
  根据上面的结构,大概可以绘制出对象的模型如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hH0Kn0Ni-1608209419799)(深入探索C-对象模型之C-对象/simple_object.drawio.svg)]

  这里已经看到静态类型和对象内存不在同一地区,因此下面的类不会再包含静态类型的数据。

3.1.2 包含虚函数的简单对象

  当前测试使用的类如下,相比上面的base移除了多余的static成员函数和成员变量,添加了一个虚函数。

class virtual_base
{
public:
	virtual_base();
	~virtual_base();

	void nonstatic_func();
	virtual void virtual_func1();
	virtual void virtual_func2();
	virtual void virtual_func3();
	virtual void virtual_func4();
public:
	int _nonstatic_x;
	char _nonstatic_ch;
};

  上面的对象只包含一个虚函数,测试结果如下:

对象virtual_base的实例b的大小为:                            16
对象virtual_base的实例b的地址:                              00000081EF6FF488
对象virtual_base的实例b的成员变量_nonstatic_x的地址:        virtual_base::_nonstatic_x    00000081EF6FF490
对象virtual_base的实例b的成员变量_nonstatic_ch的地址:       virtual_base::_nonstatic_ch   00000081EF6FF494
第0个虚函数执行结果:                            virtual_base::virtual_func1
对象virtual_base的第0个虚函数地址:              00007FF77CBD147E
第1个虚函数执行结果:                            virtual_base::virtual_func2
对象virtual_base的第1个虚函数地址:              00007FF77CBD1479
第2个虚函数执行结果:                            virtual_base::virtual_func3
对象virtual_base的第2个虚函数地址:              00007FF77CBD1474
第3个虚函数执行结果:                            virtual_base::virtual_func4
对象virtual_base的第3个虚函数地址:              00007FF77CBD1483

  可以看到虚函数表的地址存放在对象的开头,之后紧跟的是其他对象元素。因此对象大的小为sizeof(ptr) + sizeof(char) + sizeof(int) + 内存对齐另外在对虚函数进行解析能够完全解析到相关的虚函数并执行得到执行结果。另外,RTTI相关的type_info在表项的-1位置,通过调试器能够看到相关结构,但是没能成功解析出具体的参数值。

		vptr[-1]	0x00007ff7241acf10 {cpp_memory_model.exe!const virtual_base::`RTTI Complete Object Locator'}	void *

  从cl的输出能够看到基本符合测试结果。

class virtual_base      size(16):
        +---
 0      | {vfptr}
 8      | _nonstatic_x
12      | _nonstatic_ch
        | <alignment member> (size=3)
        +---

virtual_base::$vftable@:
        | &virtual_base_meta
        |  0
 0      | &virtual_base::virtual_func1
 1      | &virtual_base::virtual_func2
 2      | &virtual_base::virtual_func3
 3      | &virtual_base::virtual_func4

  从上面的测试结果得到的内存模型如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-livmFPv5-1608209419801)(深入探索C-对象模型之C-对象/vso.drawio.svg)]

3.1.3 单继承内存模型

  简单单继承模型继承自base,并且只为其添加了一个简单的数据类型。

class inherit : public base
{
public:
	char _inherit_ch;
};

  从下面的测试可以看出基类存放在继承类的开头位置,之后紧跟的便是子类独有的成员变量。

对象inherit的实例b的大小为:                                 12
对象inherit的实例b的地址:                                   00000083A26FFA18
对象inherit的实例b的成员变量base::_nonstatic_x的地址:       inherit::base::_nonstatic_x   00000083A26FFA18
对象inherit的实例b的成员变量base::_nonstatic_ch的地址:      inherit::base::_nonstatic_ch  00000083A26FFA1C
对象inherit的实例b的成员变量_inherit_ch的地址:              inherit::_inherit_ch          00000083A26FFA20

  从下面基本可以看出完全符合测试的结果。

class inherit   size(12):
        +---
 0      | +--- (base class base)
 0      | | _nonstatic_x
 4      | | _nonstatic_ch
        | | <alignment member> (size=3)
        | +---
 8      | _inherit_ch
        | <alignment member> (size=3)
        +---

  根据上面的结构得到的内存结构如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ebv5YNwj-1608209419802)(深入探索C-对象模型之C-对象/sinherit.drawio.svg)]

3.1.4 包含虚函数的单继承对象

  单继承体系中,下面的类只重写了基类中的一个虚函数,并且添加了一个自身的虚函数。

class virtual_inherit : public virtual_base
{
public:
	char _virtual_inherit_ch;
public:
	virtual void virtual_func1();
};

  测试结果如下:

对象virtual_inherit的实例b的大小为:                                             24
对象virtual_inherit的实例b的地址:                                               00000046DBFBF6E8
对象virtual_inherit的实例b的成员变量virtual_base::_nonstatic_x的地址:           virtual_inherit::virtual_base::_nonstatic_x       00000046DBFBF6F0
对象virtual_inherit的实例b的成员变量virtual_base::_nonstatic_ch的地址:          virtual_inherit::virtual_base::_nonstatic_ch      00000046DBFBF6F4
对象virtual_inherit的实例b的成员变量_virtual_inherit_ch的地址:                  virtual_inherit::_virtual_inherit_ch              00000046DBFBF6F8
第0个虚函数执行结果:                            virtual_inherit::virtual_func1
对象virtual_base的第0个虚函数地址:              00007FF6E2671136
第1个虚函数执行结果:                            virtual_base::virtual_func2
对象virtual_base的第1个虚函数地址:              00007FF6E267104B
第2个虚函数执行结果:                            virtual_base::virtual_func3
对象virtual_base的第2个虚函数地址:              00007FF6E2671005
第3个虚函数执行结果:                            virtual_base::virtual_func4
对象virtual_base的第3个虚函数地址:              00007FF6E26713F2
第4个虚函数执行结果:                            virtual_inherit::virtual_inherit_func
对象virtual_base的第4个虚函数地址:              00007FF6E2671497

  根据上面的测试结果和下面的结构能够看到子类重写的虚函数在类中的虚函数表中被替换,并且当前类新增的虚函数被添加到虚函数表的末尾。

class virtual_inherit   size(24):
        +---
 0      | +--- (base class virtual_base)
 0      | | {vfptr}
 8      | | _nonstatic_x
12      | | _nonstatic_ch
        | | <alignment member> (size=3)
        | +---
16      | _virtual_inherit_ch
        | <alignment member> (size=7)
        +---

virtual_inherit::$vftable@:
        | &virtual_inherit_meta
        |  0
 0      | &virtual_inherit::virtual_func1
 1      | &virtual_base::virtual_func2
 2      | &virtual_base::virtual_func3
 3      | &virtual_base::virtual_func4
 4      | &virtual_inherit::virtual_inherit_func

  根据上面的测试得到的内存模型如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bouuHsx1-1608209419802)(深入探索C-对象模型之C-对象/vsinherit.drawio.svg)]

3.1.5 多继承体系

  继承体系非常简单只包含两个简单的基类。

class base_left
{
public:
	int _base_left_int;
	char _base_left_ch;
};

class base_right
{
public:
	int _base_right_int;
	char _base_right_ch;
};

class minherit: public base_left, public base_right
{
public:
	char _minherit_ch;
};

  从下面可以看出base_left在继承类开头,之后紧跟的是base_right,最后才是基类本身的数据。

对象minherit的实例b的大小为:                                                    20
对象minherit的实例b的地址:                                                      000000D03AEFF128
对象minherit的实例b的成员变量base_left::_base_left_int的地址:                   minherit::base_left::_base_left_int               000000D03AEFF128
对象minherit的实例b的成员变量base_left::_base_left_ch的地址:                    minherit::base_left::_base_left_ch                000000D03AEFF12C
对象minherit的实例b的成员变量base_right::_base_right_int的地址:                 minherit::base_right::_base_right_int             000000D03AEFF130
对象minherit的实例b的成员变量base_right::_base_right_ch的地址:                  minherit::base_right::_base_right_ch              000000D03AEFF134
对象minherit的实例b的成员变量_minherit_ch的地址:                                minherit::_minherit_ch                            000000D03AEFF138
class minherit  size(20):
        +---
 0      | +--- (base class base_left)
 0      | | _base_left_int
 4      | | _base_left_ch
        | | <alignment member> (size=3)
        | +---
 8      | +--- (base class base_right)
 8      | | _base_right_int
12      | | _base_right_ch
        | | <alignment member> (size=3)
        | +---
16      | _minherit_ch
        | <alignment member> (size=3)
        +---

  推断出的内存模型如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uUjGbsvK-1608209419803)(深入探索C-对象模型之C-对象/minherit.drawio.svg)]

  如果将继承顺序改为

class minherit: public base_right, public base_left
{
public:
	char _minherit_ch;
};

  内存中base_leftbase_right换了个顺序

对象minherit的实例b的大小为:                                                    20
对象minherit的实例b的地址:                                                      000000E48634F8F8
对象minherit的实例b的成员变量base_left::_base_left_int的地址:                   minherit::base_left::_base_left_int               000000E48634F900
对象minherit的实例b的成员变量base_left::_base_left_ch的地址:                    minherit::base_left::_base_left_ch                000000E48634F904
对象minherit的实例b的成员变量base_right::_base_right_int的地址:                 minherit::base_right::_base_right_int             000000E48634F8F8
对象minherit的实例b的成员变量base_right::_base_right_ch的地址:                  minherit::base_right::_base_right_ch              000000E48634F8FC
对象minherit的实例b的成员变量_minherit_ch的地址:                                minherit::_minherit_ch                            000000E48634F908
class minherit  size(20):
        +---
 0      | +--- (base class base_right)
 0      | | _base_right_int
 4      | | _base_right_ch
        | | <alignment member> (size=3)
        | +---
 8      | +--- (base class base_left)
 8      | | _base_left_int
12      | | _base_left_ch
        | | <alignment member> (size=3)
        | +---
16      | _minherit_ch
        | <alignment member> (size=3)
        +---

3.1.6 包含虚函数的多继承体系

class vbase_left
{
public:
	int _base_left_int;
	char _base_left_ch;
public:
	virtual void vbase_left_virtual_function1();
	virtual void vbase_left_virtual_function2();
};

class vbase_right
{
public:
	int _base_right_int;
	char _base_right_ch;
public:
	virtual void vbase_right_virtual_function1();
	virtual void vbase_right_virtual_function2();
};

class vminherit : public vbase_left, public vbase_right
{
public:
	char _minherit_ch;
public:
	virtual void vminherit_virtual_function();
	virtual void vbase_left_virtual_function1();
	virtual void vbase_right_virtual_function1();
};

  从下面的结构能够看到继承类中包含两个虚函数指针,分别存储在基类的开头,并且子类自身的虚函数被添加到继承顺序中第一个虚函数表中。

class vminherit size(40):
        +---
 0      | +--- (base class vbase_left)
 0      | | {vfptr}
 8      | | _base_left_int
12      | | _base_left_ch
        | | <alignment member> (size=3)
        | +---
16      | +--- (base class vbase_right)
16      | | {vfptr}
24      | | _base_right_int
28      | | _base_right_ch
        | | <alignment member> (size=3)
        | +---
32      | _minherit_ch
        | <alignment member> (size=7)
        +---

vminherit::$vftable@vbase_left@:
        | &vminherit_meta
        |  0
 0      | &vminherit::vbase_left_virtual_function1
 1      | &vbase_left::vbase_left_virtual_function2
 2      | &vminherit::vminherit_virtual_function

vminherit::$vftable@vbase_right@:
        | -16
 0      | &vminherit::vbase_right_virtual_function1
 1      | &vbase_right::vbase_right_virtual_function2

  根据上面的结构推断到下面的结果如下:

对象vminherit的实例b的大小为:                                                   40
对象vminherit的实例b的地址:                                                     000000474F6FF388
对象vminherit的实例b的成员变量vbase_left::_base_left_int的地址:                 vminherit::vbase_left::_base_left_int             000000474F6FF390
对象vminherit的实例b的成员变量vbase_left::_base_left_ch的地址:                  vminherit::vbase_left::_base_left_ch              000000474F6FF394
对象vminherit的实例b的成员变量vbase_right::_base_right_int的地址:               vminherit::vbase_right::_base_right_int           000000474F6FF3A0
对象vminherit的实例b的成员变量vbase_right::_base_right_ch的地址:                vminherit::vbase_right::_base_right_ch            000000474F6FF3A4
对象vminherit的实例b的成员变量_minherit_ch的地址:                               vminherit::_minherit_ch                           000000474F6FF3A8

第一个虚函数表:0个虚函数执行结果:                            vminherit::vbase_left_virtual_function1
对象vminherit的第0个虚函数地址:         00007FF7FCC514CE
第1个虚函数执行结果:                            vbase_left::vbase_left_virtual_function2
对象vminherit的第1个虚函数地址:         00007FF7FCC5135C
第2个虚函数执行结果:                            vminherit::vminherit_virtual_function
对象vminherit的第2个虚函数地址:         00007FF7FCC51429

第二个虚函数表:0个虚函数执行结果:                            vminherit::vbase_right_virtual_function1
对象vminherit的第0个虚函数地址:         00007FF7FCC514D3
第1个虚函数执行结果:                            vbase_right::vbase_right_virtual_function2
对象vminherit的第1个虚函数地址:         00007FF7FCC51280

  推断到的结构模型如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qNRbjpQk-1608209419804)(深入探索C-对象模型之C-对象/vminherit.drawio.svg)]

3.1.7 不包含虚函数的菱形继承

  菱形继承采用的结构如下:

class grand
{
public:
	int _grand_x;
	char _grand_ch;
};

class father : public grand
{
public:
	char _father_ch;
};

class mother : public grand
{
public:
	char _mother_ch;
};

class child : public mother, public father
{
public:
	char _child_ch;
};
3.1.7.1 不使用虚继承
class child     size(28):
        +---
 0      | +--- (base class mother)
 0      | | +--- (base class grand)
 0      | | | _grand_x
 4      | | | _grand_ch
        | | | <alignment member> (size=3)
        | | +---
 8      | | _mother_ch
        | | <alignment member> (size=3)
        | +---
12      | +--- (base class father)
12      | | +--- (base class grand)
12      | | | _grand_x
16      | | | _grand_ch
        | | | <alignment member> (size=3)
        | | +---
20      | | _father_ch
        | | <alignment member> (size=3)
        | +---
24      | _child_ch
        | <alignment member> (size=3)
        +---

  从上面可以看到每个基类都会保存一份自身基类的副本。

对象child的实例b的大小为:                                                       28
对象child的实例b的地址:                                                         000000FA898FF7D8
对象child的实例b的成员变量father::grand::_grand_x的地址:                        child::father::grand::_grand_x                    000000FA898FF7E4
对象child的实例b的成员变量father::grand::_grand_ch的地址:                       child::father::grand::_grand_ch                   000000FA898FF7E8
对象child的实例b的成员变量father::_father_ch的地址:                             child::father::_father_ch                         000000FA898FF7EC
对象child的实例b的成员变量mother::grand::_grand_x的地址:                        child::mother::grand::_grand_x                    000000FA898FF7D8
对象child的实例b的成员变量mother::grand::_grand_ch的地址:                       child::mother::grand::_grand_ch                   000000FA898FF7DC
对象child的实例b的成员变量mother::_mother_ch的地址:                             child::mother::_mother_ch                         000000FA898FF7E0
对象child的实例b的成员变量_child_ch的地址:                                      child::_child_ch                                  000000FA898FF7F0

  推导出的内存模型如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BaKoKbIW-1608209419805)(深入探索C-对象模型之C-对象/dimond_inherit.drawio.svg)]

3.1.7.2 使用虚继承
#pragma  once

class grand
{
public:
	int _grand_x;
	char _grand_ch;
};

class father : virtual public grand
{
public:
	char _father_ch;
};

class mother : virtual public grand
{
public:
	char _mother_ch;
};

class child :  public mother,  public father
{
public:
	char _child_ch;
};

  使用虚继承之后结构变为如下:

class child     size(48):
        +---
 0      | +--- (base class mother)
 0      | | {vbptr}
 8      | | _mother_ch
        | | <alignment member> (size=7)
        | +---
16      | +--- (base class father)
16      | | {vbptr}
24      | | _father_ch
        | | <alignment member> (size=7)
        | +---
32      | _child_ch
        | <alignment member> (size=7)
        +---
        +--- (virtual base grand)
40      | _grand_x
44      | _grand_ch
        | <alignment member> (size=3)
        +---

child::$vbtable@mother@:
 0      | 0
 1      | 40 (childd(mother+0)grand)

child::$vbtable@father@:
 0      | 0
 1      | 24 (childd(father+0)grand)
vbi:       class  offset o.vbptr  o.vbte fVtorDisp
           grand      40       0       4 0

  测试结果如下:

对象child的实例b的大小为:                                                       48
对象child的实例b的地址:                                                         0000000D68B2F618
对象child的实例b的成员变量father::_grand_x的地址:                               child::father::_grand_x                           0000000D68B2F640
对象child的实例b的成员变量father::_grand_ch的地址:                              child::father::_grand_ch                          0000000D68B2F644
对象child的实例b的成员变量father::_father_ch的地址:                             child::father::_father_ch                         0000000D68B2F630
对象child的实例b的成员变量mother::_grand_x的地址:                               child::mother::_grand_x                           0000000D68B2F640
对象child的实例b的成员变量mother::_grand_ch的地址:                              child::mother::_grand_ch                          0000000D68B2F644
对象child的实例b的成员变量mother::_mother_ch的地址:                             child::mother::_mother_ch                         0000000D68B2F620
对象child的实例b的成员变量_child_ch的地址:                                      child::_child_ch                                  0000000D68B2F638

  从上面的结构能够看到内存中只有一份共享的grand,但是问题是怎么空间还比没有虚继承的时候大了,这是因为child的两个父类motherfather为了知道它们共享的基类grand的位置在内存中添加了一个指针vbptr,用来指向基类偏移量的表格,因为可能存在多个共享的基类。也就是说visual studio的虚继承实现是通过保存偏移到一个表格中,然后为每个对象添加指针指向对应的偏移,如果编译器需要知道每个父类对象所对应的基类的地址,只需要addr+offset即可。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eTxv99or-1608209419805)(深入探索C-对象模型之C-对象/dimond_vinherit.drawio.svg)]

3.1.8 包含虚函数的菱形继承

class vgrand
{
public:
	virtual void vgrand_virtual_func1();
	virtual void vgrand_virtual_func2();
	virtual void vgrand_virtual_func3();
	virtual void vgrand_virtual_func4();
	virtual void vgrand_virtual_func5();
public:
	int _vgrand_x;
	char _vgrand_ch;
};

class vfather : public vgrand
{
public:
	virtual void vfather_virtual_func1();
	virtual void vfather_virtual_func2();
	virtual void vgrand_virtual_func1();
	virtual void vgrand_virtual_func3();
public:
	char _vfather_ch;
};

class vmother : public vgrand
{
public:
	virtual void vmother_virtual_func1();
	virtual void vmother_virtual_func2();
	virtual void vgrand_virtual_func2();
	virtual void vgrand_virtual_func3();
public:
	char _vmother_ch;
};

class vchild :  public vmother,  public vfather
{
public:
	void vchild_virtual_func();
	virtual void vgrand_virtual_func4();
	virtual void vfather_virtual_func1();
	virtual void vmother_virtual_func1();
public:
	char _vchild_ch;
};
3.1.8.1 不使用虚继承
class vchild    size(56):
        +---
 0      | +--- (base class vmother)
 0      | | +--- (base class vgrand)
 0      | | | {vfptr}
 8      | | | _vgrand_x
12      | | | _vgrand_ch
        | | | <alignment member> (size=3)
        | | +---
16      | | _vmother_ch
        | | <alignment member> (size=7)
        | +---
24      | +--- (base class vfather)
24      | | +--- (base class vgrand)
24      | | | {vfptr}
32      | | | _vgrand_x
36      | | | _vgrand_ch
        | | | <alignment member> (size=3)
        | | +---
40      | | _vfather_ch
        | | <alignment member> (size=7)
        | +---
48      | _vchild_ch
        | <alignment member> (size=7)
        +---

vchild::$vftable@vmother@:
        | &vchild_meta
        |  0
 0      | &vgrand::vgrand_virtual_func1
 1      | &vmother::vgrand_virtual_func2
 2      | &vmother::vgrand_virtual_func3
 3      | &vchild::vgrand_virtual_func4
 4      | &vgrand::vgrand_virtual_func5
 5      | &vchild::vmother_virtual_func1
 6      | &vmother::vmother_virtual_func2

vchild::$vftable@vfather@:
        | -24
 0      | &vfather::vgrand_virtual_func1
 1      | &vgrand::vgrand_virtual_func2
 2      | &vfather::vgrand_virtual_func3
 3      | &thunk: this-=24; goto vchild::vgrand_virtual_func4
 4      | &vgrand::vgrand_virtual_func5
 5      | &vchild::vfather_virtual_func1
 6      | &vfather::vfather_virtual_func2
对象vchild的实例b的大小为:                                                      56
对象vchild的实例b的地址:                                                        0000008C94DFF008
对象vchild的实例b的成员变量vfather::vgrand::_vgrand_x的地址:                    vchild::vfather::vgrand::_vgrand_x                0000008C94DFF028
对象vchild的实例b的成员变量vfather::vgrand::_vgrand_ch的地址:                   vchild::vfather::vgrand::_vgrand_ch               0000008C94DFF02C
对象vchild的实例b的成员变量vfather::_vfather_ch的地址:                          vchild::vfather::_vfather_ch                      0000008C94DFF030
对象vchild的实例b的成员变量vmother::vgrand::_vgrand_x的地址:                    vchild::vmother::vgrand::_vgrand_x                0000008C94DFF010
对象vchild的实例b的成员变量vmother::vgrand::_vgrand_ch的地址:                   vchild::vmother::vgrand::_vgrand_ch               0000008C94DFF014
对象vchild的实例b的成员变量vmother::_vmother_ch的地址:                          vchild::vmother::_vmother_ch                      0000008C94DFF018
对象vchild的实例b的成员变量_vchild_ch的地址:                                    vchild::_vchild_ch                                0000008C94DFF038

第一个虚函数表:0个虚函数执行结果:                            vgrand::vgrand_virtual_func1
对象vchild的第0个虚函数地址:            00007FF7E83F114F1个虚函数执行结果:                            vmother::vgrand_virtual_func2
对象vchild的第1个虚函数地址:            00007FF7E83F12CB
第2个虚函数执行结果:                            vmother::vgrand_virtual_func3
对象vchild的第2个虚函数地址:            00007FF7E83F12673个虚函数执行结果:                            vchild::vgrand_virtual_func4
对象vchild的第3个虚函数地址:            00007FF7E83F12DF
第4个虚函数执行结果:                            vgrand::vgrand_virtual_func5
对象vchild的第4个虚函数地址:            00007FF7E83F13845个虚函数执行结果:                            vchild::vmother_virtual_func1
对象vchild的第5个虚函数地址:            00007FF7E83F11CC
第6个虚函数执行结果:                            vmother::vmother_virtual_func2
对象vchild的第6个虚函数地址:            00007FF7E83F112C

第二个虚函数表:0个虚函数执行结果:                            vfather::vgrand_virtual_func1
对象vchild的第0个虚函数地址:            00007FF7E83F101E
第1个虚函数执行结果:                            vgrand::vgrand_virtual_func2
对象vchild的第1个虚函数地址:            00007FF7E83F100F2个虚函数执行结果:                            vfather::vgrand_virtual_func3
对象vchild的第2个虚函数地址:            00007FF7E83F11183个虚函数执行结果:                            vchild::vgrand_virtual_func4
对象vchild的第3个虚函数地址:            00007FF7E83F14974个虚函数执行结果:                            vgrand::vgrand_virtual_func5
对象vchild的第4个虚函数地址:            00007FF7E83F13845个虚函数执行结果:                            vchild::vfather_virtual_func1
对象vchild的第5个虚函数地址:            00007FF7E83F10326个虚函数执行结果:                            vfather::vfather_virtual_func2
对象vchild的第6个虚函数地址:            00007FF7E83F10B4

  推断得到的对象模型如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iLT9iNeo-1608209419806)(深入探索C-对象模型之C-对象/vdiamond_inherit.drawio.svg)]

3.1.8.2 使用虚继承
#pragma  once

class vgrand
{
public:
	virtual void vgrand_virtual_func1();
	virtual void vgrand_virtual_func2();
	virtual void vgrand_virtual_func3();
	virtual void vgrand_virtual_func4();
	virtual void vgrand_virtual_func5();
public:
	int _vgrand_x;
	char _vgrand_ch;
};

class vfather : virtual public vgrand
{
public:
	virtual void vfather_virtual_func1();
	virtual void vfather_virtual_func2();
	virtual void vgrand_virtual_func1();
	virtual void vgrand_virtual_func3();
public:
	char _vfather_ch;
};

class vmother : virtual public vgrand
{
public:
	virtual void vmother_virtual_func1();
	virtual void vmother_virtual_func2();
	virtual void vgrand_virtual_func2();
	virtual void vgrand_virtual_func3();
public:
	char _vmother_ch;
};

class vchild : public vmother, public vfather
{
public:
	void vchild_virtual_func();
	virtual void vgrand_virtual_func4();
	virtual void vfather_virtual_func1();
	virtual void vmother_virtual_func1();
	virtual void vgrand_virtual_func3();			//如果不对当前函数进行重写,则编译器并无知道运行时应该调用vmother::vgrand_virtual_func3还是vfather::vgrand_virtaul_func3
public:
	char _vchild_ch;
};
class vchild    size(72):
        +---
 0      | +--- (base class vmother)
 0      | | {vfptr}
 8      | | {vbptr}
16      | | _vmother_ch
        | | <alignment member> (size=7)
        | +---
24      | +--- (base class vfather)
24      | | {vfptr}
32      | | {vbptr}
40      | | _vfather_ch
        | | <alignment member> (size=7)
        | +---
48      | _vchild_ch
        | <alignment member> (size=7)
        +---
        +--- (virtual base vgrand)
56      | {vfptr}
64      | _vgrand_x
68      | _vgrand_ch
        | <alignment member> (size=3)
        +---

vchild::$vftable@vmother@:
        | &vchild_meta
        |  0
 0      | &vchild::vmother_virtual_func1
 1      | &vmother::vmother_virtual_func2

vchild::$vftable@vfather@:
        | -24
 0      | &vchild::vfather_virtual_func1
 1      | &vfather::vfather_virtual_func2

vchild::$vbtable@vmother@:
 0      | -8
 1      | 48 (vchildd(vmother+8)vgrand)

vchild::$vbtable@vfather@:
 0      | -8
 1      | 24 (vchildd(vfather+8)vgrand)

vchild::$vftable@vgrand@:
        | -56
 0      | &thunk: this-=8; goto vfather::vgrand_virtual_func1
 1      | &thunk: this-=32; goto vmother::vgrand_virtual_func2
 2      | &vchild::vgrand_virtual_func3
 3      | &vchild::vgrand_virtual_func4
 4      | &vgrand::vgrand_virtual_func5

vchild::vgrand_virtual_func4 this adjustor: 56
vchild::vfather_virtual_func1 this adjustor: 24
vchild::vmother_virtual_func1 this adjustor: 0
vchild::vgrand_virtual_func3 this adjustor: 56
vbi:       class  offset o.vbptr  o.vbte fVtorDisp
          vgrand      56       8       4 0
对象vchild的实例b的大小为:                                                      72
对象vchild的实例b的地址:                                                        00000037DC9CF660
对象vchild的实例b的成员变量vfather::_vgrand_x的地址:                            vchild::vfather::_vgrand_x                        00000037DC9CF6A0
对象vchild的实例b的成员变量vfather::_vgrand_ch的地址:                           vchild::vfather::_vgrand_ch                       00000037DC9CF6A4
对象vchild的实例b的成员变量vfather::_vfather_ch的地址:                          vchild::vfather::_vfather_ch                      00000037DC9CF688
对象vchild的实例b的成员变量vmother::_vgrand_x的地址:                            vchild::vmother::_vgrand_x                        00000037DC9CF6A0
对象vchild的实例b的成员变量vmother::_vgrand_ch的地址:                           vchild::vmother::_vgrand_ch                       00000037DC9CF6A4
对象vchild的实例b的成员变量vmother::_vmother_ch的地址:                          vchild::vmother::_vmother_ch                      00000037DC9CF670
对象vchild的实例b的成员变量_vchild_ch的地址:                                    vchild::_vchild_ch                                00000037DC9CF690

第一个虚函数表:0个虚函数执行结果:                            vchild::vmother_virtual_func1
对象vchild的第0个虚函数地址:            00007FF7C359115E
第1个虚函数执行结果:                            vmother::vmother_virtual_func2
对象vchild的第1个虚函数地址:            00007FF7C35910EB

第二个虚函数表:0个虚函数执行结果:                            vchild::vfather_virtual_func1
对象vchild的第0个虚函数地址:            00007FF7C3591028
第1个虚函数执行结果:                            vfather::vfather_virtual_func2
对象vchild的第1个虚函数地址:            00007FF7C3591091

第三个虚函数表:0个虚函数执行结果:                            vfather::vgrand_virtual_func1
对象vchild的第0个虚函数地址:            00007FF7C3591087
第1个虚函数执行结果:                            vmother::vgrand_virtual_func2
对象vchild的第1个虚函数地址:            00007FF7C359111D
第2个虚函数执行结果:                            vchild::vgrand_virtual_func3
对象vchild的第2个虚函数地址:            00007FF7C35912B7
第3个虚函数执行结果:                            vchild::vgrand_virtual_func4
对象vchild的第3个虚函数地址:            00007FF7C3591212
第4个虚函数执行结果:                            vgrand::vgrand_virtual_func5
对象vchild的第4个虚函数地址:            00007FF7C3591280

  推断到的内存分布如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nBEg4rzz-1608209419807)(深入探索C-对象模型之C-对象/vdiamond_vinherit.drawio.svg)]

3.2 G++

  这里测试的编译器信息:gcc version 7.5.0 (Ubuntu 7.5.0-6ubuntu2),下面会使用g++ -fdump-class-hierarchy [filename]查看类的结构。
  测试代码采用上面同样的代码。

3.2.1 简单对象

Class base
   size=8 align=4
   base size=5 base align=4
base (0x0x7f3b22817960) 0
对象base的实例b的大小为:                                               8
对象base的实例b的地址:                                                 0x7fffd1e71f70
对象base的实例b的成员变量_nonstatic_x的地址:                     base::_nonstatic_x                                0x7fffd1e71f70
对象base的实例b的成员变量_nonstatic_ch的地址:                    base::_nonstatic_ch                               0x7fffd1e71f74
对象base的静态成员变量_static_x的地址:                           base::_static_x                                   0x7feec64a7010

3.2.2 包含虚函数的简单对象

Vtable for virtual_base
virtual_base::_ZTV12virtual_base: 6 entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI12virtual_base)
16    (int (*)(...))virtual_base::virtual_func1
24    (int (*)(...))virtual_base::virtual_func2
32    (int (*)(...))virtual_base::virtual_func3
40    (int (*)(...))virtual_base::virtual_func4

Class virtual_base
   size=16 align=8
   base size=13 base align=8
virtual_base (0x0x7fb0b3ea3900) 0
    vptr=((& virtual_base::_ZTV12virtual_base) + 16)
对象virtual_base的实例b的大小为:                                       16
对象virtual_base的实例b的地址:                                          0x7fffcd756d50
对象virtual_base的实例b的成员变量_nonstatic_x的地址:               virtual_base::_nonstatic_x                        0x7fffcd756d58
对象virtual_base的实例b的成员变量_nonstatic_ch的地址:              virtual_base::_nonstatic_ch                       0x7fffcd756d5c
对象virtual_base的第1个虚函数表地址:    virtual_base::vptr                                0x7fffcd756d500个虚函数执行结果:                            virtual_base::virtual_func1
对象virtual_base的第0个虚函数地址:              0x7f8adc7ce6f21个虚函数执行结果:                            virtual_base::virtual_func2
对象virtual_base的第1个虚函数地址:              0x7f8adc7ce72a2个虚函数执行结果:                            virtual_base::virtual_func3
对象virtual_base的第2个虚函数地址:              0x7f8adc7ce7623个虚函数执行结果:                            virtual_base::virtual_func4
对象virtual_base的第3个虚函数地址:              0x7f8adc7ce79a

3.2.3 简单单继承

Class inherit
   size=8 align=4
   base size=6 base align=4
inherit (0x0x7f420c63d1a0) 0
  base (0x0x7f420c7a79c0) 0
对象inherit的实例b的大小为:                                            8
对象inherit的实例b的地址:                                               0x7fffd71b95a0
对象inherit的实例b的成员变量base::_nonstatic_x的地址:              inherit::base::_nonstatic_x                       0x7fffd71b95a0
对象inherit的实例b的成员变量base::_nonstatic_ch的地址:             inherit::base::_nonstatic_ch                      0x7fffd71b95a4
对象inherit的实例b的成员变量_inherit_ch的地址:                     inherit::_inherit_ch                              0x7fffd71b95a5

  这里的结构和cl不同,cl并不会破坏基类的整体性,而gcc做了内存紧簇。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6T61Jvdv-1608209419808)(深入探索C-对象模型之C-对象/gcc_sinherit.drawio.svg)]

3.2.4 包含虚函数的简单单继承

Vtable for virtual_inherit
virtual_inherit::_ZTV15virtual_inherit: 7 entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI15virtual_inherit)
16    (int (*)(...))virtual_inherit::virtual_func1
24    (int (*)(...))virtual_base::virtual_func2
32    (int (*)(...))virtual_base::virtual_func3
40    (int (*)(...))virtual_base::virtual_func4
48    (int (*)(...))virtual_inherit::virtual_inherit_func

Class virtual_inherit
   size=16 align=8
   base size=14 base align=8
virtual_inherit (0x0x7f8cad7b0138) 0
    vptr=((& virtual_inherit::_ZTV15virtual_inherit) + 16)
  virtual_base (0x0x7f8cad793960) 0
      primary-for virtual_inherit (0x0x7f8cad7b0138)
对象virtual_inherit的实例b的大小为:                                              16
对象virtual_inherit的实例b的地址:                                                 0x7fffdffcdb40
对象virtual_inherit的实例b的成员变量virtual_base::_nonstatic_x的地址:        virtual_inherit::virtual_base::_nonstatic_x       0x7fffdffcdb48
对象virtual_inherit的实例b的成员变量virtual_base::_nonstatic_ch的地址:       virtual_inherit::virtual_base::_nonstatic_ch      0x7fffdffcdb4c
对象virtual_inherit的实例b的成员变量_virtual_inherit_ch的地址:               virtual_inherit::_virtual_inherit_ch              0x7fffdffcdb4d
对象virtual_inherit的第1个虚函数表地址: virtual_inherit::vptr                             0x7fffdffcdb400个虚函数执行结果:                            virtual_inherit::virtual_func1
对象virtual_base的第0个虚函数地址:              0x7f94adef98301个虚函数执行结果:                            virtual_base::virtual_func2
对象virtual_base的第1个虚函数地址:              0x7f94adef972a2个虚函数执行结果:                            virtual_base::virtual_func3
对象virtual_base的第2个虚函数地址:              0x7f94adef97623个虚函数执行结果:                            virtual_base::virtual_func4
对象virtual_base的第3个虚函数地址:              0x7f94adef979a4个虚函数执行结果:                            virtual_inherit::virtual_inherit_func
对象virtual_base的第4个虚函数地址:              0x7f94adef9868

  其内存结构推断如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZN6Od29s-1608209419808)(深入探索C-对象模型之C-对象/gcc_vsinherit.drawio.svg)]

3.2.5 简单多继承

Class minherit
   size=20 align=4
   base size=17 base align=4
minherit (0x0x7fda3561e2a0) 0
  base_right (0x0x7fda35777a20) 0
  base_left (0x0x7fda35777a80) 8
对象minherit的实例b的大小为:                                                     20
对象minherit的实例b的地址:                                                        0x7ffff40425c0
对象minherit的实例b的成员变量base_left::_base_left_int的地址:                minherit::base_left::_base_left_int               0x7ffff40425c8
对象minherit的实例b的成员变量base_left::_base_left_ch的地址:                 minherit::base_left::_base_left_ch                0x7ffff40425cc
对象minherit的实例b的成员变量base_right::_base_right_int的地址:              minherit::base_right::_base_right_int             0x7ffff40425c0
对象minherit的实例b的成员变量base_right::_base_right_ch的地址:               minherit::base_right::_base_right_ch              0x7ffff40425c4
对象minherit的实例b的成员变量_minherit_ch的地址:                             minherit::_minherit_ch                            0x7ffff40425d0

3.2.6 包含虚函数的多继承

Vtable for vminherit
vminherit::_ZTV9vminherit: 10 entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI9vminherit)
16    (int (*)(...))vminherit::vbase_left_virtual_function1
24    (int (*)(...))vbase_left::vbase_left_virtual_function2
32    (int (*)(...))vminherit::vminherit_virtual_function
40    (int (*)(...))vminherit::vbase_right_virtual_function1
48    (int (*)(...))-16
56    (int (*)(...))(& _ZTI9vminherit)
64    (int (*)(...))vminherit::_ZThn16_N9vminherit29vbase_right_virtual_function1Ev
72    (int (*)(...))vbase_right::vbase_right_virtual_function2

Class vminherit
   size=32 align=8
   base size=30 base align=8
vminherit (0x0x7f37ec85e380) 0
    vptr=((& vminherit::_ZTV9vminherit) + 16)
  vbase_left (0x0x7f37ec4239c0) 0
      primary-for vminherit (0x0x7f37ec85e380)
  vbase_right (0x0x7f37ec423a20) 16
      vptr=((& vminherit::_ZTV9vminherit) + 64)
对象vminherit的实例b的大小为:                                                    32
对象vminherit的实例b的地址:                                                       0x7fffcded6160
对象vminherit的实例b的成员变量vbase_left::_base_left_int的地址:              vminherit::vbase_left::_base_left_int             0x7fffcded6168
对象vminherit的实例b的成员变量vbase_left::_base_left_ch的地址:               vminherit::vbase_left::_base_left_ch              0x7fffcded616c
对象vminherit的实例b的成员变量vbase_right::_base_right_int的地址:            vminherit::vbase_right::_base_right_int           0x7fffcded6178
对象vminherit的实例b的成员变量vbase_right::_base_right_ch的地址:             vminherit::vbase_right::_base_right_ch            0x7fffcded617c
对象vminherit的实例b的成员变量_minherit_ch的地址:                            vminherit::_minherit_ch                           0x7fffcded617d

第一个虚函数表:
对象vminherit的第1个虚函数表地址:       vminherit::vptr                                   0x7fffcded61600个虚函数执行结果:                            vminherit::vbase_left_virtual_function1
对象vminherit的第0个虚函数地址:         0x7f1d216b39ce1个虚函数执行结果:                            vbase_left::vbase_left_virtual_function2
对象vminherit的第1个虚函数地址:         0x7f1d216b39262个虚函数执行结果:                            vminherit::vminherit_virtual_function
对象vminherit的第2个虚函数地址:         0x7f1d216b3a443个虚函数执行结果:                            vminherit::vbase_right_virtual_function1
对象vminherit的第3个虚函数地址:         0x7f1d216b3a06

第二个虚函数表:
对象vminherit的第2个虚函数表地址:       vminherit::vptr                                   0x7fffcded61700个虚函数执行结果:                            vminherit::vbase_right_virtual_function1
对象vminherit的第0个虚函数地址:         0x7f1d216b3a3d1个虚函数执行结果:                            vbase_right::vbase_right_virtual_function2
对象vminherit的第1个虚函数地址:         0x7f1d216b3996

  从上面的测试结果能够看到第一个虚函数表中多了一个第二个基类的一个虚函数的副本,该虚函数是被子类重写过得,未重写的仍然在原来的表格中。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gY2cxMKh-1608209419809)(深入探索C-对象模型之C-对象/gcc_vminherit.drawio.svg)]

3.2.7 不包含虚函数的菱形继承

3.2.7.1 不使用虚继承
Class child
   size=24 align=4
   base size=22 base align=4
child (0x0x7f2f78f1e310) 0
  mother (0x0x7f2f78f0d270) 0
    grand (0x0x7f2f79077a80) 0
  father (0x0x7f2f78f0d2d8) 12
    grand (0x0x7f2f79077ae0) 12
对象child的实例b的大小为:                                                        24
对象child的实例b的地址:                                                           0x7fffeff730a0
对象child的实例b的成员变量father::_grand_x的地址:                            child::father::_grand_x                           0x7fffeff730ac
对象child的实例b的成员变量father::_grand_ch的地址:                           child::father::_grand_ch                          0x7fffeff730b0
对象child的实例b的成员变量father::_father_ch的地址:                          child::father::_father_ch                         0x7fffeff730b4
对象child的实例b的成员变量mother::_grand_x的地址:                            child::mother::_grand_x                           0x7fffeff730a0
对象child的实例b的成员变量mother::_grand_ch的地址:                           child::mother::_grand_ch                          0x7fffeff730a4
对象child的实例b的成员变量mother::_mother_ch的地址:                          child::mother::_mother_ch                         0x7fffeff730a8
对象child的实例b的成员变量_child_ch的地址:                                   child::_child_ch                                  0x7fffeff730b5

  内存结构基本和vs相同,只是内存紧缩的问题。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-73vElKaQ-1608209419810)(深入探索C-对象模型之C-对象/gcc_dimond_inherit.drawio.svg)]

3.2.7.2 使用虚继承
Vtable for child
child::_ZTV5child: 6 entries
0     28
8     (int (*)(...))0
16    (int (*)(...))(& _ZTI5child)
24    12
32    (int (*)(...))-16
40    (int (*)(...))(& _ZTI5child)

Construction vtable for mother (0x0x7fe8eab9d270 instance) in child
child::_ZTC5child0_6mother: 3 entries
0     28
8     (int (*)(...))0
16    (int (*)(...))(& _ZTI6mother)

Construction vtable for father (0x0x7fe8eab9d2d8 instance) in child
child::_ZTC5child16_6father: 3 entries
0     12
8     (int (*)(...))0
16    (int (*)(...))(& _ZTI6father)

VTT for child
child::_ZTT5child: 4 entries
0     ((& child::_ZTV5child) + 24)
8     ((& child::_ZTC5child0_6mother) + 24)
16    ((& child::_ZTC5child16_6father) + 24)
24    ((& child::_ZTV5child) + 48)

Class child
   size=40 align=8
   base size=26 base align=8
child (0x0x7fe8eabae310) 0
    vptridx=0 vptr=((& child::_ZTV5child) + 24)
  mother (0x0x7fe8eab9d270) 0
      primary-for child (0x0x7fe8eabae310)
      subvttidx=8
    grand (0x0x7fe8ead07a80) 28 virtual
        vbaseoffset=-24
  father (0x0x7fe8eab9d2d8) 16
      subvttidx=16 vptridx=24 vptr=((& child::_ZTV5child) + 48)
    grand (0x0x7fe8ead07a80) alternative-path
对象child的实例b的大小为:                                                        40
对象child的实例b的地址:                                                           0x7fffe265d4a0
对象child的实例b的成员变量father::_grand_x的地址:                            child::father::_grand_x                           0x7fffe265d4bc
对象child的实例b的成员变量father::_grand_ch的地址:                           child::father::_grand_ch                          0x7fffe265d4c0
对象child的实例b的成员变量father::_father_ch的地址:                          child::father::_father_ch                         0x7fffe265d4b8
对象child的实例b的成员变量mother::_grand_x的地址:                            child::mother::_grand_x                           0x7fffe265d4bc
对象child的实例b的成员变量mother::_grand_ch的地址:                           child::mother::_grand_ch                          0x7fffe265d4c0
对象child的实例b的成员变量mother::_mother_ch的地址:                          child::mother::_mother_ch                         0x7fffe265d4a8
对象child的实例b的成员变量_child_ch的地址:                                   child::_child_ch                                  0x7fffe265d4b9

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-amQmZJaH-1608209419810)(深入探索C-对象模型之C-对象/gcc_dimond_vinherit.drawio.svg)]

3.2.8 包含虚函数的菱形继承

3.2.8.1 不使用虚继承
Class vchild
   size=32 align=8
   base size=31 base align=8
vchild (0x0x7fc36bc6e3f0) 0
    vptr=((& vchild::_ZTV6vchild) + 16)
  vmother (0x0x7fc36b850208) 0
      primary-for vchild (0x0x7fc36bc6e3f0)
    vgrand (0x0x7fc36b833a20) 0
        primary-for vmother (0x0x7fc36b850208)
  vfather (0x0x7fc36b850270) 16
      vptr=((& vchild::_ZTV6vchild) + 96)
    vgrand (0x0x7fc36b833a80) 16
        primary-for vfather (0x0x7fc36b850270)
对象vchild的实例b的大小为:                                                       32
对象vchild的实例b的地址:                                                          0x7fffdeff1740
对象vchild的实例b的成员变量vfather::_vgrand_x的地址:                         vchild::vfather::_vgrand_x                        0x7fffdeff1758
对象vchild的实例b的成员变量vfather::_vgrand_ch的地址:                        vchild::vfather::_vgrand_ch                       0x7fffdeff175c
对象vchild的实例b的成员变量vfather::_vfather_ch的地址:                       vchild::vfather::_vfather_ch                      0x7fffdeff175d
对象vchild的实例b的成员变量vmother::_vgrand_x的地址:                         vchild::vmother::_vgrand_x                        0x7fffdeff1748
对象vchild的实例b的成员变量vmother::_vgrand_ch的地址:                        vchild::vmother::_vgrand_ch                       0x7fffdeff174c
对象vchild的实例b的成员变量vmother::_vmother_ch的地址:                       vchild::vmother::_vmother_ch                      0x7fffdeff174d
对象vchild的实例b的成员变量_vchild_ch的地址:                                 vchild::_vchild_ch                                0x7fffdeff175e

第一个虚函数表:
对象vchild的第1个虚函数表地址:  vchild::vptr                                      0x7fffdeff17400个虚函数执行结果:                            vgrand_virtual_func1
对象vchild的第0个虚函数地址:            0x7f48bf84a2421个虚函数执行结果:                            vgrand_virtual_func2
对象vchild的第1个虚函数地址:            0x7f48bf84a4aa2个虚函数执行结果:                            vgrand_virtual_func3
对象vchild的第2个虚函数地址:            0x7f48bf84a6063个虚函数执行结果:                            vgrand_virtual_func4
对象vchild的第3个虚函数地址:            0x7f48bf84a5904个虚函数执行结果:                            vgrand_virtual_func5
对象vchild的第4个虚函数地址:            0x7f48bf84a3225个虚函数执行结果:                            vmother_virtual_func1
对象vchild的第5个虚函数地址:            0x7f48bf84a5ce6个虚函数执行结果:                            vmother_virtual_func2
对象vchild的第6个虚函数地址:            0x7f48bf84a472

第二个虚函数表:
对象vchild的第1个虚函数表地址:  vchild::vptr                                      0x7fffdeff17500个虚函数执行结果:                            vgrand_virtual_func1
对象vchild的第0个虚函数地址:            0x7f48bf84a3ca1个虚函数执行结果:                            vgrand_virtual_func2
对象vchild的第1个虚函数地址:            0x7f48bf84a27a2个虚函数执行结果:                            vgrand_virtual_func3
对象vchild的第2个虚函数地址:            0x7f48bf84a63d3个虚函数执行结果:                            vgrand_virtual_func4
对象vchild的第3个虚函数地址:            0x7f48bf84a5c74个虚函数执行结果:                            vgrand_virtual_func5
对象vchild的第4个虚函数地址:            0x7f48bf84a3225个虚函数执行结果:                            vfather_virtual_func1
对象vchild的第5个虚函数地址:            0x7f48bf84a5896个虚函数执行结果:                            vfather_virtual_func2
对象vchild的第6个虚函数地址:            0x7f48bf84a392

  基本的结构还是和vs差不多,只是内存紧缩。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bkW6Tbyw-1608209419811)(深入探索C-对象模型之C-对象/gcc_vdiamond_inherit.drawio.svg)]

3.2.8.2 使用虚继承
VTT for vchild
vchild::_ZTT6vchild: 7 entries
0     ((& vchild::_ZTV6vchild) + 24)
8     ((& vchild::_ZTC6vchild0_7vmother) + 24)
16    ((& vchild::_ZTC6vchild0_7vmother) + 112)
24    ((& vchild::_ZTC6vchild16_7vfather) + 24)
32    ((& vchild::_ZTC6vchild16_7vfather) + 112)
40    ((& vchild::_ZTV6vchild) + 184)
48    ((& vchild::_ZTV6vchild) + 96)

Class vchild
   size=48 align=8
   base size=26 base align=8
vchild (0x0x7f748bf4e3f0) 0
    vptridx=0 vptr=((& vchild::_ZTV6vchild) + 24)
  vmother (0x0x7f748bb302d8) 0
      primary-for vchild (0x0x7f748bf4e3f0)
      subvttidx=8
    vgrand (0x0x7f748bb13a20) 32 virtual
        vptridx=40 vbaseoffset=-24 vptr=((& vchild::_ZTV6vchild) + 184)
  vfather (0x0x7f748bb30340) 16
      subvttidx=24 vptridx=48 vptr=((& vchild::_ZTV6vchild) + 96)
    vgrand (0x0x7f748bb13a20) alternative-path
对象vchild的实例b的大小为:                                                       48
对象vchild的实例b的地址:                                                          0x7ffff30b0210
对象vchild的实例b的成员变量vfather::_vgrand_x的地址:                         vchild::vfather::_vgrand_x                        0x7ffff30b0238
对象vchild的实例b的成员变量vfather::_vgrand_ch的地址:                        vchild::vfather::_vgrand_ch                       0x7ffff30b023c
对象vchild的实例b的成员变量vfather::_vfather_ch的地址:                       vchild::vfather::_vfather_ch                      0x7ffff30b0228
对象vchild的实例b的成员变量vmother::_vgrand_x的地址:                         vchild::vmother::_vgrand_x                        0x7ffff30b0238
对象vchild的实例b的成员变量vmother::_vgrand_ch的地址:                        vchild::vmother::_vgrand_ch                       0x7ffff30b023c
对象vchild的实例b的成员变量vmother::_vmother_ch的地址:                       vchild::vmother::_vmother_ch                      0x7ffff30b0218
对象vchild的实例b的成员变量_vchild_ch的地址:                                 vchild::_vchild_ch                                0x7ffff30b0229

第一个虚函数表:
对象vchild的第1个虚函数表地址:  vchild::vptr                                      0x7ffff30b02100个虚函数执行结果:                            vchild::vmother_virtual_func1
对象vchild的第0个虚函数地址:            0x7f19968aa71a1个虚函数执行结果:                            vmother::vmother_virtual_func2
对象vchild的第1个虚函数地址:            0x7f19968aa53a2个虚函数执行结果:                            vmother::vgrand_virtual_func2
对象vchild的第2个虚函数地址:            0x7f19968aa5843个虚函数执行结果:                            vchild::vgrand_virtual_func3
对象vchild的第3个虚函数地址:            0x7f19968aa7644个虚函数执行结果:                            vchild::vgrand_virtual_func4
对象vchild的第4个虚函数地址:            0x7f19968aa6c65个虚函数执行结果:                            vchild::vfather_virtual_func1
对象vchild的第5个虚函数地址:            0x7f19968aa676

第二个虚函数表:
对象vchild的第2个虚函数表地址:  vchild::vptr                                      0x7ffff30b02200个虚函数执行结果:                            vchild::vfather_virtual_func1
对象vchild的第0个虚函数地址:            0x7f19968aa6c01个虚函数执行结果:                            vfather::vfather_virtual_func2
对象vchild的第1个虚函数地址:            0x7f19968aa3fe2个虚函数执行结果:                            vfather::vgrand_virtual_func1
对象vchild的第2个虚函数地址:            0x7f19968aa4483个虚函数执行结果:                            vchild::vgrand_virtual_func3
对象vchild的第3个虚函数地址:            0x7f19968aa7b7

第三个虚函数表:
对象vchild的第3个虚函数表地址:  vchild::vptr                                      0x7ffff30b02300个虚函数执行结果:                            vfather::vgrand_virtual_func1
对象vchild的第0个虚函数地址:            0x7f19968aa4921个虚函数执行结果:                            vmother::vgrand_virtual_func2
对象vchild的第1个虚函数地址:            0x7f19968aa5ce2个虚函数执行结果:                            vchild::vgrand_virtual_func3
对象vchild的第2个虚函数地址:            0x7f19968aa7ae3个虚函数执行结果:                            vchild::vgrand_virtual_func4
对象vchild的第3个虚函数地址:            0x7f19968aa7104个虚函数执行结果:                            vgrand::vgrand_virtual_func5
对象vchild的第4个虚函数地址:            0x7f19968aa36a

  可以看到gcc类中不存在vbptr,即用来指出基类的指针了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KES33q15-1608209419811)(深入探索C-对象模型之C-对象/gcc_vdiamond_vinherit.drawio.svg)]

3.3 Clang

  clang测试版本

clang version 10.0.0-4ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix

  测试过程中会对内存模型和gcc,vs对比,如果和二者都不相同则会画出结构图,否则会说明,无说明,则表示三者都相同。
  从下面的测试中将会看到,clang的处理方式和gcc类似,只是clang的函数存放在地址较低的地方。

3.3.1 简单对象

对象base的实例b的地址:                                                            0x7fffee8e1288
对象base的实例b的成员变量_nonstatic_x的地址:                                 base::_nonstatic_x                                0x7fffee8e1288
对象base的实例b的成员变量_nonstatic_ch的地址:                                base::_nonstatic_ch                               0x7fffee8e128c
对象base的静态成员变量_static_x的地址:                                       base::_static_x                                        0x40b088

3.3.2 包含虚函数的简单对象

对象virtual_base的实例b的大小为:                                                 16
对象virtual_base的实例b的地址:                                                    0x7fffc80cc3e0
对象virtual_base的实例b的成员变量_nonstatic_x的地址:                         virtual_base::_nonstatic_x                        0x7fffc80cc3e8
对象virtual_base的实例b的成员变量_nonstatic_ch的地址:                        virtual_base::_nonstatic_ch                       0x7fffc80cc3ec
对象virtual_base的第1个虚函数表地址:    virtual_base::vptr                                0x7fffc80cc3e00个虚函数执行结果:                            virtual_base::virtual_func1
对象virtual_base的第0个虚函数地址:              0x401c001个虚函数执行结果:                            virtual_base::virtual_func2
对象virtual_base的第1个虚函数地址:              0x401c402个虚函数执行结果:                            virtual_base::virtual_func3
对象virtual_base的第2个虚函数地址:              0x401c803个虚函数执行结果:                            virtual_base::virtual_func4
对象virtual_base的第3个虚函数地址:              0x401cc0

3.3.3 简单单继承

对象inherit的实例b的大小为:                                                      8
对象inherit的实例b的地址:                                                         0x7fffddb5d388
对象inherit的实例b的成员变量base::_nonstatic_x的地址:                        inherit::base::_nonstatic_x                       0x7fffddb5d388
对象inherit的实例b的成员变量base::_nonstatic_ch的地址:                       inherit::base::_nonstatic_ch                      0x7fffddb5d38c
对象inherit的实例b的成员变量_inherit_ch的地址:                               inherit::_inherit_ch                              0x7fffddb5d38d

3.3.4 包含虚函数的简单单继承

对象virtual_inherit的实例b的大小为:                                              16
对象virtual_inherit的实例b的地址:                                                 0x7fffc3795c60
对象virtual_inherit的实例b的成员变量virtual_base::_nonstatic_x的地址:        virtual_inherit::virtual_base::_nonstatic_x       0x7fffc3795c68
对象virtual_inherit的实例b的成员变量virtual_base::_nonstatic_ch的地址:       virtual_inherit::virtual_base::_nonstatic_ch      0x7fffc3795c6c
对象virtual_inherit的实例b的成员变量_virtual_inherit_ch的地址:               virtual_inherit::_virtual_inherit_ch              0x7fffc3795c6d
对象virtual_inherit的第1个虚函数表地址: virtual_inherit::vptr                             0x7fffc3795c600个虚函数执行结果:                            virtual_inherit::virtual_func1
对象virtual_base的第0个虚函数地址:              0x401d001个虚函数执行结果:                            virtual_base::virtual_func2
对象virtual_base的第1个虚函数地址:              0x401c402个虚函数执行结果:                            virtual_base::virtual_func3
对象virtual_base的第2个虚函数地址:              0x401c803个虚函数执行结果:                            virtual_base::virtual_func4
对象virtual_base的第3个虚函数地址:              0x401cc04个虚函数执行结果:                            virtual_inherit::virtual_inherit_func
对象virtual_base的第4个虚函数地址:              0x401d40

3.3.5 简单多继承

对象minherit的实例b的大小为:                                                     20
对象minherit的实例b的地址:                                                        0x7fffc14c2c58
对象minherit的实例b的成员变量base_left::_base_left_int的地址:                minherit::base_left::_base_left_int               0x7fffc14c2c60
对象minherit的实例b的成员变量base_left::_base_left_ch的地址:                 minherit::base_left::_base_left_ch                0x7fffc14c2c64
对象minherit的实例b的成员变量base_right::_base_right_int的地址:              minherit::base_right::_base_right_int             0x7fffc14c2c58
对象minherit的实例b的成员变量base_right::_base_right_ch的地址:               minherit::base_right::_base_right_ch              0x7fffc14c2c5c
对象minherit的实例b的成员变量_minherit_ch的地址:                             minherit::_minherit_ch                            0x7fffc14c2c68

3.3.6 包含虚函数的多继承

对象vminherit的实例b的大小为:                                                    32
对象vminherit的实例b的地址:                                                       0x7fffdd0afb40
对象vminherit的实例b的成员变量vbase_left::_base_left_int的地址:              vminherit::vbase_left::_base_left_int             0x7fffdd0afb48
对象vminherit的实例b的成员变量vbase_left::_base_left_ch的地址:               vminherit::vbase_left::_base_left_ch              0x7fffdd0afb4c
对象vminherit的实例b的成员变量vbase_right::_base_right_int的地址:            vminherit::vbase_right::_base_right_int           0x7fffdd0afb58
对象vminherit的实例b的成员变量vbase_right::_base_right_ch的地址:             vminherit::vbase_right::_base_right_ch            0x7fffdd0afb5c
对象vminherit的实例b的成员变量_minherit_ch的地址:                            vminherit::_minherit_ch                           0x7fffdd0afb5d

第一个虚函数表:
对象vminherit的第1个虚函数表地址:       vminherit::vptr                                   0x7fffdd0afb400个虚函数执行结果:                            vminherit::vbase_left_virtual_function1
对象vminherit的第0个虚函数地址:         0x401e801个虚函数执行结果:                            vbase_left::vbase_left_virtual_function2
对象vminherit的第1个虚函数地址:         0x401dc02个虚函数执行结果:                            vminherit::vminherit_virtual_function
对象vminherit的第2个虚函数地址:         0x401f203个虚函数执行结果:                            vminherit::vbase_right_virtual_function1
对象vminherit的第3个虚函数地址:         0x401ec0

第二个虚函数表:
对象vminherit的第2个虚函数表地址:       vminherit::vptr                                   0x7fffdd0afb500个虚函数执行结果:                            vminherit::vbase_right_virtual_function1
对象vminherit的第0个虚函数地址:         0x401f001个虚函数执行结果:                            vbase_right::vbase_right_virtual_function2
对象vminherit的第1个虚函数地址:         0x401e40

3.3.7 不包含虚函数的菱形继承

3.3.7.1 不使用虚继承
对象child的实例b的大小为:                                                        24
对象child的实例b的地址:                                                           0x7fffd2016958
对象child的实例b的成员变量father::_grand_x的地址:                            child::father::_grand_x                           0x7fffd2016964
对象child的实例b的成员变量father::_grand_ch的地址:                           child::father::_grand_ch                          0x7fffd2016968
对象child的实例b的成员变量father::_father_ch的地址:                          child::father::_father_ch                         0x7fffd201696c
对象child的实例b的成员变量mother::_grand_x的地址:                            child::mother::_grand_x                           0x7fffd2016958
对象child的实例b的成员变量mother::_grand_ch的地址:                           child::mother::_grand_ch                          0x7fffd201695c
对象child的实例b的成员变量mother::_mother_ch的地址:                          child::mother::_mother_ch                         0x7fffd2016960
对象child的实例b的成员变量_child_ch的地址:                                   child::_child_ch                                  0x7fffd201696d
3.3.7.2 使用虚继承
对象child的实例b的大小为:                                                        40
对象child的实例b的地址:                                                           0x7ffffb828c28
对象child的实例b的成员变量father::_grand_x的地址:                            child::father::_grand_x                           0x7ffffb828c44
对象child的实例b的成员变量father::_grand_ch的地址:                           child::father::_grand_ch                          0x7ffffb828c48
对象child的实例b的成员变量father::_father_ch的地址:                          child::father::_father_ch                         0x7ffffb828c40
对象child的实例b的成员变量mother::_grand_x的地址:                            child::mother::_grand_x                           0x7ffffb828c44
对象child的实例b的成员变量mother::_grand_ch的地址:                           child::mother::_grand_ch                          0x7ffffb828c48
对象child的实例b的成员变量mother::_mother_ch的地址:                          child::mother::_mother_ch                         0x7ffffb828c30
对象child的实例b的成员变量_child_ch的地址:                                   child::_child_ch                                  0x7ffffb828c41

3.3.8 包含虚函数的菱形继承

3.3.8.1 不使用虚继承
对象vchild的实例b的大小为:                                                       32
对象vchild的实例b的地址:                                                          0x7ffffa3dba50
对象vchild的实例b的成员变量vfather::_vgrand_x的地址:                         vchild::vfather::_vgrand_x                        0x7ffffa3dba68
对象vchild的实例b的成员变量vfather::_vgrand_ch的地址:                        vchild::vfather::_vgrand_ch                       0x7ffffa3dba6c
对象vchild的实例b的成员变量vfather::_vfather_ch的地址:                       vchild::vfather::_vfather_ch                      0x7ffffa3dba6d
对象vchild的实例b的成员变量vmother::_vgrand_x的地址:                         vchild::vmother::_vgrand_x                        0x7ffffa3dba58
对象vchild的实例b的成员变量vmother::_vgrand_ch的地址:                        vchild::vmother::_vgrand_ch                       0x7ffffa3dba5c
对象vchild的实例b的成员变量vmother::_vmother_ch的地址:                       vchild::vmother::_vmother_ch                      0x7ffffa3dba5d
对象vchild的实例b的成员变量_vchild_ch的地址:                                 vchild::_vchild_ch                                0x7ffffa3dba6e

第一个虚函数表:
对象vchild的第1个虚函数表地址:  vchild::vptr                                      0x7ffffa3dba500个虚函数执行结果:                            vgrand::vgrand_virtual_func1
对象vchild的第0个虚函数地址:            0x4013f01个虚函数执行结果:                            vmother::vgrand_virtual_func2
对象vchild的第1个虚函数地址:            0x4018102个虚函数执行结果:                            vchild::vgrand_virtual_func3
对象vchild的第2个虚函数地址:            0x401a903个虚函数执行结果:                            vchild::vgrand_virtual_func4
对象vchild的第3个虚函数地址:            0x4019b04个虚函数执行结果:                            vgrand::vgrand_virtual_func5
对象vchild的第4个虚函数地址:            0x4015705个虚函数执行结果:                            vchild::vmother_virtual_func1
对象vchild的第5个虚函数地址:            0x401a306个虚函数执行结果:                            vmother::vmother_virtual_func2
对象vchild的第6个虚函数地址:            0x4017b0

第二个虚函数表:
对象vchild的第1个虚函数表地址:  vchild::vptr                                      0x7ffffa3dba600个虚函数执行结果:                            vfather::vgrand_virtual_func1
对象vchild的第0个虚函数地址:            0x4016901个虚函数执行结果:                            vgrand::vgrand_virtual_func2
对象vchild的第1个虚函数地址:            0x4014502个虚函数执行结果:                            vchild::vgrand_virtual_func3
对象vchild的第2个虚函数地址:            0x401af03个虚函数执行结果:                            vchild::vgrand_virtual_func4
对象vchild的第3个虚函数地址:            0x401a104个虚函数执行结果:                            vgrand::vgrand_virtual_func5
对象vchild的第4个虚函数地址:            0x4015705个虚函数执行结果:                            vchild::vfather_virtual_func1
对象vchild的第5个虚函数地址:            0x4019906个虚函数执行结果:                            vfather::vfather_virtual_func2
3.3.8.2 使用虚继承
对象vchild的实例b的大小为:                                                       48
对象vchild的实例b的地址:                                                          0x7fffe5bb37e0
对象vchild的实例b的成员变量vfather::_vgrand_x的地址:                         vchild::vfather::_vgrand_x                        0x7fffe5bb3808
对象vchild的实例b的成员变量vfather::_vgrand_ch的地址:                        vchild::vfather::_vgrand_ch                       0x7fffe5bb380c
对象vchild的实例b的成员变量vfather::_vfather_ch的地址:                       vchild::vfather::_vfather_ch                      0x7fffe5bb37f8
对象vchild的实例b的成员变量vmother::_vgrand_x的地址:                         vchild::vmother::_vgrand_x                        0x7fffe5bb3808
对象vchild的实例b的成员变量vmother::_vgrand_ch的地址:                        vchild::vmother::_vgrand_ch                       0x7fffe5bb380c
对象vchild的实例b的成员变量vmother::_vmother_ch的地址:                       vchild::vmother::_vmother_ch                      0x7fffe5bb37e8
对象vchild的实例b的成员变量_vchild_ch的地址:                                 vchild::_vchild_ch                                0x7fffe5bb37f9

第一个虚函数表:
对象vchild的第1个虚函数表地址:  vchild::vptr                                      0x7fffe5bb37e00个虚函数执行结果:                            vchild::vmother_virtual_func1
对象vchild的第0个虚函数地址:            0x401ab01个虚函数执行结果:                            vmother::vmother_virtual_func2
对象vchild的第1个虚函数地址:            0x4017f02个虚函数执行结果:                            vmother::vgrand_virtual_func2
对象vchild的第2个虚函数地址:            0x4018503个虚函数执行结果:                            vchild::vgrand_virtual_func3
对象vchild的第3个虚函数地址:            0x401b104个虚函数执行结果:                            vchild::vgrand_virtual_func4
对象vchild的第4个虚函数地址:            0x401a305个虚函数执行结果:                            vchild::vfather_virtual_func1
对象vchild的第5个虚函数地址:            0x4019b0

第二个虚函数表:
对象vchild的第2个虚函数表地址:  vchild::vptr                                      0x7fffe5bb37f00个虚函数执行结果:                            vchild::vfather_virtual_func1
对象vchild的第0个虚函数地址:            0x401a101个虚函数执行结果:                            vfather::vfather_virtual_func2
对象vchild的第1个虚函数地址:            0x4016302个虚函数执行结果:                            vfather::vgrand_virtual_func1
对象vchild的第2个虚函数地址:            0x4016903个虚函数执行结果:                            vchild::vgrand_virtual_func3
对象vchild的第3个虚函数地址:            0x401b70

第三个虚函数表:
对象vchild的第3个虚函数表地址:  vchild::vptr                                      0x7fffe5bb38000个虚函数执行结果:                            vfather::vgrand_virtual_func1
对象vchild的第0个虚函数地址:            0x4016f01个虚函数执行结果:                            vmother::vgrand_virtual_func2
对象vchild的第1个虚函数地址:            0x4018b02个虚函数执行结果:                            vchild::vgrand_virtual_func3
对象vchild的第2个虚函数地址:            0x401b903个虚函数执行结果:                            vchild::vgrand_virtual_func4
对象vchild的第3个虚函数地址:            0x401a904个虚函数执行结果:                            vgrand::vgrand_virtual_func5
对象vchild的第4个虚函数地址:            0x401570

3.4 总结

  三个编译器vs(实际上为cl.exe,此处简称vs大家都好明白),clang,gcc对内存对象布局大体类似。其中clanggcc完全相同,只是函数地址存放位置clang存放在地址较低的地方,并且clanggcc都会对对象做内存紧缩,这样会破坏对于c的数据结构完整性兼容。
  vsclang,gcc的主要区别:

  1. clanggcc会做内存紧缩,vs并没有做;
  2. clanggcc
  3. 在包含虚函数表的菱形继承中,vs会保留vfptr,vbptr,分别指向虚函数表和共享基类的偏移,而clang,gcc只保留了vfptr,应该在其他地方存储了偏移。
  4. 在包含虚函数表的菱形继承中,vs和其他两个编译器生成的对象的虚函数表中的内容不同;
  5. 在包含虚函数的多继承中,gccclang在第一个虚函数表多维护了一个被子类重写的虚函数的复本,不知为何。

4 参考

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
gcc/clang是常见的C/C++编译器,而VS Code和Vim则是两种流行的文本编辑器。下面我将分别介绍它们的特点和用途。 gccclang是两种开源的编译器,用于将C/C++源代码转换为可执行文件。它们都具有高度的兼容性和优化功能,支持多个操作系统。gcc是GNU编译器集合的一部分,被广泛用于Linux系统,而clang则是一个较新的编译器,具有更好的错误报告和诊断功能。它们都有广泛的社区支持,并且被广泛应用于C/C++开发。 VS Code是一种功能强大的源代码编辑器,由微软开发,并支持各种编程语言。它具有丰富的插件生态系统,可以通过安装插件来扩展其功能。VS Code具有智能代码补全、调试功能、版本控制集成等特点,能够提高开发效率。它还支持多种操作系统,因此非常适合团队合作和跨平台开发。 Vim是一种经典的文本编辑器, UNIX系统上的“vi”的改进版本。它是一个模态编辑器,使用键盘快捷键进行操作,具有高度的定制性和可扩展性。Vim提供各种高级编辑功能,如宏录制、多重撤销和自动完成。由于其高效的编辑方式和卓越的性能,Vim经常被程序员用于编写代码和编辑文本文件。 总结来说,gcc/clang是用于编译C/C++代码的工具,而VS Code和Vim则是常见的代码编辑器。它们分别具有不同的特点和用途,根据个人需求和偏好可以选择适合自己的工具和编辑器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值