2012-06-01 78 views
9
class A 
{ 
    public virtual void WhoAreYou() { Console.WriteLine("I am an A"); } 
} 
class B : A 
{ 
    public override void WhoAreYou() { Console.WriteLine("I am a B"); } 
} 
class C : B 
{ 
public new virtual void WhoAreYou() { Console.WriteLine("I am a C"); } 
} 
class D : C 
{ 
    public override void WhoAreYou() { Console.WriteLine("I am a D"); } 
} 


C c = new D(); 
c.WhoAreYou();// "I am a D" 
A a = new D(); 
a.WhoAreYou();// "I am a B" !!!! 

如何在內部分配引用,引用A包含引用B? 任何人都可以解釋發生了什麼?C中的動態綁定#

+0

嗯打破我可能是錯的,但我認爲這是發生了什麼。當你聲明一個D類的對象並把它分配給一個類時C --- C類具有一個虛函數,在這種情況下它將只使用D的覆蓋函數。但是,當你聲明D類的一個對象並將它分配給一個類A時,會發生什麼是因爲D從B和C繼承了C和C,並且B最終從A繼承了,但同時覆蓋了A,那麼你就有了這個打印語句。 –

+0

怎麼樣:閱讀MSDN並試圖理解虛擬/覆蓋/新機器?你的例子非常清楚! –

+0

@Flo:在第一種情況下,對象C具有D的引用,它調用D的方法。但在第二種情況下,顯然A具有D的參考,而方法調用它如何調用B的方法(內部發生什麼)..安靜的混亂.. –

回答

7

C類,WhoAreYou()沒有方法覆蓋基類方法,因爲它是用new關鍵字定義的,其中新增方法與相同名稱其中隱藏基類方法。這就是爲什麼這個:

C c = new D(); 
c.WhoAreYou();// "I am a D" 

調用在D重寫的方法,其覆蓋與new關鍵字定義它的基類的方法。

然而,當目標類型爲A,那麼這個:

A a = new D(); 
a.WhoAreYou();// "I am a B" !!!! 

調用在B重寫的方法,爲你呼籲A類型,其方法是通過B重寫的a的方法。

+0

感謝您的回覆Nawaz。 A有D的參考,A不知道它的子類。所以,我必須從派生的一個跟蹤。是這樣嗎?如果不是意味着..但是如果D的引用調用B的方法以及它如何跟蹤A中的派生類(在方法表的方面)像內部的東西那樣會更好。 –

3

您的類C WhoAreYou()方法是'new',因此隱藏了B中的一個。這意味着D類中的覆蓋重寫了C的方法而不是B(它重寫了A的方法)。

既然你已經到A的引用,最遠下來它的層次是WhoAreYou()函數是一個類B.

http://msdn.microsoft.com/en-us/library/435f1dw2.aspx

1

這是平均值,即C'S

public new virtual void WhoAreYou(){} 

打破了虛擬方法鏈。

當您通過A的參考調用d的方法WhoAreYou()的虛擬性開始工作,但它在C.