2010-10-04 98 views
5

在繼承爲什麼基類構造函數首先得到調用爲什麼不是派生的?爲什麼構造函數按相反順序調用?

+2

請參閱:http://stackoverflow.com/questions/140490/base-constructor-in-c-which-gets-called-first,http://stackoverflow.com/questions/1882692/c-constructor-execution -訂購 – 2010-10-04 09:24:35

回答

7

確保在派生類中使用基類的公共或受保護成員之前,它們已被正確初始化。
確切地說,派生類構造函數首先運行,並且隱式調用基類構造函數,作爲編譯器(假定爲缺省無參數構造函數)在派生類構造函數的主體中插入的第一條語句。

3

派生類是通過擴展基類創建的。應該確保在基類成員可以在派生類中進行擴展之前,它已被正確初始化。此外,派生類中初始化的成員不應被基類覆蓋。

2

什麼首先出生,父母或孩子?

3

考慮一下如果是相反的情況會發生什麼。我們來設想一個具有_id值的用戶類。 0的_id是一個代表「客人」賬戶的特殊值(忽略「特殊值」的問題,首先它們並不總是一個壞主意,其次這僅僅是一個例子)。 _id也可以在施工後不能更改(這是有道理的,如果它可以改變它不再是一個標識符)。

public class User 
{ 
    private readonly int _id; 
    public User(int id) 
    { 
    _id = id; 
    } 
    public int ID 
    { 
    get { return _id; } 
    } 
    public bool IsGuest 
    { 
    get { return _id == 0; } 
    } 
} 

現在考慮一個Admin類,從它的子類。 Admin類的其中一個規則是客人永遠不能成爲管理員。這不變應在所有點強制執行的客戶狀態可以改變,在這種情況下只是在構造函數:

public class Admin : User 
{ 
    public Admin(int id) 
    :base(id) 
    { 
    if(IsGuest) 
     throw new SecurityException("Guest users cannot be admins."); 
    } 
} 

如果AdminUser以前建造的話,那就總是拋出此異常,作爲供試品將始終將0與0進行比較。如果我們對guest虛擬機有不同的特殊值,那麼它會更糟,並且即使在它應該時也不會拋出異常,並且會導致安全問題。

請記住,編寫Admin類的人不需要知道User如何工作,而不是記錄有關其公共和受保護接口的內容。他們可以通過添加他們自己的測試來確定id是否爲零,但除了這是代碼的不必要重複之外,他們沒有理由爲什麼他們應該知道IsGuest檢查是如何工作的,而且它可能會更加複雜比以上,也許可能是專有,混淆和無證。更一般地說,如果沒有「構建一個用戶」的概念作爲先發生的事情,那麼「構建一個管理員」的整個概念是沒有意義的,我們不能使一個更專門化的X沒有做一個X作爲先決條件。

相關問題