簡體   English   中英

覆蓋非虛方法?

[英]Overriding Non-Virtual methods?

下面是一些代碼,用於顯示重寫虛擬方法的時間。 它輸出:BBAABA這是正確的嗎? 我以為bar方法無法被覆蓋......?

#include <iostream>
using namespace std;


class A
{
public:
    virtual void foo(){cout<<"A"<<endl;}
            void bar(){cout<<"A"<<endl;}
};

class B : public A
{
public:
    void foo(){cout<<"B"<<endl;}
    void bar(){cout<<"B"<<endl;}
};

int main()
{
    B b;
    A * pA = new A;
    A * pA2 = &b;
    b.foo(); b.bar();
    pA->foo(); pA->bar();
    pA2->foo(); pA2->bar();

}    

我沒有看到任何錯誤:

B b;
b.foo(); b.bar();

聲明並初始化B的實例,編譯類型為B ,運行時類型為B 不需要多態性(也不能實現,因為沒有涉及指針)。

A * pA = new A;
pA->foo(); pA->bar();

你聲明的指針, A與實例初始化A 即使在這種情況下不需要多態性也可以工作,因此調用來自A foo()bar()

A * pA2 = &b;
pA2->foo(); pA2->bar();

您聲明一個指向A的指針,並使用對B的引用對其進行初始化。 編譯時間類型為A* ,運行時類型為B* 應用通過虛函數的多態性,因此虛方法是B::foo()而非虛方法是A::bar()

b.foo()給出B

b.bar()也給出了隱藏A::bar() B 它不是壓倒一切,它隱藏着名字。

pA->foo()給出ApA->bar()給出A

pA2->foo()給出B因為它是一個虛函數。

pA2->bar()給出A因為它不是虛函數。 它是靜態鏈接的,它調用A::bar()

前兩個輸出都應該是B,因為你在類型B的對象上調用foo()和bar()。因為你沒有使用指針,編譯器知道它是B類型的對象,因此不需要請參考vtable來調用該方法,因此即使bar()不是虛擬的,編譯器也知道使用B實現。

接下來的兩個輸出都應該是A,因為你在指向類型A的對象的指針上調用foo()和bar()。在這種情況下,foo()是虛擬的,而vtable指向A的實現方法。 bar()不是虛擬的,因此編譯器決定使用A實現。

最后兩個輸出應該是B和A,因為你在指向類型B的對象的指針上調用foo()和bar()。在這種情況下,foo()是虛擬的,vtable指向B實現方法。 bar()不是虛擬的,因此編譯器決定使用A實現,因為您正在使用指向A類型對象的指針。

這是正確的,pA2-> bar()調用不會被覆蓋。 即使它是一個B對象,也可以將它轉換為A,編譯器調用A類的成員函數。

foo()是虛擬的,因此包含在類B中的是指向哪個版本的foo()對於類是正確的指針,無論它被轉換到何處。

此包含稱為指向虛函數表的指針。 只要您的類具有虛擬成員,就會為其創建一個靜態函數表(並且還將包括任何其他后續虛函數),另外一個常量隱藏成員指針指向該表。 當您轉換對象時,函數表不會更改,任何虛函數都將保持“附加”到原始類型。

PS,別忘了刪除pA ...你目前有內存泄漏:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM