С++ - язык, который изучается постепенно.Конструирование.
                   Справочники Всё для создания сайта

Ссылки


Home
Бизнес
Справочники
Советы







Материалы книги получены с http://www.itlibitum.ru/

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

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

template <class Type>

class MP {

private:

Type* t;

public:

MP() : t(NULL) {}

MP(Type* pointer) : t(pointer) {}

~MP() { delete t; }

// И т.д.

};

Foo* foo = new Foo;

MP<Foo> mp1(foo);

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

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

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

class Foo {

friend class MP<Foo>;

protected:

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

public:

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

};

template <class Type>

class MP {

private:

Type* t;

public:

MP() : t(new Type) {}

// И т.д.

};

Aгa, уже лучше. При создании указателя его конструктор также конструирует и указываемый объект. Объявляя указатель другом, мы можем сделать конструкторы Foo закрытыми или защищенными и сохранить доступ к ним из конструкторов указателя. Теперь клиент никак не сможет добраться до Foo, кроме как через MP<Foo>. Мы еще неоднократно вернемся к вопросу о том, как, когда и где создавать указываемые объекты, а пока давайте немного отвлечемся. Если конструкторы Foo вызываются с аргументами, существуют две альтернативы:

1. Вместо того чтобы пользоваться универсальным шаблоном ведущего указателя, создайте для

Foo нестандартный класс ведущего указателя MPFoo. Для каждого конструктора Foo создайте

конструктор MPFoo с точно такой же сигнатурой и передайте его аргументы конструктору Foo.

2. Воспользуйтесь безаргументным конструктором для создания объекта и предоставьте

отдельную функцию инициализации, которая может вызываться клиентом после

конструирования.

Второй вариант выглядит так:

class Foo {

friend class MP<Foo>;

protected:

Foo(); // Единственный конструктор

public:

Initialized(int, char*);

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

};

MP<Foo> mpf;

mpf->Initialize(17, "Hello"); // Завершить конструирование

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


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

Home  Создание сайтов  Учебник по записи CD  Справочник Web дизайнера Самоучитель IE PHP и MySQL Компьютерные сети С++ E-mail me

Copyright 2007. Климов Александр. All Right Reserved.
Hosted by uCoz