Программирование >>  Решение нетривиальных задач 

1 ... 69 70 71 [ 72 ] 73 74 75 ... 77


для того, чтобы получить 20-элементный массив из 10-элементных массивов.

157. Шаблоны классов должны обычно определять производные классы

158. Шаблоны не заменяют наследование; они его автоматизируют

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

Во-первых, давайте взглянем на то, что не нужно делать. Класс storable, уже использованный мной, снова представляется хорошим примером. Сначала создадим объект collection для управления сохраняемыми объектами:

class collection

storable *head; public:

...

storable *find( const storable &a match of this ) const;

storable *collection::find( const storable &a match of this ) const

Послать сообщение объекту начала списка, указывающее, что спи сок просматривается на совпадение со значением a match of this;

return head ? head->find( a match of this ) : NULL

Механизм поиска нужных объектов скрыт внутри класса storable. Вы можете изменить лежащую в основе структуру данных, поменяв определение storable, и эти изменения совсем не затронут реализацию класса collection.

Затем давайте реализуем класс storable, использующий простой связанный список в качестве лежащей в основе структуры данных:

class storable

storable *next, *prev;



В действительности я бы использовал множественное наследование с участием класса string. Использованный здесь код имеет цель немного упростить пример.

public:

storable *find ( const storable &match of this ) const;

storable *successor ( void ) const;

virtual int operator== ( const storable &r ) const;

storable *storable::find( const storable &match of this ) const

Возвращает указатель на первый элемент в списке (начиная с себя), имеющий тот же ключ, что и match of this. Обычно, объект-коллекция должен послать это сообщение объекту начала списка, указатель на который хранится в классе коллекции.

storable *current = this;

for( ; current; current = current->next )

if( *current == match of this ) найдено совпадение return current;

storable *storable::successor( void ) const

Возвращает следующее значение в последовательности. return next;

Функция operator==() должна быть чисто виртуальной, потому что отсутствует возможность ее реализации на уровне класса storable. Реализация должна быть выполнена в производном классе13 :

class storable string : public storable

string s; public:

virtual int operator==( const storable &r ) const;

...

virtual int operator==( const storable &r ) const

storable string *right = dynamic cast<storable string *>( &r

return right ? (s == r.s) : NULL;

Я здесь использовал предложенный в ISO/ANSI Си++ безопасный механизм нисходящего приведения типов. right инициализируется значением null, если передаваемый объект (r) не относится к типу



См. пред1дущее примечание к правилу 156. - Ред.

storable string. Например, он может принадлежать к некоторому другому классу, также являющемуся наследником storable.

Пока все идет хорошо. Теперь к проблемам, связанным с шаблонами. Кто-нибудь, не понимающий того, что делает, говорит: Ребята, я могу исключить наследование и потребность в виртуальных функциях, используя шаблоны , а делает, вероятно, нечто подобное:

template <class t key>

class storable

storable *next, *prev; t key key; public:

...

storable *find ( const storable &match me ) const;

storable *successor ( void ) const;

int operator==( const storable &r ) const;

template <class t key>

int storable<t key>::operator==( const storable<t key> &r ) const

return key == r.key ;

template <class t key>

storable<t key> *storable<t key>::successor( void ) const

return next;

template <class t key>

storable *storable<t key>::find( const storable<t key>

&match me ) const

storable<t key> *current = this;

for( ; current; current = current->next )

if( *current == match me ) найдено совпадение

return current;

Проблема здесь в непроизводительных затратах. Функции-члены шаблона класса сами являются шаблонами функций. Когда компилятор расширяет шаблон storable, он также расширяет варианты всех функций-членов этого шаблона*. Хотя я их не показал, вероятно, в классе storable



1 ... 69 70 71 [ 72 ] 73 74 75 ... 77

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