8.5.3 Производные классы
В конструкции
сост идентификатор : public opt typedef-имя
typedef-имя должно означать ранее описанный класс, назваемый базовым классом для описываемого класса. Говорится, что последний выводится из предшествующего (является проиводным от него). По поводу смысла public см. #8.5.9. На члены базового класса можно ссылаться так, как если бы они были членами производного класса, за исключением тех случаев, кода имя базового члена было переопределено в производном класе; в этом случае для ссылки на скрытое имя можно использвать операцию :: (#7.1). Производный класс сам может использоваться в качестве базового класса. Невозможно стристь производные от union (#8.5.13). Указатель на производный класс может неявно преобразовываться в указатель на открытый
базовый класс (#6.7).
Для объектов класса, производного от класса, для которго была определена operator= (#8.5.11), присваивание неявно не определено (#7.14 и #8.5)
Например:
class base (* int a, b; *);
class derived : public base (* int b, c; *);
derived d;
d.a = 1; d.base::b = 2; d.b = 3; d.c = 4;
осуществляет присваивание четырем членам d.
8.5.4 Виртуальные функции
Если базовый класс base содержит virtual (виртуальную) (#8.1) функцию vf, а производный класс derived также содержит функцию vf, то обе функции должны иметь один и тот же тип, и вызов vf для объекта класса derived вызывает derived::vf. Например:
struct base (* virtual void vf (); void f (); *);
class derived : public base (* void vf (); void f (); *);
derived d; base* bp = amp;d; bp-»vf(); bp-»f();
Вызовы вызывают, соответственно, derived::vf и base::f для объекта класса derived, именованного d. Так что интерпртация вызова виртуальной функции зависит от типа объекта, для которого она вызвана, в то время как интерпретация вызова нвиртуальной функции зависит только от типа указателя, обознчающего объект.
Виртуальная функция не может быть другом (friend) (#8.5. 10). Функция f в классе, выведенном из класса, который имеет виртуальную функцию f, сама считается виртуальной. Виртуалная функция в базовом классе должна быть определена. Виртальная функция, которая была определена в базовом классе, не обязательно должна определяться в производном классе. В этом случае во всех вызовах используется функция, определенная для базового класса.
8.5.5 Конструкторы
Функция член с именем, совпадающим с именем ее класса, называется конструктором. Если класс имеет конструктор, то он вызывается для каждого объекта этого класса перед тем, как этот объект будет калибо использован, см. #8.6.
Конструктор не может быть virtual или friend.
Если класс имеет базовый класс или объекты члены с контрукторами, их конструкторы вызываются до конструктора проиводного класса. Первым вызывается конструктор базового класа. Объяснение того, как для таких конструктороу могут специфицироваться параметры , см. в #10, а того, как контрукторы могут использоваться для управления свободной пмятью, см. в #8.5.8.
Объект класса с конструктором не может быть членом обединения.
Для конструктора нельзя задать возвращаемое значение, как нельзя использовать оператор return в теле конструктора.
Конструктор может явно применяться для создания новых объектов его типа используя синтаксис
typedef-имя ( список_параметров opt )
Например,
complex zz = complex (1,2.3); cprint (complex (7.8,1.2));
Объекты, созданные таким образом, не имеют имени (если только конструктор не использован как инициализатор, как это было с zz выше), и их время жизни ограничено областью видмости, в которой они созданы.
8.5.6 Преобразования
Конструктор, получающий один параметр, определяет преоразование из типа своего параметра в тип своего класса. Такие преобразования неявно применяются дополнительно к стандартным пробразованиям (#6.6-7). Поэтому присваивание объекту из класса X допустимо, если тип T присваиваемого значения есть X, или если было описано преобразование из T в X. Аналогично конструкторы используются для преобразования инициализаторов (#8.6), параметров функции (#7.1) и возвращаемых функцией значений (#9.10). Например:
class X (* ... X (int); *); f (X arg) (* X a = 1; // a = X (1) a = 2; // a = X (2) f (3); // f (X (3)) *)
Если ни один конструктор для класса X не получает приваиваемый тип, то не делается никаких попыток отыскать другие конструкторы для преобразования присваиваемого значения в тип, который мог бы быть приемлем для конструкторов класса X. Например: class X (* ... X (int); *); class X (* ... Y (X); *); Y a = 1; // недопустимо: Y (X (1)) не пробуется Функция член класса X с именем вида имя_функции_преобразования:
operator тип
задает преобразование из X в тип. Тип не может содержать описания [] «вектор из» или () «функция, возвращающая». Оно будет применяться неявно аналогично конструкторам выше (толко если оно единственно: #8.9), или его можно вызвать явно с помощью записи приведения к типу. Например:
class X (* // ... operator int(); *);
X a; int i = int(a); i = (int)a; i = a;
Во всех трех случаях значене будет преобразовываться функцией X::operator int(). Применение определяемых пользовтелем преобразований не сводится только к присваиваниям и инициализациям. Например:
X a, b; // ... int i = (a) ? 1+a : 0; int j = (a amp; amp;b) ? a+b : i;
8.5.7 Деструкторы
Функция член класса cl с именем ~cl называется деструтором. Деструктор не возвращает никакого значения и не полчает никаких параметров; он используется для уничтожения знчений типа cl непосредственно перед уничтожением содержащего их объекта. Деструктор не может быть вызван явно.
Деструктор для базового класса выполняется после десруктора производного от него класса. Деструкторы для объектов членов выполняются после деструктора для объекта, членом кторого они являются. Как деструкторы используютя для управлния свободной памятью, см. объяснение в #8.5.8.
Объект класса с деструктором не может быть членом обединения.
8.5.8 Свободная память
Когда с помощью операции new создается классовый объект, то для получения необходимой памяти конструктор будет (неяно) использовать operator new (#7.1). Конструктор может осществить свое собственное резервирование памяти посредством присваивания указателю this до каких-либо использований члна. С помощью присваивания this значения ноль деструктор мжет избежать стандартной операции дерезервирования памяти для объекта его класса. Например:
class cl (* int v[10]; cl () (* this = my_own_allocator (sizeof (cl)); *) ~cl () (* my_own_deallocator (this); this = 0; *) *) На входе в конструктор this являеется не-нулем, если рзервирование памяти уже имело место (как это имеет место для auto, static объектов и объектов членов), и нулем в остальных случаях. Вызовы конструкторов для базового класса и объектов члнов будут иметь место после присваивания указателю this. Если
конструктор базового класса осуществляет присваивание this, то новое значение также будет использоваться конструктором производного класса (если таковой есть).
При уничтожении вектора объектов класса с деструктором необходимо указывать число элементов. Например:
class X (* ... ~X(); *); X* p = new X [size]; delete[size] p;