|
Программирование >> Инициализация объектов класса, структура
#ifndef ARRAY RC S H #define ARRAY RC S H #include Array S.C #include Array RC.C template <class Type> class Array RC S : public Array RC S : public Array RC<Type>, public Array Sort<Type> public: AArray RC S( int sz = AArray<Type>::ArraySize ) : Array<Type>( sz ) { clear bit(); } Array RC S( const Array RC S srca ) : Array<Type>( rca ) { sort( 0,Array<Type>:: size-1 ); clear bit(); } Array RC S( const Type* arr, int sz ) : Array<Type>( arr, sz ) { sort( 0,Array<Type>:: size-1 ); clear bit(); } Types operator[]( int index ) set bit(); return Array RC<Type>::operator[]( index ); Array RC S.h: #endif Этот класс наследует две реализации каждой интерфейсной функции Array: из Array Sort и из виртуального базового класса Array через Array RC (за исключением оператора взятия индекса, для которого из обоих базовых классов наследуется замещенный экземпляр). При невиртуальном наследовании вызов find() был бы помечен компилятором как неоднозначный, поскольку он не знает, какой из унаследованных экземпляров мы имели в виду. В нашем случае замещенным в Array Sort экземплярам отдается предпочтение по сравнению с экземплярами, унаследованными из виртуального базового класса через Array RC (см. раздел 18.5.4). Таким образом, при виртуальном наследовании неквалифицированный вызов find() разрешается в пользу экземпляра, унаследованного из класса Array Sort. Оператор взятия индекса переопределен в классах Array RC и Array Sort, и обе реализации имеют равный приоритет. Поэтому внутри Array RC S неквалифицированное обращение к оператору взятия индекса неоднозначно. Класс Array RC S должен предоставить собственную реализацию, иначе пользователи не смогут напрямую применять такой оператор к объектам этого класса. Но какова 18.6.3. Класс массива с множественным наследованием Определим отсортированный массив с контролем выхода за границы. Для этого можно применить множественное наследование от Array RC и Array Sort. Вот как выглядит наша реализация (напомним еще раз, что мы ограничились тремя конструкторами и оператором взятия индекса). Определение находится в заголовочном файле #include Array RC S.h #include try array.C #include <string> int main() static int ia[ 10 ] = { 12, 7, 14, 9, 128, 17, 6,3,27, 5 }; static string sa[ 7 ] = { Eeyore , Pooh , Tigger , Piglet , Owl , Gopher , Heffalump Array RC S<int> iA( ia,10 ); Array RC S<string> SA( sa,7 ); cout << ёНёбабёдабёу ёёаппа Array RC S<int> << endl; try array( iA ); cout << ёНёбабёдабёу ёёаппа Array RC S<string> << endl; try array( SA ); return 0; по очереди классы, конкретизированные из шаблона Array RC S типами int и string: Вот что печатает программа для класса, конкретизированного типом string (теперь ошибка выхода за границы массива перехватывается): конкретизация класса Array Sort<string> try array: начальные значения массива ( 7 )< Eeyore, Gopher, Heffalump, Owl, Piglet, Pooh Tigger > try array: после присваиваний ( 7 )< Eeyore, Gopher, Owl, Piglet, Pooh, Pooh Pooh > try array: почленная инициализация ( 7 )< Eeyore, Gopher, Owl, Piglet, Pooh, Pooh Pooh > try array: после почленного копирования ( 7 )< Eeyore, Piglet, Owl, Piglet, Pooh, Pooh Pooh > семантика его вызова в Array RC S? При учете отсортированности массива он должен установить в true унаследованный член dirty bit. А чтобы учесть наследование от класса с контролем выхода за границы массива - проверить указанный индекс. После этого можно возвращать элемент массива с данным индексом. Последние два шага выполняет унаследованный из Array RC оператор взятия индекса. При обращении return Array RC<Type>::operator[]( index ); он вызывается явно, и механизм виртуализации не применяется. Поскольку это встроенная функция, то при статическом вызове компилятор подставляет ее код в место вызова. Теперь протестируем нашу реализацию с помощью функции try array(), передавая ей try array: после вызова grow 7 )< <empty>, <empty>, <empty>, <empty>, Eeyore, Owl Piglet, Piglet, Pooh, Pooh, Pooh > искомое значение: Tigger возвращенный индекс: -1 Assertion failed: ix >= 0 && ix < size Представленная в этой главе реализация иерархии класса Array иллюстрирует применение множественного и виртуального наследования. Детально проектирование класса массива описано в [NACKMAN94]. Однако, как правило, достаточно класса vector из стандартной библиотеки. Упражнение 18.16 Добавьте в Array функцию-член spy() . Она запоминает операции, примененные к объекту класса: число доступов по индексу; количество вызовов каждого члена; какой элемент искали с помощью find() и сколько было успешных поисков. Поясните свои проектные решения. Модифицируйте все подтипы Array так, чтобы spy() можно было использовать и для них тоже. Упражнение 18.17 Стандартный библиотечный класс map (отображение) называют еще ассоциативным массивом, поскольку он поддерживает индексирование значением ключа. Как вы думаете, является ли ассоциативный массив кандидатом на роль подтипа нашего класса Array? Почему? Упражнение 18.18 Перепишите иерархию Array, пользуясь контейнерными классами из стандартной библиотеки и применяя обобщенные алгоритмы.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |