在执行时候能够找到和 调用正确的函数体。可以想象,为了达到这个目的,一些相关信息应该封装在对 象自身中。这些信息有点象身份证明,标识自己,这样在动态联编的时候,编译 器可以根据这些标记找到相应的函数体,"不要跑,就是你了"。
实际上的动态联编过程是什么样的呢。
二 对象类型信息
为了证明我们的猜想,我们用下面的一个程序进行测试,下面的程序将获取普通 的类和包含虚函数的类的字节大小。程序代码如下。
//3.cpp
1.#include <iostream.h>
2.class shape_novirtual{
3.int a;
4.public:
5.void draw() {cout<<"shape_novirtual::draw()"<<endl;}
6.};
7.class shape_virtual1{
8.int a;
9.public:
10.virtual void draw(){cout<<"shape_virtual::draw() "<<endl;}
11.};
12.class shape_virtual2{
13.int a;
14.public:
15.virtual void draw() {cout<<"shape_virtual2::draw()"<<endl;}
16.virtual void draw1(){cout<<"shape_virtual2::draw1() "<<endl;}
17.};
18.main(){
19.cout<<"sizeof(int)"<<sizeof(int) <<endl;
20.cout<<"sizeof(class shape_novirtual):"<<sizeof(shape_novirtual)<<endl;
21.cout<<"sizeof(void*):"<<sizeof(void*) <<endl;
22.cout<<"sizeof(class shape_virtual):"<<sizeof(shape_virtual)<<endl;
23.cout<<"sizeof(class shape_virtual2):"<<sizeof(shape_virtual2)<<endl;
24.}
VC6.0中运行结果如下:
sizeof(int)4
sizeof (class shape_novirtual):4
sizeof(void*):4
sizeof(class shape_virtual1):8
sizeof(class shape_virtual2):8
Press any key to continue
从上面可以看出,没有虚函数的类shape_novirtual 的大小为4,正好为int a的大小。而带有虚函数的类shape_virtual1和 shape_virtual2的大小除了int a的大小还多出了4格个字节的大小,这个大小正 好是void*指针的大小。到现在为止我们基本上可以说带有虚函数的对象自身确实 插入了一些指针信息,而且这个指针信息并不随着虚函数的增加而增大。
如果我们将每个类的成员变量int a去掉,VC6.0运行结果就会变成下面的情况。
sizeof(int)4
sizeof(class shape_novirtual):1
sizeof (void*):4
sizeof(class shape_virtual1):4
sizeof(class shape_virtual2):4
Press any key to continue
上面的运行结 果应该让人感到例外。既然size(int)为4,现在没有了这个成员变量,类 shape_novirtual应该字节大小为0,但事实上C++编译器不允许对象为零长度。试 想一个长度为0的对象在内存中怎么存放?怎么获取它的地址?为了避免这种情况 ,C++强制给这种类插入一个缺省成员,长度为1。如果有自定义的变量,变量将 取代这个缺省成员。 |