C++类对象大小的计算(二)含有虚函数类大小计算

来源:互联网 发布:stc15f2k单片机下载线 编辑:程序博客网 时间:2024/05/17 03:40

前一篇文章《C++类对象大小的计算(一)常规类大小计算》初步介绍类大小计算后,我们继续来讨论含有虚函数时类的大小。

以下内存测试环境为Win7+VS2012,操作系统为32位

五、包含虚函数的类

        包含虚函数的类,对象生成时,会在类对象当中插入一个指针,这个指针称做虚函数表指针,简称虚表指针(vPtr)。该指针指向一个虚函数表(简称虚表),虚函数表中存储了虚函数的入口地址。基类当中有虚函数时,会产生该虚函数表;创建基类对象,对象中的vPtr会指向该表;调用虚函数时,是通过vPtr在此表当中寻找函数入口地址的。

        当派生类继承含有虚函数的子类时,会复制一份虚函数表,派生类如果有与基类中虚函数同名的虚函数,会在虚函数表中覆盖原来基类的虚函数;如果虚函数不重名,只会在虚函数表中增加一个函数入口。这种机制实现了类的多态。

如下面的例子:

#include <iostream>using namespace std;class A {public:A(int x=0) {cout<<"A"<<x<<endl;}void printA() {cout<<"Hello A";}};class B :public A{public:B(int x=0) {cout<<"B"<<x<<endl;}virtual void printB() {cout<<"Hello B";}};class C : public B{public:C() {cout<<"C"<<endl;}virtual void printC() {cout<<"Hello C";}};int main() {A a;B b;C c;cout<<"size of a:"<<sizeof(a)<<endl;cout<<"size of b:"<<sizeof(b)<<endl;cout<<"size of c:"<<sizeof(c)<<endl;return 0;}

VS类结构图:




运行结果为:


        类A没有虚函数,因此大小仍然是1。类B因为有虚函数,其对象当中包含了一个vPtr指针,指针指向类B的虚函数表(假设为vTB),该表中存储了printB的入口地址,因此大小为4。类C因为继承了类B,也就复制了vTB(设为vTC),其对象中也就包含了指向vTC的虚表指针,该虚表中除了有printB的入口地址外,还包含了printC的入口地址,因此,类C对象大小为4。

        考虑另一种情况,类C同时继承了类A、B,类A、B当中都有虚函数。如下面的例子:
#include <iostream>using namespace std;class A {public:A(int x=0) {cout<<"A"<<x<<endl;}virtual void printA() {cout<<"Hello A";}};class B {public:B(int x=0) {cout<<"B"<<x<<endl;}virtual void printB() {cout<<"Hello B";}};class C : public B, public A{public:C() {cout<<"C"<<endl;}void printC() {cout<<"Hello C";}};int main() {A a;B b;C c;cout<<"size of a:"<<sizeof(a)<<endl;cout<<"size of b:"<<sizeof(b)<<endl;cout<<"size of c:"<<sizeof(c)<<endl;return 0;}
VS类结构图:



运行结果为:
类A、B对象的大小按照上面所说的内存很好理解。类C因为同时继承了类A、B,因此就复制了两个虚函数表,也就有了两个vPtr,所以大小为8。如果类C有虚函数,也会放在其中一张虚函数表当中,不会再增加对象大小。
        含有成员变量时,按照《C++类对象大小的计算(一)常规类大小计算》所讲内容加上相应的大小即可。

        下面的文章《C++类对象大小的计算(三)含有虚函数、虚继承类大小计算》会讨论增加虚继承时,类对象的大小。
0 0
原创粉丝点击