В определении конструктора для класса инициализаторы для прямых и виртуальных подобъектов базового класса и нестатических членов данных могут быть указаны с помощью a ctor-initializer, который имеет форму
ctor-initializer: : mem-initializer-list
mem-initializer-list: mem-initializer ...opt mem-initializer-list , mem-initializer ...opt
mem-initializer: mem-initializer-id ( expression-listopt ) mem-initializer-id braced-init-list
mem-initializer-id: class-or-decltype identifier
В mem-initializer-idисходном неквалифицированном поиске identifierвыполняется поиск в области действия класса конструктора, и, если он не найден в этой области, выполняется поиск в области, содержащей определение конструктора. [ Note: Если класс конструктора содержит член с тем же именем, что и прямой или виртуальный базовый класс класса, mem-initializer-id именование члена или базового класса, состоящее из одного идентификатора, относится к члену класса. Для mem-initializer-id скрытого базового класса можно указать полное имя. ] Если не названы класс конструктора, нестатический член данных класса конструктора или прямая или виртуальная база этого класса, объект имеет неправильный формат. — end note mem-initializer-idmem-initializer
A mem-initializer-list может инициализировать базовый класс, используя любой, class-or-decltypeкоторый обозначает этот тип базового класса. [ Example:
struct A { A(); };
typedef A global_A;
struct B { };
struct C: public A, public B { C(); };
C::C(): global_A() { } // mem-initializer for base A
— end example ]
Если a mem-initializer-id неоднозначно, потому что он обозначает как прямой не виртуальный базовый класс, так и унаследованный виртуальный базовый класс, mem-initializer это неправильно сформировано. [ Example:
struct A { A(); };
struct B: public virtual A { };
struct C: public A, public B { C(); };
C::C(): A() { } // ill-formed: which A?
— end example ]
A ctor-initializer может инициализировать вариантный член класса конструктора. Если a ctor-initializer указывает более одного mem-initializer для одного и того же члена или для одного и того же базового класса, ctor-initializer это неправильно сформировано.
A mem-initializer-listможет делегировать другому конструктору класса конструктора, используя любой, class-or-decltypeкоторый обозначает сам класс конструктора. Если mem-initializer-idобозначает класс конструктора, он должен быть единственным mem-initializer; конструктор - этоdelegating constructor, а конструктор, выбранный объектом, mem-initializer- этоtarget constructor. Целевой конструктор выбирается по разрешению перегрузки. После возврата целевого конструктора выполняется тело делегирующего конструктора. Если конструктор прямо или косвенно делегирует себе полномочия, программа имеет неправильный формат и диагностика не требуется. [ Example:
struct C { C( int ) { } // #1: non-delegating constructor C(): C(42) { } // #2: delegates to #1 C( char c ) : C(42.0) { } // #3: ill-formed due to recursion with #4 C( double d ) : C('a') { } // #4: ill-formed due to recursion with #3 };
— end example ]
expression-list Или braced-init-list в mem-initializer используются для инициализации назначенного субобъекта (или, в случае делегирования конструктора, полный класс объекта) в соответствии с правилами инициализаций[dcl.init] для прямой инициализации. [ Example:
struct B1 { B1(int); /* ... */ }; struct B2 { B2(int); /* ... */ }; struct D : B1, B2 { D(int); B1 b; const int c; }; D::D(int a) : B2(a+1), B1(a+2), c(a+3), b(a+4) { /* ... */ } D d(10);
— end example ] [ Note: Инициализация, выполняемая каждым из них, mem-initializer представляет собой файлfull-expression. Любое выражение в a mem-initializer оценивается как часть полного выражения, выполняющего инициализацию. ] A, где означает, что виртуальный базовый класс игнорируется во время выполнения конструктора любого класса, который не является самым производным классом. — end note mem-initializermem-initializer-id
Временное выражение, привязанное к ссылочному элементу в a, mem-initializer имеет неправильный формат. [ Example:
struct A {
A() : v(42) { } // error
const int& v;
};
— end example ]
В конструкторе без делегирования, если данный потенциально сконструированный подобъект не обозначен a mem-initializer-id (включая случай, когда его нет, mem-initializer-list потому что у конструктора нет ctor-initializer), тогда
если объект является нестатическим членом данных, который имеетdefault member initializer либо
класс конструктора - этоunion, и никакой другой вариантный член этого союза не обозначен символом mem-initializer-idили
класс конструктора не является объединением, и, если предприятие является членом анонимного союза, ни один из членов этого союза не обозначаются mem-initializer-id,
сущность инициализируется из инициализатора члена по умолчанию, как указано в[dcl.init];
в противном случае, если сущность является анонимным объединением или вариантом member ([class.union.anon]), инициализация не выполняется;
в противном случае - сущностьdefault-initialized.
[ Note: Anabstract class никогда не является наиболее производным классом, поэтому его конструкторы никогда не инициализируют виртуальные базовые классы, поэтому соответствующий класс mem-initializers может быть опущен. ] Попытка инициализировать более одного нестатического элемента данных объединения приводит к неправильному формату программы. [ После того , как вызов конструктора для класса для объекта с автоматической или динамической продолжительностью хранения завершен, если конструктор не был вызван как часть значения инициализации и член не является ни инициализацией , ни присваивается значение во время выполнения из тело конструктора, член имеет неопределенное значение. ] [ — end note Note: XXcompound-statement — end note Example:
struct A { A(); }; struct B { B(int); }; struct C { C() { } // initializes members as follows: A a; // OK: calls A::A() const B b; // error: B has no default constructor int i; // OK: i has indeterminate value int j = 5; // OK: j has the value 5 };
— end example ]
Если данный нестатический член данных имеет как инициализатор члена по умолчанию, так и a mem-initializer, выполняется инициализация, указанная в mem-initializer, и инициализатор члена нестатических данных по умолчанию игнорируется. [ Example: Учитывая
struct A {
int i = /* some integer expression with side effects */ ;
A(int arg) : i(arg) { }
// ...
};
A(int) конструктор просто инициализацииi со значением arg, и побочных эффектов вiинициализаторе члена по умолчанию «S не будет иметь место. ] — end example
Временное выражение, привязанное к ссылочному элементу из инициализатора элемента по умолчанию, имеет неправильный формат. [ Example:
struct A { A() = default; // OK A(int v) : v(v) { } // OK const int& v = 42; // OK }; A a1; // error: ill-formed binding of temporary to reference A a2(1); // OK, unfortunately
— end example ]
В конструкторе без делегирования деструктором для каждого потенциально сконструированного подобъекта типа класса являетсяpotentially invoked. [ Note: Это положение гарантирует, что деструкторы могут быть вызваны для полностью сконструированных подобъектов в случае возникновения исключения ([except.ctor]). ] — end note
В конструкторе без делегирования инициализация выполняется в следующем порядке:
Во-первых, и только для конструктораmost derived classвиртуальных базовых классов инициализируются в том порядке, в котором они появляются при обходе направленного ациклического графа базовых классов в глубину слева направо, где «слева направо» порядок появления базовых классов в производном классе base-specifier-list.
Затем прямые базовые классы инициализируются в порядке объявления, как они появляются в base-specifier-list (независимо от порядка mem-initializers).
Затем нестатические элементы данных инициализируются в том порядке, в котором они были объявлены в определении класса (опять же, независимо от порядка mem-initializers).
Наконец, compound-statementвыполняется тело конструктора.
[ Note: Порядок объявления необходим, чтобы гарантировать, что базовые и членские подобъекты уничтожаются в порядке, обратном инициализации. ] — end note
[ Example:
struct V { V(); V(int); }; struct A : virtual V { A(); A(int); }; struct B : virtual V { B(); B(int); }; struct C : A, B, virtual V { C(); C(int); }; A::A(int i) : V(i) { /* ... */ } B::B(int i) { /* ... */ } C::C(int i) { /* ... */ } V v(1); // use V(int) A a(2); // use V(int) B b(3); // use V() C c(4); // use V()
— end example ]
Имена в expression-list или braced-init-list из a mem-initializer оцениваются в области действия конструктора, для которого mem-initializer указан. [ Example:
class X { int a; int b; int i; int j; public: const int& r; X(int i): r(a), b(i), i(i), j(this->i) { } };
инициализируется X::r для ссылки X::a, инициализируется X::b значением параметра конструктора i, инициализируется X::i значением параметра конструктора iи инициализируется X::j значением X::i; это происходит каждый раз, когда создается объект класса X . ] [ Поскольку они оцениваются в области видимости конструктора, указатель может использоваться в элементе a для ссылки на инициализируемый объект. ] — end example Note: mem-initializerthisexpression-listmem-initializer — end note
Дляvirtual member functionsстроящегося объекта можно вызывать функции-члены (в том числе ). Точно так же строящийся объект может быть операндом typeid operator или для dynamic_cast. Однако, если эти операции выполняются в ctor-initializer (или в функции, вызываемой прямо или косвенно из a ctor-initializer) до завершения всех mem-initializers базовых классов for, программа имеет неопределенное поведение. [ Example:
class A { public: A(int); }; class B : public A { int j; public: int f(); B() : A(f()), // undefined: calls member function but base A not yet initialized j(f()) { } // well-defined: bases are all initialized }; class C { public: C(int); }; class D : public B, C { int i; public: D() : C(f()), // undefined: calls member function but base C not yet initialized i(f()) { } // well-defined: bases are all initialized };
— end example ]
[ Note: [class.cdtor] описывает результат вызовов виртуальных функций typeid и dynamic_casts во время построения для четко определенных случаев; то есть описывает polymorphic behavior строящийся объект. ] — end note
За mem-initializerкоторым следует многоточиеpack expansion , инициализируются базовые классы, указанные в раскрытии пакета в base-specifier-list классе. [ Example:
template<class... Mixins> class X : public Mixins... { public: X(const Mixins&... mixins) : Mixins(mixins)... { } };
— end example ]