問題:定義一個空的類型,裡面沒有任何的成員變量或者成員函數,對這個類型進行 sizeof 運算,結果是?
結果是1,因為空類型的實例不包含任何信息,按道理 sizeof 計算之後結果是0,但是在聲明任何類型的實例的時候,必須在內存占有一定的空間,否則無法使用這些實例,至於占據多少內存大小,由編譯器決定。
繼續問:如果在這個類型裡添加一個構造函數和析構函數,那麼結果又是多少?
還是1,因為我們調用構造函數和析構函數,只需要知道函數的地址即可,而這些函數的地址只和類型相關,和類型的實例無關,編譯器不會為這兩個函數在實例內添加任何額外的信息。
繼續問:如果把析構函數變為虛函數呢?結果是多少?
c++編譯器發現了類型裡有虛函數,,就會為這個類型生成一個虛函數表,並在該類型的每一個實例中添加一個指向虛函數表的指針,在32位機器,指針類型大小是4字節,結果是4,64位機器中,指針大小是8字節,結果是8。
面向對象的多態的實現效果
多態:同樣的調用語句有多種不同的表現形態
看下面的例子:
- class animal
- {
- public:
- void sleep()
- {
- cout<<"animal sleep"<<endl;
- }
- void breathe()
- {
- cout<<"animal breathe"<<endl;
- }
- };
- class fish:public animal
- {
- public:
- void breathe()
- {
- cout<<"fish bubble"<<endl;
- }
- };
- int main(void)
- {
- fish fh;
- animal *pAn=&fh;
- pAn->breathe();
- return 0;
- }
父類指針指向了子類對象,調用了 breathe 方法,那麼結果是animal breathe,也就是說調用的是父類的breathe方法。 這沒有實現多態性。因為C++編譯器在編譯的時候,要確定每個對象調用的函數的地址,這稱為早期綁定(early binding),當fish類的對象fh的地址賦給父類的pAn指針時,C++編譯器進行了類型轉換,它認為父類的指針變量pAn保存的就是animal對象的地址。當在main函數中執行pAn->breathe時,調用的就是animal對象的breathe函數。