Язык программирования C++ от Страуструпа

Объекты класса как члены


Рассмотрим пример:

class classdef {

  table members;

  int no_of_members;

  // ...

  classdef(int size);

  ~classdef();

};

Цель этого определения, очевидно, в том, чтобы classdef содержал член, являющийся таблицей размером size, но есть сложность: надо обеспечить вызов конструктора table::table() с параметром size. Это можно сделать, например, так:

classdef::classdef(int size)

  :members(size)

{

  no_of_members = size;



  // ...

}

Параметр для конструктора члена (т.е. для table::table()) указывается в определении (но не в описании) конструктора класса, содержащего член (т.е. в определении classdef::classdef()). Конструктор для члена будет вызываться до выполнения тела того конструктора, который задает для него список параметров.

Аналогично можно задать параметры для конструкторов других членов (если есть еще другие члены):

class classdef {

  table members;

  table friends;

  int no_of_members;

  // ...

  classdef(int size);

  ~classdef();

};

Списки параметров для членов отделяются друг от друга запятыми (а не двоеточиями), а список инициализаторов для членов можно задавать в произвольном порядке:

classdef::classdef(int size)

  : friends(size), members(size), no_of_members(size)

{

  // ...

}

Конструкторы вызываются в том порядке, в котором они заданы в описании класса.

Подобные описания конструкторов существенны для типов, инициализация и присваивание которых отличны друг от друга, иными словами, для объектов, являющихся членами класса с конструктором, для постоянных членов или для членов типа ссылки. Однако, как показывает член no_of_members из приведенного примера, такие описания конструкторов можно использовать для членов любого типа.

Если конструктору члена не требуется параметров, то и не нужно задавать никаких списков параметров. Так, поскольку конструктор table::table() был определен со стандартным значением параметра, равным 15, достаточно такого определения:

classdef::classdef(int size)

  : members(size), no_of_members(size)


{

  // ...

}

Тогда размер таблицы friends будет равен 15.

Если уничтожается объект класса, который сам содержит объекты класса (например, classdef), то вначале выполняется тело деструктора объемлющего класса, а затем деструкторы членов в порядке, обратном их описанию.

Рассмотрим вместо вхождения объектов класса в качестве членов традиционное альтернативное ему решение: иметь в классе указатели на члены и инициализировать члены в конструкторе:

class classdef {

  table* members;

  table* friends;

  int no_of_members;

  // ...

};

classdef::classdef(int size)

{

  members = new table(size);

  friends = new table;  // используется стандартный

  // размер table

  no_of_members = size;

  // ...

}

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

classdef::~classdef()

{

  // ...

  delete members;

  delete friends;

}

Такие отдельно создаваемые объекты могут оказаться полезными, но учтите, что members и friends указывают на независимые от них объекты, каждый из которых надо явно размещать и удалять. Кроме того, указатель и объект в свободной памяти суммарно занимают больше места, чем объект-член.


Содержание раздела