http://blog.csdn.net/livelylittlefish/article/details/2171374
虚函数的应用特性
例:编写三个类:没有虚函数、有一个虚函数、有两个虚函数,在主函数中定义这三个类的对象,分别取这个类所占的内存空间的大小,观察在内存中的分配;
代码如下:
/************************************************************************
* 虚函数的应用特性例子
************************************************************************/
#include < iostream.h >
// 没有虚函数的类
class CNoVirtual
{ int x;
public:
CNoVirtual(int nx){x=nx;}
void func() const{}
int GetX() const {return x;}
} ;
// 有一个虚函数的类
class COneVirtual
{ int x;
public:
COneVirtual(int nx){x=nx;}
virtual void func() const{}
int GetX(){return x;}
} ;
// 有两个虚函数的类
class CTwoCirtuals
{ int x;
public:
CTwoCirtuals(int nx){x=nx;}
virtual void func() const{}
virtual int GetX() const {return x;}
} ;
void main()
{ CNoVirtual obj1(100);
COneVirtual obj2(200);
CTwoCirtuals obj3(300);
cout<<"size of types: ";
cout<<"int : "<<sizeof(int)<<endl;
cout<<"CNoVirtual : "<<sizeof(CNoVirtual)<<endl;
cout<<"void* : "<<sizeof(void*)<<endl;
cout<<"COneVirtual : "<<sizeof(COneVirtual)<<endl;
cout<<"CTwoVirtual : "<<sizeof(CTwoCirtuals)<<endl;
}
* 虚函数的应用特性例子
************************************************************************/
#include < iostream.h >
// 没有虚函数的类
class CNoVirtual
{ int x;
public:
CNoVirtual(int nx){x=nx;}
void func() const{}
int GetX() const {return x;}
} ;
// 有一个虚函数的类
class COneVirtual
{ int x;
public:
COneVirtual(int nx){x=nx;}
virtual void func() const{}
int GetX(){return x;}
} ;
// 有两个虚函数的类
class CTwoCirtuals
{ int x;
public:
CTwoCirtuals(int nx){x=nx;}
virtual void func() const{}
virtual int GetX() const {return x;}
} ;
void main()
{ CNoVirtual obj1(100);
COneVirtual obj2(200);
CTwoCirtuals obj3(300);
cout<<"size of types: ";
cout<<"int : "<<sizeof(int)<<endl;
cout<<"CNoVirtual : "<<sizeof(CNoVirtual)<<endl;
cout<<"void* : "<<sizeof(void*)<<endl;
cout<<"COneVirtual : "<<sizeof(COneVirtual)<<endl;
cout<<"CTwoVirtual : "<<sizeof(CTwoCirtuals)<<endl;
}
1. 运行结果:
2. 对象的内存分配情况:
3. 对象的地址及内容:
4. 对象的成员变量的地址及内容:
综上,对象的内存空间分配情况如下:
说明:
从上面的结果可以看到,没有虚函数的类CNoVirtual的大小正好是其成员变量——一个整型数据的大小,而有一个虚函数和两个虚函数的类的大小还要加上一个紧缩的空指针类型的大小。这说明了在包含虚函数的类中,编译系统自动加入了一些表明类型的信息。
当一个类中拥有虚函数时,编译系统将为该类创建一个数组VTABLE。VTABLE数组中的元素是虚函数的地址,且同一虚函数的地址在基类和派生类的VTABLE中相对首位置的偏移是一样的。同时,编译系统还加入了相应的调用虚函数的代码。所有这些都是不需要程序员作的工作,由系统自动完成。在初始化该类对象时,将加入一个指向VTABLE的指针,这个指针一般称为VPTR。一般来说,VPTR位于该类对象的存储单元的最开始部位,如上图所示。
这样,当VPTR被正确的初始化之后,便指向了该对象的VTABLE,从而在对象及其特定的虚函数定义间建立了联系。从虚函数调用的意义上来说,VPTR表明了类型信息,因为它使得调用与类型相符合。
从上面的结果可以看到,没有虚函数的类CNoVirtual的大小正好是其成员变量——一个整型数据的大小,而有一个虚函数和两个虚函数的类的大小还要加上一个紧缩的空指针类型的大小。这说明了在包含虚函数的类中,编译系统自动加入了一些表明类型的信息。
当一个类中拥有虚函数时,编译系统将为该类创建一个数组VTABLE。VTABLE数组中的元素是虚函数的地址,且同一虚函数的地址在基类和派生类的VTABLE中相对首位置的偏移是一样的。同时,编译系统还加入了相应的调用虚函数的代码。所有这些都是不需要程序员作的工作,由系统自动完成。在初始化该类对象时,将加入一个指向VTABLE的指针,这个指针一般称为VPTR。一般来说,VPTR位于该类对象的存储单元的最开始部位,如上图所示。
这样,当VPTR被正确的初始化之后,便指向了该对象的VTABLE,从而在对象及其特定的虚函数定义间建立了联系。从虚函数调用的意义上来说,VPTR表明了类型信息,因为它使得调用与类型相符合。
//类的函数已经编译好在代码区...根本不会算在sizeof()大小里面
//实际是有虚函数的类对象会多了个虚表的占用空间.
//实际是有虚函数的类对象会多了个虚表的占用空间.