天天看點

為什麼基類指針(或引用)可以調用派生類的private虛函數

在基類中定義了public虛函數,在派生類中将其重寫,但是設定為private,為什麼通過基類指針仍然可以發生動态綁定調用派生類中的private虛函數?

例子如下:

class Base
{
public:
    // public虛函數
    virtual void Disp() { cout << "base.\n"; }
};
 
class Derived : public Base
{
private:
    // 重寫基類虛函數,但是放在private中
    virtual void Disp() { cout << "derived.\n"; }
};
 
void main()
{
    Derived Dobj;
    Base *pBase = &Dobj;
    pBase->Disp();    // 顯示的結果是派生類的虛函數被調用!
}
           

正确的解釋:派生類中虛函數的通路權限是在編譯階段由基類确定的,在運作階段不再檢查通路權限,是以,虛函數的通路權限與派生類就沒關系了。

更進一步的解釋:當pBase->Disp()時,首先通過這個對象的vptr找到對應的vtable, 因為它實際上是Derived對象,是以找到的是Derived的虛表,所有的Derived對象都共用這個虛表。又因為是通過基類的指針調用的,編譯器從Base的類型資訊中查到Disp是虛表中的第一個entry, 而且這個函數的通路權限是public的,是以首先它讓你調用,其次,從虛表第一個entry中取出的函數位址對應着Derived::Disp, 是以最後是Derived::Disp被調用,Derived::Disp在Derived中的通路權限在這裡是無關的了,編譯器根本不會費事去查詢這一資訊。甚至這一資訊可能根本編譯器也不知道。