虛函數的應用特性
* 虛函數的應用特性例子
************************************************************************/
#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;
}
從上面的結果可以看到,沒有虛函數的類CNoVirtual的大小正好是其成員變量——一個整型數據的大小,而有一個虛函數和兩個虛函數的類的大小還要加上一個緊縮的空指針類型的大小。這說明了在包含虛函數的類中,編譯系統自動加入了一些表明類型的信息。
當一個類中擁有虛函數時,編譯系統將爲該類創建一個數組VTABLE。VTABLE數組中的元素是虛函數的地址,且同一虛函數的地址在基類和派生類的VTABLE中相對首位置的偏移是一樣的。同時,編譯系統還加入了相應的調用虛函數的代碼。所有這些都是不需要程序員作的工作,由系統自動完成。在初始化該類對象時,將加入一個指向VTABLE的指針,這個指針一般稱爲VPTR。一般來說,VPTR位於該類對象的存儲單元的最開始部位,如上圖所示。
這樣,當VPTR被正確的初始化之後,便指向了該對象的VTABLE,從而在對象及其特定的虛函數定義間建立了聯繫。從虛函數調用的意義上來說,VPTR表明了類型信息,因爲它使得調用與類型相符合。