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.
R.12.7 Конструкторы и деструкторы
В конструкторах и деструкторах можно вызывать функцию-член. Отсюда следует, что можно вызывать (непосредственно или косвенно) виртуальные функции. Вызываемая функция должна быть определена в классе самого конструктора или деструктора или в базовых классах, но не должна быть функцией, которая их подавляет в производном классе. Этим обеспечивается то, что еще несозданные объекты не будут использованы при выполнении конструктора или деструктора. Рассмотрим пример:
class X {
public:
virtual void f();
X() { f(); } // вызов X::f()
~X() { f(); } // вызов X::f()
};
class Y: public X {
int& r;
public:
void f()
{
r++; // беда, если `r' не инициализировано
}
Y(int& rr)::r(rr) {}
};
Результат непосредственного или косвенного вызова из конструктора чистой виртуальной функции для инициализируемого объекта неопределен, если только явно не использовано уточнение имени функции (§R.10.3).
R.12.8 Копирование объектов класса
Объекты класса могут копироваться двумя способами: либо присваиванием (§R.5.17), либо инициализацией (§R.12.1, §R.8.4), которая может происходить при передаче параметров (§R.5.2.2) или результата функции (§R.6.6.3). Для класса X эти две операции концептуально реализуются как операция присваивания и конструктор копирования (§R.12.1). В программе можно определить или одну из них, или обе. Если пользователь не определил их в программе, то они будут для всех членов класса X определяться соответственно как присваивание по членам и инициализация по членам.
Если все базовые классы и все члены класса X имеют конструктор копирования, в котором допустимы в качестве параметра объекты типа const, то порождаемый конструктор копирования для X будет иметь единственный параметр типа const X& и записываться так:
X::X(const X&)
Иначе, у него будет единственный параметр типа X&:
X::X(X&)
и инициализация копированием объектов типа const класса X будет невозможна.
Аналогично, если все базовые классы и члены класса X имеют операцию присваивания, допускающую параметры типа const, тогда порождаемая для X операция присваивания будет иметь единственный параметр типа const X& и записываться так:
X& X::operator=(const X&)
Иначе, у нее будет единственный параметр типа X&:
X& X::operator=(X&)
и присваивание копированием объектов класса X типа const будет невозможно. Стандартная операция присваивания возвращает ссылку на объект, который нужно было копировать.
Объекты, представляющие виртуальные базовые классы, будут инициализироваться только один раз с помощью порождаемого конструктора копирования. Объекты, представляющие виртуальные базовые классы, допускают присваивания им только один раз с помощью порождаемой операции присваивания.
Присваивание по членам и инициализация по членам означают следующее: если класс X имеет в качестве члена класс M, для реализации присваивания и инициализации члена используются операции присваивания в M и конструктор копирования M соответственно. Если класс имеет член типа const, или член, являющийся ссылкой, или член или базовый класс такого класса, где функция operator=() является частной, то для него стандартная операция присваивания не может быть создана. Аналогично, если член или базовый класс класса M имеет частный конструктор копирования, то стандартный конструктор копирования для такого класса не может быть создан.
Пока не появится необходимость в определении, стандартные присваивание и конструктор копирования будут только описаны (т.е. не будет создано тело функции). Иными словами, функция X::operator=() будет порождена только тогда, когда нет явного описания операций присваивания, а объект класса X присваивается объекту класса X или объекту класса, производного от X, или вычисляется адрес функции X::operator=(). Аналогичная ситуация с инициализацией.
Читать дальше