Идиомы и стили С++ | страница 6



, и по моему, обе диспетчеризации происходят по механизму виртуальных функций. Увы, мне лень набирать код.

Код к данному шагу я не проверял, в отличие от предыдущих. К диспетчеризации мы еще вернемся. Или не вернемся. Но следующий шаг однозначно про указатели.

Шаг 5 - Ведущие указатели (Master Pointers). Важные конструкторы.

Если мы уж взялись заниматься умными указателями, то очень быстро придем к выводу, что неплохо ограничить их свободу так, чтобы два указателя не указывали на один объект. Далее я их называю ведущими указателями. Для этого нужно реализовать буквально три-четыре правила:

1. Порождение ведущего указателя порождает объект, уничтожение ведущего указателя уничтожает объект;

2. Копирование ведущего указателя создает точную копию объекта;

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

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

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

>class CThat {

>private:

> int i;

>public:

> CThat (int _i=0):i(_i) {}

> CThat (const CThat& _that):i(_that.i) {}

> CThat& operator=(const CThat& _that) {

>  if (this == &_that) return *this;

>  i = _that.i;

>  return *this;

> }

>};


>class MasterPointer {

>private:

> CThat* t;

>public:

> // MasterPointer():t(new CThat){}

> MasterPointer(CThat _that=0):t(new CThat(_that)) {}

> MasterPointer(const MasterPointer& mp): t(new CThat((*mp.t))) {}

> ~MasterPointer() { delete t; }

> MasterPointer& operator=(const MasterPointer& mp) {

>  if (this != &mp) {

>   delete t;

>   t = new CThat(*(mp.t));

>  }

>  return *this;

> }

>};

Напоминать не надо, что this - это указатель на самого себя? Кстати и оказалось, что для реализации ведущего указателя класс указываемого объекта должен и сам иметь:

1. Конструктор без аргументов или с аргуметами, имеющими значения по умолчанию (default constructor). Компилятор вам нарисует такой один, если вы не определите конструкторов вообще никаких. На вид это будет просто ежик чернобыльский. Попытка создать внутри функции (я имею в виду в стеке) массив таких объектов наплодит вам массив дегенератов (это вне семантики ведущих указателей, мы же договариваемся, что без ведущих указателей такие объекты вообще не существуют). Так что не рискуйте.