class Abracadabra
{
public:
Abracadabra();
~Abracadabra(){}
//Содержит в себе другие пользовательские классы MyDog, MyBook.
MyDog mDog;
MyBook mBook;
};
Корректная инициалицация членов класса.
Допустим есть у нас вот такой класс:
Код:
Допустим классы MyDog и MyBook могут инициализироваться числом определяющих к примеру возраст и строкой определяющей название: MyDod(3), MyBook("FooBar").
Особенностью класса Abracadabra допустим является то, что члены класса (объекты mDog и mBook) НЕ создаются со значениями по умолчанию, а инициализируются классом Abracadabra.
Т.е. к примеру, конструктор класса Abracadabra имеет такой вид:
Код:
Abracadabra::Abracadabra(): mDog(3), mCat("FooBar"){}
Собственно здесь я ничего нового не изложил. Но вот о чем прочел в книжке...
Раньше я думал, что порядок инициализаторов ...abra(): mDog(3), mBook("FooBar"){} Может иметь произвольный порядок, т.к. по сути мы до запуска конструктора основного класса запускаем конструкторы его членов. По идее, как мне казалось, порядок здесь не важен.
Однако в книге акцентирован тот момент, что инициализаторы обязательно должны идти в том же порядке, что и в объявлении членов класса!
Т.е. по всей видимости запись
Код:
Abracadabra::Abracadabra(): mBook("FooBar"), mDog(3){}
будет уже не корректной.
Терзают меня смутные сомнения, а так ли это? Или это необоснованные страшилки?
[QUOTE=Gigahard]Однако в книге акцентирован тот момент, что инициализаторы обязательно должны идти в том же порядке, что и в объявлении членов класса![/QUOTE]Фигня какая-то... Мне не интересны стандарты, но даже несмотря на потенциальную свою неосведомлённость в этой связи, осмелюсь заявить, что ситуация автором произведения явно искажена. Момент тут если и будет, то другого плана: порядок следования инициализаторов не важен, а реально поля будут инициализированы/сконструированы в порядке их (а не инициализаторов) следования при объявлении.
Осознал.
К примеру:
Код:
class FooBar
{
public:
FooBar();
~FooBar(){}
int a;
int b;
};
{
public:
FooBar();
~FooBar(){}
int a;
int b;
};
Если мы запишем конструктор в виде:
Код:
FooBar::FooBar():b(256), a(b){}
То в итоге получим не тот результат который ожидали. Т.е. первым все равно будет инициализироватся a и ему будет присвоено значение еще не инициализированного члена b. А член b инициализируется уже потом. В результате мы получим мусор в a и инициализированный b.
Я сначала не врубился в смысл строк, т.к. порядок инициализации до этого для меня был самоочевиден и я как то даже не задумывался над возможной проблемой.
Цитата: Der Meister
Мне не интересны стандарты
А почему? Удобно же цитаты приводить.
[QUOTE=Стандарт_п12.6.2(5)]— Then, nonstatic data members shall be initialized in the order they were declared in the class definition
(again regardless of the order of the mem-initializers).[/QUOTE]
Мой вольный перевод (английский у меня не очень, извиняйте) : После этого должны быть инициализированы нестатические члены-данные в порядке их определения в классе (не обращая внимания на порядок инициализвторов).
Цитата: Gigahard
Терзают меня смутные сомнения, а так ли это? Или это необоснованные страшилки?
Недавно столкнулся с этим. Но на практике. MinGW на код вида:
Код:
class Test
{
int value;
char symbol;
public:
Test(): symbol('k'), value(12) {}
};
{
int value;
char symbol;
public:
Test(): symbol('k'), value(12) {}
};
ругается так: warning 'Test::symbol' will be initialized after 'int Test::value' when initialized here (на строке с конструктором)
При обратном порядке инициализаторов все тихо.
Тоже было сюрпризом :)