Выполнение конструктора в C ++ - PullRequest
2 голосов
/ 10 сентября 2011

Выполнение конструктора выполняется в два этапа:

  1. Фаза инициализации

  2. Фаза выполнения тела, которая состоит из всехзаявления в теле конструктора.Обратите внимание, что члены данных типа класса всегда инициализируются на этапе инициализации, независимо от того, инициализирован ли член явно в списке инициализатора конструктора.Инициализация происходит перед выполнением любого оператора в теле конструктора.

Рассмотрим способ инициализации экземпляра ученика класса конструктором -

Student(string &fn, string &ln, int i, int y = Freshman)
    : first_name(fn)
    , last_name(ln)
    , id(i)
    , year(y)
{}

Это еще один, но «неэффективный» и «не элегантный» способ сделать то же самое -

Student(string &fn, string &ln, int i, int y = Freshman)  
 {
     first_name = fn;
     last_name = ln;
     id = i;
     year = y; 
 }

Этот конструктор в новом коде (код выше) назначаетученики класса ученика.Он явно не инициализирует их.Независимо от того, существует ли явный инициализатор или нет, члены first_name и last_name инициализируются еще до выполнения конструктора.Этот конструктор неявно использует строковый конструктор по умолчанию для инициализации членов first_name и last_name.Когда выполняется тело конструктора, члены first_name и last_name уже имеют значения.Эти значения перезаписываются присваиванием внутри тела конструктора.

Таким образом, это означает, что к моменту, когда выполнение достигает открывающей скобки конструктора, это условие -

  • 'first_name', которое является строкой , инициализируется вызовом строкового конструктора по умолчанию (тот, который компилятор ' делает ').
  • 'last_name', которое является строкой , инициализируется вызовом строкового конструктора по умолчанию (тот, который компилятор ' создает ').
  • 'id',это целое число равно неинициализировано .
  • 'год', которое является целое число равно неинициализировано .

И теперь ясно, что присваивания выполняются для каждой из четырех переменных в теле конструктора.

Это мойпонимание этой вещи правильно?Я почему-то чувствую, что мне чего-то не хватает.

Кроме того, при использовании списков инициализации используются конструкторы по умолчанию (тот, который компилятор делает для нас ), вызывается и передается с нашими параметрами(в случае string ) и инициализация выполняется как в "int id = i;" в случае id (i) ??

PS: большинство изцитаты из этой ссылки -

http://www.bogotobogo.com/cplusplus/constructor.php

Ответы [ 3 ]

7 голосов
/ 10 сентября 2011

Ваше понимание в основном верно, за исключением того, что вы должны инициализировать const членов в инициализаторе, потому что вы не можете назначить им (потому что они const) в теле конструктора или где-нибудь еще когда-либо снова. Если вы попытаетесь оставить элемент const неинициализированным, вы получите ошибку компиляции.

И да, в списках инициализации вызывается конструктор объекта, который соответствует аргументам, которые вы ему даете. Если аргументов нет (например, : blah()), вызывается конструктор по умолчанию.

Кроме того, в некоторых случаях вы обязательно должны использовать список инициализаторов (это не необязательно ), например

  • Когда в классе const членов
  • Когда класс является непосредственным потомком класса без конструктора по умолчанию
  • Когда у класса есть ссылочные члены
1 голос
/ 10 сентября 2011

Кроме того, при использовании списков инициализации используются конструкторы по умолчанию (тот, который компилятор делает для нас), которые вызываются и передаются с нашими параметрами (в случае строки), а инициализация выполняется так же, как в случае «int id = i;» в случае из id (i) ??

Во-первых, конструкторы по умолчанию не обязательно "те, которые компилятор делает для нас". Они просто конструкторы без параметров, например Student(). Иногда компилятор автоматически генерирует один, например, для int, а иногда его нужно написать, например, для std::string.

Простой способ думать об этом таков: если присутствует инициализатор, то вызывается соответствующий конструктор. Итак, если предположить, что first_name равно std::string, то инициализатор first_name(fn) приводит к созданию first_name с std::string::string(const std::string&), передавая fn в качестве параметра. Если инициализатор не используется, то first_name создается с std::string::string() до выполнения кода { ... }, затем, когда вы пишете first_name = fn;, это приводит к вызову std::string::operator =(const std::string&), передавая fn в качестве параметра.

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

1 голос
/ 10 сентября 2011

Вы не говорите, как определяется ваш класс Student, но вы можете быть запутаны в одном: во второй, "не элегантной" версии, first_name не обязательно является константной строкой - скорее, fn является ссылкой на константную строку, и вы присваиваете значение вашей переменной-члену first_name.

Теперь перейдем к спискам инициализаторов: суть в том, что вы можете указать, какие конструкторы объектов-членов вызываются. Без списка все объекты-члены имеют свои конструкторы по умолчанию (или, точнее, они инициализируются по умолчанию). Однако любой объект, который вы упомянули в списке инициализатора, будет иметь , который конструктор (или, скорее, «инициализатор») будет называться вместо .

Список инициализаторов - это не просто украшение. Это важно, потому что объекты-члены и подобъекты могут даже не быть конструируемыми по умолчанию, и поэтому должен быть предусмотрен инициализатор . Член const на самом деле очень хороший пример:

struct Foo
{
  const int n;
  Foo();  // error! What is n?
  Foo(int m) : n(m) { } // OK
};

Вот еще один пример, на этот раз производный от базового класса, у которого нет конструктора по умолчанию:

struct Bar : Foo
{
  Bar();  // error! How to initialize Foo?
  Bar() : Foo(5) { } // OK, now Bar::n == 5
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...