今天为了加深自己对虚函数的理解,所以做了一个有趣的小试验。定义了类A、类B并且类C继承了类A类B。代码如下:
#include <iostream>
#include <new>
class A
{
public:
A(){}
virtual void InfoA() { std::cout<< " A::InfoA() " << std::endl; }
private:
char arrayA[3];
};
class B
{
public:
B() {}
virtual void InofB() { std::cout<< " B::InfoB() " <<std::endl; }
private:
char arrayB[3];
};
class C:public A,public B
{
public:
C() {}
virtual void InfoA() { std::cout<< " C::InfoA() " <<std::endl; }
virtual void InfoB() { std::cout<< " C::InofB() " << std::endl; }
private:
char arrayC[3];
};
int main()
{
A a;
B b;
C c;
std::cout<<" sizeof(A) = : "<<sizeof(a)<<std::endl;
std::cout<<" sizeof(B) = : "<<sizeof(b)<<std::endl;
std::cout<<" sizeof(C) = : "<<sizeof(c)<<std::endl;
return 0;
}
在我的电脑中输出结果如下:
sizeof (A) = : 8
sizeof (B) = : 8
sizeof (C) = : 20
刚开始我还觉得有点奇怪,为什么类A占了8个字节?因为以前就知道虚函数是由一个叫做虚拟函数分配表(_vfptr)的指针维护着,而指针在32位机器中占用了4个字节。嗯想想有点道理,但是为什么是8个字节而不是7个?看看定义的类A,定义了一个虚函数,并且定义了一个私有的char数组,分配了3个字节的空间,如果正如我刚才说的有一个虚拟函数分配表指针,那么相加应该7个字节才对。后来我想了一下才知道,原来在计算机内存里面地址会自动对齐。因为我存储的是3个字节的数据,而计算机是32位的,由于对齐原因它实际上分配了4个字节,不过只有3个自己是可用的。如果这样那么最后结果sizeof(A)的大小是8了就不奇怪了。那么同样sizeof(B)也是8字节了。那还有一个问题,sizeof(C)为什么会是20个字节?后来我看了看汇编代码我才知道,原来类C有类A、B的一份拷贝,而且还有一个3字节的数组,也同样是因为对齐原因,所以8+8+4 = 20字节了。
图示:
____________
| class A |
|__________|
| _vfptr |----->____________________
|__________| |[0]void A::InfoA()|
| arrayA[0]| |__________________|
| arrayA[1]|
| arrayA[2]|
|__________|
内存对齐
____________
| class B |
|__________|
| _vfptr |----->____________________
|__________| |[0]void B::InfoB()|
| arrayB[0]| |__________________|
| arrayB[1]|
| arrayB[2]|
|__________|
内存对齐
____________
| class C |
|__________|
| A |
|__________|
| _vfptr |----->____________________
|__________| |[0]void A::InfoA()|
| arrayA[0]| |__________________|
| arrayA[1]|
| arrayA[2]|
| 内存对齐 |
|__________|
| B |
|__________|
| _vfptr |----->____________________
|__________| |[0]void B::InfoB()|
| arrayB[0]| |__________________|
| arrayB[1]|
| arrayB[2]|
| 内存对齐 |
|__________|
| arrayC[0]|
| arrayC[1]|
| arrayC[2]|
| 内存对齐 |
|__________|
这里我还留下一个疑问,现在是类继承的虚函数的情况,那么TEMPLATE类的继承虚函数的情况又是怎样的?等着两天有时间再做个实验看看。。。待续。。。