2010-10-04 6 views
5

В наследовании, почему конструктор базового класса сначала получает вызов, почему не производный?Почему конструктор вызывается в обратном порядке?

+2

См. Http://stackoverflow.com/questions/140490/base-constructor-in-c-which-gets-called-first, http://stackoverflow.com/questions/1882692/c-constructor-execution -заказ –

ответ

7

Чтобы убедиться, что общедоступные или защищенные члены базового класса правильно инициализированы до их использования в производном классе.
Чтобы быть точным, конструктор производного класса запускается сначала с неявным вызовом конструктора базового класса, вставленного в качестве первого оператора в купе конструктора производного класса компилятором (при условии, что конструкторы по умолчанию не являются аргументами).

3

Производный класс создается путем расширения базового класса. Должно быть обеспечено, чтобы элементы базового класса были правильно инициализированы, прежде чем он может быть расширен в производном классе. Кроме того, члены, инициализированные в производном классе, не должны быть переопределены базовым классом.

2

Что родится первым, родитель или ребенок?

3

Рассмотрите, что может случиться, если это было наоборот. Представим себе класс пользователя со значением _id. _id 0 - это специальные значения, которые представляют собой гостевую учетную запись (игнорируйте проблемы вокруг «специальных значений», во-первых, они не всегда являются плохими идеями, а во-вторых, это всего лишь пример). _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."); 
    } 
} 

Если Admin была построена до User то всегда будет бросать это исключение, так как тест будет всегда сравните 0 с 0. Если бы у нас было другое особое значение для гостей, тогда было бы еще хуже и никогда не бросать исключение даже тогда, когда это необходимо, и разрешать проблему безопасности.

Имейте в виду, что человек, который называет класс Admin, не должен знать, как User работает помимо того, что описано в его общедоступном и защищенном интерфейсе. Они могли уловить проблему выше, добавив свой собственный тест на то, является ли id нулевым или нет, но кроме того, что это ненужное дублирование кода, нет причин, по которым они должны знать, как работает проверка IsGuest, и это может быть намного сложнее чем он выше, а может быть, и, возможно, проприетарный, запутанный и недокументированный.

В общем, вся концепция «создания администратора» не имеет смысла без понятия «конструирование пользователя» как чего-то, что произошло первым, мы не можем сделать более специализированный тип X без создания X как необходимое условие.

Смежные вопросы