2012-09-22 60 views
2

如果對您發現愚蠢的問題,請原諒我。我是C++的新手,我正在研究朗姆酒時間多態性。我想知道當基類對象調用派生類函數(這是非虛擬的)時會發生什麼。例如看代碼當基類對象調用派生類函數(這是非虛擬的)時會發生什麼

class base { 
    public: 
     virtual void vfunc() {cout << "This is base's vfunc().\n";} 
}; 

class derived1 : public base { 
    public: 
     void vfunc() {cout << "This is derived1's vfunc().\n";} 
}; 

int main() 
{ 
    base *p, b; 
    derived1 d1; 

    p = &b; 
    p->vfunc(); 

    p = &d1; 
    p->vfunc(); 

    return 0; 
} 

我得到所期望的輸出中,我然後移除從基類virtual關鍵字,並且當我跑的程序的輸出是

This is base's vfunc(). 
This is base's vfunc(). 

我將非常感謝如果有一個人解釋什麼在兩種情況下發生的(在指針操作而言)

感謝

回答

1

這是怎麼回事的是,有兩個虛函數表,一個基地和一個派生。在基地的vtable中,你有一個vfunc()的條目,並且在派生的vtable中也有一個條目,訣竅是派生時將其作爲父級的vtable,看看它是否覆蓋父級的任何虛擬方法。所以它取代了那裏的東西,現在它指向它自己的版本。

換句話說,當通過基類型的實例調用vfunc()時,您檢查包含基指針vfunc()的指針的基本vtable。當您通過派生實例調用它時,會發現指向派生的指針vfunc()

如果您刪除了虛擬關鍵字,編譯器就不再尋找虛擬函數,所以不是基於對象的運行時類型,而是基於它的靜態/編譯時類型。

換句話說,如果沒有virtual關鍵字,編譯器會查看基本指針的類型,因此每次調用基本版本。

2

在虛擬情況下,在運行時p->vfunc()告訴p去類(無論它的一部分是在內存中),所述指針對象屬於的類的定義,並讀取其虛函數表(或一些類似的備用實現)來確定要調用哪個函數。

假設的vtables類似於下面:

base的VTable:

---------------- 
vfunc | 0x2048 
---------------- 

derived1的VTable:

---------------- 
vfunc | 0x2096 
---------------- 

然後基本版本或vfunc衍生版本取決於稱爲在哪裏vtables指向。

在非虛擬的情況下,這些都不會發生,調用的函數在編譯時刻處於編譯時間。在編譯期間,所有編譯器都可以看出p是「指向基址的指針」類型,並將所有p->vfunc()調用更改爲指向地址0x2048

相關問題