C#中的虛方法(virtual)例項講解

willingtolove發表於2020-11-22

虛擬函式從C#的程式編譯的角度來看,它和其它一般的函式有什麼區別呢?一般函式在編譯時就靜態地編譯到了執行檔案中,其相對地址在程式執行期間是不發生變化的,也就是寫死了的!而虛擬函式在編譯期間是不被靜態編譯的,它的相對地址是不確定的,它會根據執行時期物件例項來動態判斷要呼叫的函式,其中那個申明時定義的類叫申明類,那個執行時例項化的類叫例項類。
比如:
User u=new Teacher();
那麼User就是宣告類,Teacher就是例項類。

#具體的檢查的流程如下:

1、當呼叫一個物件的函式時,系統會直接去檢查這個物件申明定義的類,即申明類,看所呼叫的函式是否為虛擬函式;

2、如果不是虛擬函式,那麼它就直接執行該函式。而如果有virtual關鍵字,也就是一個虛擬函式,那麼這個時候它就不會立刻執行該函式了,而是轉去檢查物件的例項類。

3、在這個例項類裡,他會檢查這個例項類的定義中是否有重新實現該虛擬函式(通過override關鍵字),如果是有,它就不會再找了,而馬上執行該例項類中的這個重新實現的函式。而如果沒有的話,系統就會不停地往上找例項類的父類,並對父類重複剛才在例項類裡的檢查,直到找到第一個過載了該虛擬函式的父類為止,然後執行該父類裡過載後的函式。

#程式碼例項:

namespace VirtualTest
{
    class A
    {
        public virtual void Func() 
        {
            Console.WriteLine("Func In A");
        }
    }

    class AB : A  
    {
        public override void Func()  // 注意override ,表明重新實現了虛擬函式
        {
            Console.WriteLine("Func In AB");
        }
    }

    class BC : B 
    {
    }

    class AD : A  
    {
        public new void Func() // 注意new ,表明覆蓋父類裡的同名類,而不是重新實現
        {
            Console.WriteLine("Func In AD");
        }
    }

    class program
    {
        static void Main()
        {
            A a;         // 定義一個A類的物件a.這個A就是a的申明類
            A b;         // 定義一個A類的物件b.這個A就是b的申明類
            A c;         // 定義一個A類的物件c.這個A就是c的申明類
            A d;         // 定義一個A類的物件d.這個A就是d的申明類

            a = new A(); // 例項化a物件,A是a的例項類
            b = new AB(); // 例項化b物件,AB是b的例項類
            c = new BC(); // 例項化c物件,BC是c的例項類
            d = new AD(); // 例項化d物件,AD是d的例項類

            a.Func();    // 執行a.Func:1.先檢查申明類A 2.檢查到是虛擬方法 3.轉去檢查例項類A,就為本身 4.執行例項類A中的方法 5.輸出結果 Func In A
            b.Func();    // 執行b.Func:1.先檢查申明類A 2.檢查到是虛擬方法 3.轉去檢查例項類AB,有過載的 4.執行例項類AB中的方法 5.輸出結果 Func In AB
            c.Func();    // 執行c.Func:1.先檢查申明類A 2.檢查到是虛擬方法 3.轉去檢查例項類BC,無過載的 4.轉去檢查類BC的父類AB,有過載的 5.執行父類AB中的Func方法 5.輸出結果 Func In AB
            d.Func();    // 執行d.Func:1.先檢查申明類A 2.檢查到是虛擬方法 3.轉去檢查例項類AD,無過載的(這個地方要注意了,雖然D裡有實現Func(),但沒有使用override關鍵字,所以不會被認為是過載) 4.轉去檢查類D的父類A,就為本身 5.執行父類A中的Func方法 5.輸出結果 Func In A
            AD ad1 = new AD();
            ad1.Func(); // 執行D類裡的Func(),輸出結果 Func In AD
            Console.ReadLine();
        }
    }
}

例項的輸出結果為:

Func In A
Func In AB
Func In AB
Func In A
Func In AD

相關文章