Программирование >>  Синтаксис инициирования исключений 

1 ... 21 22 23 [ 24 ] 25 26 27 ... 82




Ведущие указатели и дескрипторы


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

Семантика ведущих указателей

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

Конечно, можно просто объявить через местную газету, что указатели должны использоваться таким и только таким образом. А можно защитить ваших пользователей от самих себя и подкрепить семантические правила языковыми средствами C++. Если вы мудро выберете второй вариант, придется учесть следующее:

1 . Указываемые объекты должны создаваться указателями в конструкторах.

2. Деструктор указателя должен удалять указываемый объект.

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

4. Оператор присваивания operator= должен удалять текущий указываемый объект, находящийся слева от него, и заменять его копией указываемого объекта справа.

Кроме того, было бы разумно сделать еще две вещи:

5. Ограничить доступ к конструкторам класса указываемого объекта.

6. Создавать указатели с помощью производящих функций (factory functions).

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

template <c1ass Type> class MP { private:

Type* t; public:



MP(); Создает указываемый объект

MP(const MP<Type>&); Копирует указываемый объект ~MP(); Удаляет указываемый объект

MP<Type>& operator=(const MP<Type>&); Удаляет левосторонний объект,

копирует правосторонний

Type* operator->() const;

Конструирование

Предположим, вы разрешили пользователям создавать собственные указываемые объекты и передавать их ведущим указателям во время конструирования.

template <c1ass Type>

class MP {

private:

Type* t; public:

MP() : t(NULL) {}

MP(Type* pointer) : t(pointer) {} ~MP() { delete t; } И т.д.

Foo* foo = new Foo;

MP<Foo> mpl(foo);

MP<Foo> mp2(foo); Облом!

Насколько проще была бы жизнь без таких пользователей! Когда mpl удаляется, пропадает и foo. В итоге mp2 начинает указывать неизвестно куда. Зачем кому-нибудь потребуется вытворять такое? - спросите вы. Как говорилось в одном рекламном ролике: Зачем спрашивать Зачем ? Если вы оставите такую дыру, можете не сомневаться: кто-нибудь когда-нибудь изобретет дьявольский план, использует ее и обвинит во всех смертных грехах вашу программу.

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

class Foo {

friend class MP<Foo>;

protected:

Foo(); Теперь доступ к конструктору имеет только MP<Foo> public:

Оставшаяся часть интерфейса

template <c1ass Type>

class MP {

private:

Type* t; public:

MP() : t(new Type) {}

И т.д.

Ага, уже лучше. При создании указателя его конструктор также конструирует и указываемый объект. Объявляя указатель другом, мы можем сделать конструкторы Foo закрытыми или защищенными и



1 ... 21 22 23 [ 24 ] 25 26 27 ... 82

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика