關於在C#中構造函數中調用虛函數的問題

在C#中若是存在類的繼承關係,應避免在構造函數中調用虛函數。這是因爲C#的運行機制形成的,緣由以下:ide

新建一個類實例時,C#會先初始化該類(對類變量賦值,並將函數記在函數表中),而後再初始化父類。構造函數的執行則相反,先執行父類的,再執行自己的。函數

若是類包含對父類虛函數的重載,在父類構造函數中調用虛函數時,會執行函數表中繼承類的虛函數,這就有問題了。測試

 

下面是個測試例子:spa

public class Base
    {
        public Base()
        {
            System.Console.WriteLine("Base.Base");
            ABitDangerousCall();
        }

        public virtual void ABitDangerousCall()
        {
            System.Console.WriteLine("Base.ABitDangerousCall");
        }

        private class Inner
        {
            public Inner()
            {
                System.Console.WriteLine("Base.Inner.Inner");
            }
        }
        private Inner inner = new Inner();
    }

    class Derived : Base
    {
        public Derived()
        {
            System.Console.WriteLine("Derived.Derived");
            ctorInitializedMember = 5;
        }

        // ctorInitializedMember is default initialized to zero before the constructor initializes it.
        private int ctorInitializedMember;
        private int derivedInt = 6;

        public override void ABitDangerousCall()
        {
            System.Console.WriteLine(String.Format("Derived.ABitDangerousCallctorInitializedMember={0} derivedInt={1}", ctorInitializedMember, derivedInt));
        }

        private class Inner
        {
            public Inner()
            {
                System.Console.WriteLine("Derived.Inner.Inner");
            }
        }
        private Inner inner = new Inner();
    }


    class Program
    {
        static void Main(string[] args)
        {
            Derived d = new Derived();
            Console.Read();
        }
    }

 

若是真有在構造函數中調用虛函數的必要,應將該類或該重載的虛函數設爲seal,以免被繼承。code

相關文章
相關標籤/搜索