天天看點

C#虛函數virtual詳解

在面向對象程式設計中,有兩種截然不同的繼承方式:實作繼承和接口繼承。在實作繼承時候,在Java中,所有函數預設都是virtual的,而在C#中所有函數并不預設為virtual的,但可以在基類中通過聲明關鍵字virtual,就可以在其派生類中通過關鍵字override重寫該函數。

     重寫後的virtual函數依舊是virtual函數。由于virtual隻對類中的執行個體函數成員有意義,是以成員字段和靜态函數都不能聲明為virtual,也不能與override和abstract一起用。C#中可以設定virtual屬性、索引器或事件。

無virtual和override關鍵字“重寫”

     這是所謂的無virtual和override的“重寫”其實隻是隐藏。如果簽名後的函數在基類中都進行了聲明,卻沒有用virtual和override關鍵字,例如:

class Program
    {
        static void Main(string[] args)
        {
            A a1 = new A(); a1.Print();
            A a2 = new B(); a2.Print();
            A a3 = new C(); a3.Print();
            Console.Read();
        }
    }
    class A
    {
        public  void Print()
        {
            Console.WriteLine("A");
        }
    }
    class B : A
    {
        public void Print()
        {
            Console.WriteLine("B");
        }
    }
    class C : B
    {
        public void Print()
        {
            Console.WriteLine("C");
        }
    }


    //列印結果   A
                A
                A
           

有virtual和override關鍵字“重寫”

 在派生類中添加關鍵字virtual和override,實作對基類的重寫:

class Program
    {
        static void Main(string[] args)
        {
            A a1 = new A(); a1.Print();
            A a2 = new B(); a2.Print();
            A a3 = new C(); a3.Print();
            Console.Read();
        }
    }
    class A
    {
        public  void Print()
        {
            Console.WriteLine("A");
        }
    }
    class B : A
    {
        public override void Print()
        {
            Console.WriteLine("B");
        }
    }
    class C : B
    {
        public void Print()
        {
            Console.WriteLine("C");
        }
    }


    //報錯
           

 在類的定義中,申明時定義的類叫申明類,執行執行個體化時候定義的類叫執行個體類。

此時編譯器具體的檢查的流程如下

1、當調用函數時,系統會直接去檢查申明類,看所調用的函數是否為虛函數;

2、如果不是,那麼它就直接執行該函數。如果是virtual函數,則轉去檢查對象的執行個體類。

3.在執行個體類中,若有override的函數,則執行該函數,如果沒有,則依次上溯,按照同樣步驟對父類進行檢查,知道找到第一個override了此函數的父類,然後執行該父類中的函數。(星夢《C#虛函數virtual詳解收藏》)

class Program
    {
        static void Main(string[] args)
        {
            A a1 = new A(); a1.Print();
            A a2 = new B(); a2.Print();
            A a3 = new C(); a3.Print();
            Console.Read();
        }
    }
    class A
    {
        public virtual void Print()
        {
            Console.WriteLine("A");
        }
    }
    class B : A
    {
        public override void Print()
        {
            Console.WriteLine("B");
        }
    }
    class C : B
    {
        public void Print()
        {
            Console.WriteLine("C");
        }
    }


    //列印結果   A
                B
                B
           
class Program
    {
        static void Main(string[] args)
        {
            A a1 = new A(); a1.Print();
            A a2 = new B(); a2.Print();
            A a3 = new C(); a3.Print();
            Console.Read();
        }
    }
    class A
    {
        public virtual void Print()
        {
            Console.WriteLine("A");
        }
    }
    class B : A
    {
        public override void Print()
        {
            Console.WriteLine("B");
        }
    }
    class C : B
    {
        public override void Print()
        {
            Console.WriteLine("C");
        }
    }


    //列印結果   A
                B
                C