logo
volkov / C++ / Бьерн Страуструп-Справочное руководство по С++

R.12.6.2 Инициализация членов и базовых классов

В определении конструктора можно задать инициализацию прямых

базовых классов и членов, не наследуемых из базовых классов. Это

особенно полезно для тех объектов, констант и ссылок, для которых

различаются семантики присваивания и инициализации. Конструкция

инициализатор-ctor имеет вид

инициализатор-ctor:

: список-инициализаторов-членов

список-инициализаторов-членов:

инициализатор-члена

инициализатор-члена , список-инициализаторов-члена

инициализатор-члена:

полное-имя-класса ( список-выражений opt )

идентификатор

Список параметров используется для инициализации нестатических членов

или объектов базового класса. Это единственный способ инициализации

нестатических членов, являющихся ссылками или объектами типа const,

например:

struct B1 { B1(int); /* ... */ };

struct B2 { B2(int); /* ... */ };

struct D : B1, B2 {

D(int);

B1 b;

const c;

};

D::D(int a) : B2(a+1), B1(a+2), c(a+3), b(a+4)

{ /* ... */ }

D d(10);

В начале инициализируются базовые классы в порядке их описания

(независимо от порядка инициализаторов-членов), затем по той же

схеме инициализируются члены, и наконец выполняется тело D::D()

($$R.12.1). Порядок описания выдерживается для того, чтобы гарантировать,

что вложенные объекты и члены будут уничтожаться в порядке, обратном

их инициализации.

Особый случай представляют виртуальные базовые классы. Они создаются

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

в каком появляются при обходе снизу и слева-направо ацикличного

направленного графа базовых классов. Порядок "слева-направо" - это

тот, в котором имена базовых классов задаются при описании в

производном классе.

Полным называется объект, который не является вложенным объектом,

представляющим некоторый базовый класс. Класс такого объекта

называют наибольшим производным классом объекта. Все вложенные

объекты виртуальных базовых классов инициализируются с помощью

конструктора наибольшего производного класса. Если в конструкторе

наибольшего производного класса не задан инициализатор-члена для

виртуального базового класса, тогда этот виртуальный базовый класс

должен иметь стандартный конструктор,либо не иметь никакого

конструктора. Всякий инициализатор-члена для виртуального базового

класса, заданный не в конструкторе класса полного объекта, игнорируется.

Приведем пример:

class V {

public:

V();

V(int);

// ...

};

class A : public virtual V {

public:

A();

A(int);

// ...

};

class B : public virtual V {

public:

B();

B(int);

// ...

};

class C : public A, public B, private virtual V {

public:

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()

Инициализатор-члена вычисляется в области видимости конструктора,

в котором он появился. Например, в следующем фрагменте

class X {

int a;

public:

const int& r;

X()::r(a) { }

};

X::r инициализируется для каждого объекта класса X ссылкой на X::a.