Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программирование на C / C++ / C++ for real programmers.pdf
Скачиваний:
231
Добавлен:
02.05.2014
Размер:
2.04 Mб
Скачать

204

Переработать старый шаблон MP из предыдущих глав (с операторной функцией operator Type*()), чтобы при выходе из пула и указателей за пределы области действия все необходимое автоматически уничтожалось.

Ниже показан примерный вид полученного интерфейса, с фрагментом клиентского кода и без виртуального оператора =.

//В файле foo.h

//Подключить объявление чисто абстрактного базового класса

#include “pool.h” class Foo { private:

Foo(const Foo&) {}

Foo& operator=(const Foo&) { return *this; } public:

static Pool* makePool(); // Создать пул, оптимизированный для Foo

static Foo* make();

// Не использует пул

static Foo* make(Pool*);

// Использует пул

// И т.д.

 

};

 

// Клиентский код

 

void g(Foo*);

 

void f()

 

{

 

MP<Pool> pool(Foo::makePool());

MP<Foo> foo(Foo::make(pool));

foo->MemberOfFoo();

// Использует операторную функцию operator->()

g(foo);

// Использует операторную функцию operator Type*()

// Выход из области

действия – удаляется сначала foo, затем pool

}

Перспективы

Глава заканчивается хорошо — умной, эффективной инкапсуляцией очень сложной проблемы дизайна. Единственным уязвимым местом является вызов функции g(), которая должна пообещать не сохранять долговременный указатель на свой аргумент. Впрочем, подобный анализ необходимо проводить для любой архитектуры, в которой используются временные пулы; в нашем случае ключом является инкапсуляция.

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