[英]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()
給出A
, pA->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.