Порядок инициализации в классе и список инициализации конструктора - PullRequest
0 голосов
/ 07 сентября 2018

Я хочу инициализировать группу членов в классе, чтобы обеспечить чистоту исходного файла. Однако объекты принимают аргумент, который я получаю только через конструктор, и могут инициализироваться либо в списке инициализации конструктора, либо в конструкторе через присваивание. (Второй вариант, конечно, не сработает.) Это в основном сценарий:

В заголовке

class Foo
{

public:
    Foo(Pointer * ptr);

private:

    Pointer * ptr;
    Member m1{ptr, "SomeText"};
    Member m2{ptr, "SomeOtherText"};
}

В CPP

Foo::Foo(Pointer*ptr) : 
    ptr(ptr) 
{
    // ...
}   

Теперь возникает вопрос: говорит ли стандарт что-нибудь о порядке инициализации между ptr и m1 / m2? Очевидно, этот код будет работать только тогда, когда ptr инициализируется до m1 и m2.

Ответы [ 3 ]

0 голосов
/ 07 сентября 2018

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

[class.base.init] # 13,3

(13.3) - Затем не статические члены данных инициализируются в порядке, в котором они были объявлены в определении класса (опять же, независимо от порядка mem-инициализаторов).

[Примечание. Порядок декларирования должен обеспечивать уничтожение базовых и дочерних подобъектов в обратном порядке инициализации. - конец примечания]

Это означает, что порядок инициализации всегда будет ptr -> m1 -> m2.

0 голосов
/ 07 сентября 2018

Порядок в определении класса важен и определяет порядок инициализации. Нет никакого способа избежать этого заказа, кроме как переопределить ваш класс (то есть поменять местами порядок).

Как только вы попадете в тело конструктора, вы можете присвоить значение любой неконстантной переменной-члена с любым значением, которое вы хотите, но в этот момент они уже были инициализированы. Если вы хотите инициализировать элемент до этого, вы должны сделать это перед телом конструктора - то есть использовать либо Foo::Foo(Pointer * ptr) : ptr(ptr) {}, либо инициализировать их, как вы делаете с m1 и m2.

0 голосов
/ 07 сентября 2018

Стандартно определяется. Члены инициализируются в порядке объявления внутри класса, поэтому Ваш код является абсолютно корректным. Потенциальная опасность - несогласованный порядок инициализации в конструкторе с порядком членов - тогда все еще поля инициализируются в порядке объявления.

...