虚函数 虚继承 C++ vc ++ g++内存区别

本人使用的是vc,根据阅读其他人的文章以及自己的实际验证,

目前,了解到的区别主要有两点:

 

大致说明虚函数与虚继承:

父类如果有虚函数,在父类对象的内存中会有一个vfptr指向虚函数的位置;

子类虚继承于父类,子类会拥有一个vbptr记录偏移量。

 

子类虚继承父类,会将父类的vfptr一并继承,例如父类有两个int,那子类对象里面就会有12个来自父类的字节,两个int和一个vfptr。

同时自己会有一个vbptr和自己的数据,比如说两个int,这里的子类就是12+12(自己的两个int和一个vbptr)。

如果是gcc,这里就结束了

 

vc就不一样了,这也是我怎么算都算不对的原因。

1.在gcc编译器下,父类与子类是共享vfptr的,也就是说,无论子类有没有重新构造虚函数,或者加入新的虚函数。

例如:vfptr->student::fun1() person::fun2() student::fun3()

而vc编译器下,子类虚继承于父类的情况下,子类的vfptr有两种情况,如果

加入新函数子类将不与父类共享vfptr

vfptr->student::fun1() person::fun2() 

vfptr->student::fun3()

如果没有加入新函数则没有影响

vfptr->student::fun1() person::fun2() 。

2.在vc编译器下,子类虚继承于父类,子类内存与父类内存之间会有一个4个字节的(vtordisp for vbase xxx)

这里附带一个我自己测试菱形继承的例子。

 1 class Car;
 2 class Person
 3 {
 4 
 5 protected:
 6     int m_age;
 7     int m_sex;
 8 
 9 
10 public:
11     Person();
12     Person(int age,int sex);
13     virtual ~Person();
14     void setAge(int age);
15     int getAge();
16     virtual void speak();
17     virtual void run();
18 };
Person.h
 1 #include "Person.h"
 2 class Worker :public virtual Person
 3 {
 4 protected:
 5     int m_salary;
 6 public:
 7     Worker();
 8     Worker(int age, int sex, int salary);
 9     ~Worker();
10     void  speak();
11     void  run();
12 
13 };
Worker.h
 1 #include "worker.h"
 2 #include "Student.h"
 3 class WorkStudent :public Worker,public Student
 4 {
 5     int int1;
 6 public:
 7     WorkStudent();
 8     WorkStudent(int age, int sex, int salary,int no, int test,int int1);
 9     ~WorkStudent();
10     void speak();
11     void run();
12 
13 };
WorkStudent.h
 1 #include "Person.h"
 2 class Student :public virtual Person
 3 {
 4 protected:
 5     int m_age;
 6     int m_sex;
 7     int m_no;
 8     int m_test;
 9 public:
10     Student();
11     Student(int age, int sex, int no,int test);
12     ~Student();
13     void  speak();
14     void  run();
15     virtual void learn();
16  
17 };
Student.h

 

大小分别是12,40,24,52

12=4+4+vfptr

40=[4vfptr(因为有新的虚函数,所以有一个属于自己的vfptr)+4vbptr+4*4]+4(vtordisp)+12(父类)

24=[4vbptr+4]+4(vtordisp)+12(父类)

注意这里的Worker是没有新的虚函数,所以是与父类里的vfptr共用。

52=40+24 - (4(vtordisp)+12(父类))

符合虚继承的作用,只有一份person类的内容。

 

这里贴一份用

/d1 reportSingleClassLayoutXX (XX就是类名)

打出来的内容

 

1>class WorkStudent size(52):
1> +---
1> 0 | +--- (base class Student)
1> 0 | | {vfptr}
1> 4 | | {vbptr}
1> 8 | | m_age
1>12 | | m_sex
1>16 | | m_no
1>20 | | m_test
1> | +---
1>24 | +--- (base class Worker)
1>24 | | {vbptr}
1>28 | | m_salary
1> | +---
1>32 | int1
1> +---
1>36 | (vtordisp for vbase Person)
1> +--- (virtual base Person)
1>40 | {vfptr}
1>44 | m_age
1>48 | m_sex
1> +---

 

posted @ 2021-09-27 22:39  章鱼哥牌深海鱼油  阅读(171)  评论(0)    收藏  举报