2016-06-21 68 views
0

我的代碼的一個例子在C#輸出線在C#虛擬方法

using System; 
class A 
{ 
    public virtual void F() { Console.WriteLine("A.F"); } 
} 
class B: A 
{ 
    public override void F() { Console.WriteLine("B.F"); } 
} 
class C: B 
{ 
    new public virtual void F() { Console.WriteLine("C.F"); } 
} 
class D: C 
{ 
    public override void F() { Console.WriteLine("D.F"); } 
} 
class Test 
{ 
static void Main() { 
    D d = new D(); 
    A a = d; 
    B b = d; 
    C c = d; 
    a.F(); 
    b.F(); 
    c.F(); 
    d.F(); 
} 
} 

此代碼輪廓

B.F 
B.F 
D.F 
D.F 

我不理解爲什麼在殼體a.F(); 有B.F?

MS如何表示,虛擬方法是通過在實時類型的對象represended

回答

1

我不理解爲什麼在殼體a.F();有B.F?

MSDN #

當調用虛擬方法,所述對象的運行時類型是 檢查用於重寫構件。 派生類中的首要成員稱爲,如果沒有 派生類已重寫成員,則該成員可能是原始成員。

粗體內容將向您解釋爲什麼在調用A.F()時打印B.F

1

從繼承的類對象對方法F()的調用將類型D對象的B.F轉換爲類型A,因爲您重寫了類B(和類D)中的方法。

你的測試是在this MSDN post on virtual methods所提供的示例的幾乎精確副本:

using System; 
class A 
{ 
    public void F() { Console.WriteLine("A.F"); } 
    public virtual void G() { Console.WriteLine("A.G"); } 
} 
class B: A 
{ 
    new public void F() { Console.WriteLine("B.F"); } 
    public override void G() { Console.WriteLine("B.G"); } 
} 
class Test 
{ 
    static void Main() { 
     B b = new B(); 
     A a = b; 
     a.F(); 
     b.F(); 
     a.G(); 
     b.G(); 
    } 
} 

在該示例中,A引入了非虛擬方法F和虛擬 方法G.中的B類介紹一個新的非虛擬方法F,從而 隱藏繼承F和也覆蓋了繼承的方法G的 例產生輸出:

AF
BF
BG
BG

注意,聲明 AG()調用BG,而不是AG這是因爲運行時類型的 實例(即B),而不是在編譯時類型實例 (即A)確定要調用的實際方法實現。 由於允許方法隱藏繼承的方法,因此類 可能包含幾個具有相同 簽名的虛擬方法。這並不存在歧義問題,因爲除了最衍生的方法以外,其他所有方法都是隱藏的。在該示例中

1

在AF()的情況下,存在因爲BF虛擬無效的F類A是覆蓋在B.

它不是被C覆蓋,因爲有一個新的運營商,其不重寫虛擬基礎方法。

因此,如果有類型爲D的類型D的實例並且您調用F(),則會調用類A的虛擬方法,但會考慮最新的覆蓋。那就是B.F.