unary_function {// в совете 40

private:

Widget w;// Класс содержит большой объем

int х;// данных, поэтому передача

// по значению

// была бы неэффективной

public:

virtual void operator() (const T& val) const; // Виртуальная функция.

// создает проблему

};// отсечения

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

template //Новый класс реализации

class BPFCImpl{ //для измененного BPFC.

private:

Widget w; //Все данные, ранее находившиеся

int х: //в BPFC, теперь размещаются

//в этом классе,

vrtual ~BPFCImpl(); //В полиморфных классах нужен

//виртуальный деструктор,

virtual void operator() (const T& val) const;

friend class BPFC;// Разрешить BPFC доступ к данным

};

template

class BPFC:// Компактная, мономорфная версия

public unary_function {

private:

BPFCImpl* pImpl;// Все данные BPFC

public:

void operator()(const T& val) const; // Функция не является

{// виртуальной; вызов передается

plImpl->operator()(val);// BPFCImpl

}

};

Реализация BFPC:: operator() дает пример того, как должны строиться реализации всех виртуальных функций BPFC: они должны вызывать свои виртуальные «прототипы» из BPFCImpl. Полученный в результате класс функтора (BPFC) компактен и мономорфен, но при этом он предоставляет доступ к большому объему данных состояния и работает полиморфно.

Материал изложен довольно кратко, поскольку описанные базовые приемы хорошо известны в кругах С++. В книге «Effective С++» этой теме посвящен совет 34. В книге «Приемы объектно-ориентированного проектирования» [6] соответствующая методика называется «паттерн Bridge». Саттер в своей книге «Exceptional С++» [8] использует термин «идиома Pimpl».

С позиций STL прежде всего необходимо помнить о том, что классы функторов, использующие данную методику, должны поддерживать соответствующий механизм копирования. Если бы вы были автором приведенного выше класса BPFC, то вам пришлось бы позаботиться о том, чтобы копирующий конструктор выполнял осмысленные действия с объектом BPFCImpl, на который он ссылается. Возможно, простейшее решение заключается в организации подсчета ссылок при помощи указателя shared_ptr из библиотеки Boost или его аналога (см. совет 50).

В сущности, копирующий конструктор BPFC — единственное, о чем вам придется побеспокоиться в контексте данного примера, поскольку при передаче и получении функторов от функций STL всегда происходит копирование (помните, что говорилось выше о передаче по значению?). Из этого вытекают два требования: компактность и мономорфизм.

<p>Совет 39. Реализуйте предикаты в виде «чистых» функций</p>

Для начала разберемся с основными терминами.

Предикатом называется функция, возвращающая тип bool (или другое значение, которое может быть автоматически преобразовано к bool). Предикаты широко используются в STL. В частности, функции сравнения в стандартных ассоциативных контейнерах представляют собой предикаты. Предикатные функции часто передаются в виде параметров таким алгоритмам, как find_if, и различным алгоритмам сортировки (обзор алгоритмов сортировки приведен в совете 31).

«Чистой» функцией называется функция, возвращаемое значение которой зависит только от параметров. Если f — «чистая» функция, а х и у — объекты, то возвращаемое значение f (х,у) может измениться только в случае изменения х или у.

В С++ все данные, используемые «чистыми» функциями, либо передаются в виде параметров, либо остаются постоянными на протяжении всего жизненного цикла функции (естественно, такие постоянные данные объявляются с ключевым словом const). Если бы данные, используемые «чистой» функцией, могли изменяться между вызовами, то вызов этой функции в разные моменты времени с одинаковыми параметрами мог бы давать разные результаты, что противоречит определению «чистой» функции.

Из сказанного должно быть понятно, что нужно сделать, чтобы предикаты были «чистыми» функциями. Мне остается лишь убедить читателя в том, что эта рекомендация обоснована. Для этого придется ввести еще один термин.

Перейти на страницу:

Все книги серии Библиотека программиста

Похожие книги