首先重新回顾一下关于类/对象大小的计算原则:
类大小计算遵循结构体对齐原则
类的大小与数据成员有关与成员函数无关
类的大小与静态数据成员无关
虚继承对类的大小的影响
虚函数对类的大小的影响
在g++编译器下的情况
一、只出现虚继承的情况
#include <iostream>
using namespace std;
class BB
{
public :
int bb_ ;
};
class B1 : virtual public BB
{
public :
int b1_ ;
};
class B2 : virtual public BB
{
public :
int b2_ ;
};
class DD : public B1, public B2
{
public :
int dd_ ;
};
int main (void)
{
cout<<sizeof (BB)<< endl;
cout<<sizeof (B1)<< endl;
cout<<sizeof (DD)<< endl;
return 0;
从输出的地址和虚基类表成员数据可以画出对象内存模型图:
virtual base table
本类地址与虚基类表指针地址的差
虚基类地址与虚基类表指针地址的差
virtual base table pointer(vbptr)
从程序可以看出pp是BB* 指针,通过打印pp 的值与&dd 比较可知,
cout<<(void*)&dd<
#include <iostream>
using namespace std;
class BB
{
public:
virtual void vpbb()
{
cout << "BB:vpbb().." << endl;
}
int bb_;
};
class B1 : public BB
{
public:
virtual void vpb1()
{
cout << "B1:vpb1().." << endl;
}
int b1_;
};
class B2 : public BB
{
public:
virtual void vpb2()
{
cout << "B2:vpb2().." << endl;
}
int b2_;
};
class DD : public B1, public B2
{
public:
virtual void vpdd()
{
cout << "DD:vpdd().." << endl;
}
int dd_;
};
typedef void (* FUNC)(void );
int main()
{
cout << sizeof(BB) << endl;
cout << sizeof(B1) << endl;
cout << sizeof(DD) << endl;
cout << endl;
return 0;
}
从成员输出的地址和通过虚函数表指针访问到的函数可以画出模型:
DD::vfdd 的位置跟继承的顺序有关,如果DD先继承的是B2, 那么它将跟在B2::vfb2 的下面。
如果派生类是从多个基类继承或者有多个继承分支(从所有根类开始算起),而其中若干个继承分支上出现了多态类,则派生类将从这些分支中的每个分支上继承一个vptr,编译器也将为它生成多个vtable,有几个vptr就生成几个vtable(每个vptr分别指向其中一个),分别与它的多态基类对应。
三、虚继承与虚函数同时出现的情况:
#include <iostream>
using namespace std;
class BB
{
public :
virtual void vfbb()
{
cout<<"BB::vfbb" <<endl;
}
virtual void vfbb2()
{
cout<<"BB::vfbb2" <<endl;
}
int bb_ ;
};
class B1 : virtual public BB
{
public :
virtual void vfb1()
{
cout<<"B1::vfb1" <<endl;
}
int b1_ ;
};
class B2 : virtual public BB
{
public :
virtual void vfb2()
{
cout<<"B2::vfb2" <<endl;
}
int b2_ ;
};
class DD : public B1, public B2
{
public :
virtual void vfdd()
{
cout<<"DD::vfdd" <<endl;
}
int dd_ ;
};
typedef void (* FUNC)(void);
int main (void)
{
cout<<sizeof (BB)<< endl;
cout<<sizeof (B1)<< endl;
cout<<sizeof (DD)<< endl;
return 0;
}
对象内存模型图: