程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#方法:虛方法的調用淺談

C#方法:虛方法的調用淺談

編輯:C#入門知識

我們在面試中經常碰到有關多態的問題,之前我也一直被此類問題所困擾,鬧不清到底執行哪個方法。
先給出一道簡單的面試題,大家猜猜看,輸出是?
  View Code 
 
    public class A
    {
        public void MethodF()
        {
            Console.WriteLine("A.F");
        }
        public virtual void MethodG()
        {
            Console.WriteLine("A.G");
        }
    }
    public class B : A
    {
        new public void MethodF()
        {
            Console.WriteLine("B.F");
        }
        public override void MethodG()
        {
            Console.WriteLine("B.G");
        }
    }
    class Test
    {
        static void Main()
        {
            B b;
            b = new B();
            A a = b;
            a.MethodF();
            b.MethodF();
            a.MethodG();
            b.MethodG();
        }
 
首先看一下虛方法的定義(MSDN):
  若一個實例方法的聲明中含有 virtual 修飾符,則稱該方法為虛擬方法。若其中沒有 virtual 修飾符,則稱該方法為非虛擬方法。
以上面題目Test類Main中代碼為例,簡單說一下CLR創建對象的過程都做了什麼事情
1) 首先,聲明一個引用類型變量 b,它僅是一個引用,保存在線程的棧上,用於將來存放B對象的有效地址。此時 b 未指向任何有效的實例,值為null,相關代碼為:
     B b;
 
2) 接下來,通過new執行對象的創建,即:
     b = new B();
對象的實例保存在托管堆上,CLR在創建一個新對象的同時,還會創建它的類型對象(如果類型對象不存在)。
  對象實例在堆中的內存包括實例字段、類型對象指針、同步索引塊,類型對象指針指向類型對象。
  類型對象在堆中分配的內存包括實例字段、類型對象指針、同步索引塊、靜態字段、方法表。
 
3)  A a = b;  這行代碼首先聲明一個類型為A的引用類型變量a,並將其實際地址指向b所指向的對象實例。
 
4)  之後就是方法的調用,下面詳細說一下C#中方法的調用:
    a.MethodF();
 當調用一個對象的方法時,會直接檢查這個對象變量(a)的類型 ,找到堆中的類型對象,查看是否有該方法,沒有則通過類型對象的類型對象指針向上回溯查找,直至找到,然後檢查該方法是否為虛方法,如果非虛,直接調用,由於MethodF 方法是非虛的,因此直接調用輸出A.F。
    a.MethodG();
 如果該方法為虛方法,即有virtual 關鍵字,則根據對象變量(a),去找到對象的實例類B,查找該類型對象中是否重新實現過該虛方法(override 關鍵字),如果有,OK執行,如果沒有,向上檢查其父類,直至找到然後執行,MethodG為虛方法,則會查找實例B,由於B中重寫了MethodG,因此此處輸出B.G。

  通過上面的描述,開始的那道面試題,我們應該輕松可以得出輸出,此處就不啰嗦了。
 
  一般考多態的面試題中 virtual new override  幾個關鍵字經常出現,new 關鍵字實現一個新的方法,同時隱藏基類的同名方法。

 


摘自 涅槃2012

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved