2010-10-04 91 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作为先决条件。

相关问题