不要在建構子中呼叫虛擬函式
最近發現當在建構子中設計要去呼叫虛擬函式時,會發生衍生類別因為還未完全執行完建構子的初始化動作,就直接呼叫它所改寫的虛擬函式的話,可能會引發一些問題。
例如:
執行結果如下:
在C#的實作中,它會先執行衍生類別所改寫的虛擬函式。但因為這時候MyDerivative的建構子還未執行,所以id2中並沒有設定成使用者在建構MyDerivative物件時所指定的值。所以輸出的結果中,id2就是預設值0了。
C++的實作方式跟C#不同,它會是呼叫基底類別的虛擬函式。
由於會有初始化未完全就執行其它相關函式的問題,所以在建構子中,最好是不要呼叫虛擬函式,或是說,最好是呼叫到只會使用到基底類別所提供的變數的虛擬函式。
例如:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace VS2020Test { public class CallVirtualFuncFromCtor { public static void UT() { MyDerivative md = new MyDerivative(2, 5); } } public class MyBase { protected int id = 0; public MyBase(int i) { id = i; ShowID(); } public virtual void ShowID() { Console.WriteLine("[Base] ID " + id.ToString()); } } public class MyDerivative : MyBase { protected int id2 = 0; public MyDerivative(int id, int id2) : base(id) { this.id2 = id2; } public override void ShowID() { Console.WriteLine("[Derivative] ID " + id.ToString() + ",ID2 " + id2.ToString() ); } } }
執行結果如下:
在C#的實作中,它會先執行衍生類別所改寫的虛擬函式。但因為這時候MyDerivative的建構子還未執行,所以id2中並沒有設定成使用者在建構MyDerivative物件時所指定的值。所以輸出的結果中,id2就是預設值0了。
C++的實作方式跟C#不同,它會是呼叫基底類別的虛擬函式。
由於會有初始化未完全就執行其它相關函式的問題,所以在建構子中,最好是不要呼叫虛擬函式,或是說,最好是呼叫到只會使用到基底類別所提供的變數的虛擬函式。
留言
張貼留言