2013-05-29 49 views
-1
class A { 
    public virtual void M() { Console.Write("A"); } 
} 

class B: A { 
    public override void M() { Console.Write("B"); } 
} 

class C: B { 
    new public virtual void M() { Console.Write("C"); } 
} 

class D: C { 
    public override void M() { Console.Write("D"); } 
    static void Main() { 
     D d = new D(); 
     C c = d; 
     B b = c; 
     A a = b; 
     d.M(); c.M(); b.M(); a.M(); 
    } 
} 

我是新來的這個概念,所以詳細的答案將不勝感激。「新」修飾符做什麼以使b.M(); a.M(); 「B」?

+0

新的修飾符不會涉及A/B--你能否澄清,你的意思是爲什麼它不爲C輸出「B」?真的,A/B的答案與新修飾符無關。覆蓋可確保調用大多數派生的方法。 – Charleh

+0

[C#關鍵字使用虛擬+覆蓋與新]的可能重複(http://stackoverflow.com/questions/159978/c-sharp-keyword-usage-virtualoverride-vs-new) –

+0

可能的http://重複stackoverflow.com/questions/1067234/oh-virtual-new-modifiers-in-c-sharp-have-different-rules-so-what-is-the –

回答

5

new修飾符本質上創建了一個同名的新方法,隱藏了同名的基方法;基本方法仍然存在,它只是被隱藏起來。您仍然可以通過將其轉換爲基本類型,從課程外部調用它。從documentation

當作爲改性劑使用的,關鍵字明確地隱藏了從構件基類繼承。

另一方面,override關鍵字指示基類方法將在子類中被覆蓋。沒有通過重寫接口,無法調用基本方法。

因此,在你的榜樣,當你調用b.M()a.M()你調用上BM方法(這是繼承了從A覆蓋)。另一方面,當您撥打d.M()c.M()時,您打電話給D(從C繼承並覆蓋)中的名爲M的完全不同的方法。

+0

b.M()和a.M()在B上都調用方法M,而d.M()和c.M()實際上都在D上調用M. – Kevin

+0

@Kevin是的,這是一個更明確的說明方式。 –

+0

@Kevin不是c只是對類型D的對象的引用?爲什麼b.M()和a.M()的答案不是「D」? – Rsaleh

1

當您定義一個虛擬方法時,您允許在繼承樹中的某個點重寫該方法。例子中的後代類(例如B)可以以某種方式更改方法的邏輯。對虛方法的調用將使用大多數派生覆蓋,這取決於對象實例的具體類型,而不是保存實例的變量的類型。

虛擬方法表(VMT)用於跟蹤這些虛擬方法和可能已應用的任何覆蓋。 A類型的變量可以包含從A類派生的任何類 - 在您的示例中,AB,CD中的任何一個。 VMT用於確定在調用虛擬方法時要調用哪個覆蓋方法。所以在你的例子中,B覆蓋了方法M。當您調用方法M時,程序會在VMT中查找要調用的正確方法,並調用該方法。

每個類定義自己的VMT,並且變量將使用與其自己的類型相關的VMT。因此A類型的變量將使用類型爲A的VMT,類型B變量將使用VMT類型B依此類推,而不管實際(具體)類的實例存儲在該變量中。覆蓋解決方案將處理實例的VMT以找到要執行的正確方法。

new運算符聲明一個名稱相同的方法,但它不是所替換方法的解析鏈的一部分。新方法可能是虛擬的,在這種情況下,它會獲得自己的一組VMT條目,或者它可能是標準的非虛擬方法。

爲了正確管理虛擬方法和覆蓋,編譯器必須有一些信息可用。由於它不能在編譯時知道變量可能存在的內容,因此它只有變量的類型。因此,當您調用類型爲A的變量的方法時,它將解析調用,因爲它應該爲A類型完成 - 通過生成代碼來對A類型的對象執行運行時重載解析。同樣適用於任何類型的變量...生成的代碼在聲明的類型上工作,並在運行時解決覆蓋問題。

所以,當你聲明C類型的變量,然後調用方法M,它是尋找一個名爲M的方法是在或低於C定義。由於您使用了new修飾符,因此永遠不會導致對A中定義的虛擬方法或其在B中的超載進行回溯。由於C.M是虛擬的,因此它將使用VMT來找到虛擬方法的新的的正確覆蓋。

因此,通常調用虛擬方法時實際調用的方法取決於實例的具體類型。關鍵字new也使變量的類型很重要。

上面的一些是更多描述準確的比在技術上準確。實際執行情況可能與以往不同:)