構造函數的調用順序是先調用System.Object,再按照層次結構由上向下(基類=》派生類)進行,直到到達編譯器要實例化的類為止。在此過程中,每個構造函數都初始化自己類中的字段。編譯器先自下而上查找構造函數,然后再自上而下地執行。
以下通過示例說明派生類的構造函數是如何執行的。
1.基類和派生類都未顯示定義構造函數
執行GenericCustomer customer = new Nevermore60Customer();語句時,編譯器首先找到試圖實例化的類的構造函數即Nevermore60Customer 類的默認構造函數,默認Nevermore60Customer 構造函數首先要做的是為其直接基類GenericCustomer運行默認構造函數,然后GenericCustomer構造函數為其直接基類System.Object運行默認構造函數。而System.Object沒有任何基類,所以它的默認構造函數直接執行;接着執行GenericCustomer的默認構造函數,將name字段初始化為null;最后執行Nevermore60Customer的默認構造函數,將highCostMinutesUsed字段初始化未0,並退出。
abstract class GenericCustomer { private string name; } class Nevermore60Customer : GenericCustomer { private uint highCostMinutesUsed; }
2.基類定義了一個無參構造函數
執行GenericCustomer customer = new Nevermore60Customer();語句,構造函數執行順序:System.Object類的默認構造函數=》GenericCustomer類的顯示無參構造函數(將name字段初始化為“<no name>”)=》Nevermore60Customer類的默認無參構造函數(將highCostMinutesUsed字段初始化為0)。
abstract class GenericCustomer { private string name; public GenericCustomer() :base() //base,調用基類的構造函數(本例中調用System.Object中的構造函數,與默認情況相同,可省略) { name = "<no name>"; } } class Nevermore60Customer : GenericCustomer { private uint highCostMinutesUsed; }
注意:若把GenericCustomer類中的構造函數聲明為private,則類Nevermore60Customer會產生一個編譯錯誤。因為編譯器試圖為Nevermore60Customer類生成默認構造函數時,需要調用類GenericCustomer的無參構造函數,但是這個函數是類GenericCustomer所私有的,其他類無法調用。
3.基類和派生類都定義了有參構造函數
執行GenericCustomer customer = new Nevermore60Customer("LiSi");語句時,構造函數執行順序:System.Object類的默認構造函數=》GenericCustomer類的有參構造函數(將name字段初始化為“LiSi”)=》Nevermore60Customer類的有參構造函數(什么也不做)。
abstract class GenericCustomer { private string name; public GenericCustomer(string name) { this.name = name; } } class Nevermore60Customer : GenericCustomer { private uint highCostMinutesUsed; public Nevermore60Customer(string name) :base(name) { } }
注意:若類Nevermore60Customer未定義上面的有參構造函數,則類Nevermore60Customer會產生一個編譯錯誤。因為類Nevermore60Customer生成的默認構造函數會試圖調用GenericCustomer類中的無參構造函數,但它並沒有這樣的函數。
4.派生類中有多個構造函數
執行GenericCustomer customer = new Nevermore60Customer("LiSi");語句時,構造函數執行順序:System.Object類的默認構造函數=》GenericCustomer類的有參構造函數(將name字段初始化為“LiSi”)=》Nevermore60Customer類中有兩個參數的構造函數(將referrerName字段初始化為“None”)=》Nevermore60Customer類中有一個參數的構造函數(什么也不做)
abstract class GenericCustomer { private string name; public GenericCustomer(string name) { this.name = name; } } class Nevermore60Customer : GenericCustomer { private uint highCostMinutesUsed; private string referrerName; public Nevermore60Customer(string name, string referrerName) : base(name) { this.referrerName = referrerName; } public Nevermore60Customer(string name) : this(name, "<None>") { } }
參考來源:《C#高級編程(第9版)》