Программирование >>  Инициализация объектов класса, структура 

1 ... 15 16 17 [ 18 ] 19 20 21 ... 395


Упражнение 2.9

Определите, какие из следующих функций могут различаться в реализации для

(a) rotate();

(b) print();

(c) size();

(d) DateBorrowed(); дата в]дачи книги

(e) rewind();

(f) borrower(); читатель

(g) is late(); книга просрочена

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

(h) is on loan(); книга в]дана Упражнение 2.10

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

Упражнение 2.11

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

Упражнение 2.12

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

(a) Точка

(b) Служащий

(c) Фигура

(d) Телефонный номер

(e) Счет в банке

программы, использующей данный интерфейс.



template <class elemType>

class Array { public:

explicit Array( int sz = DefaultArraySize ); AArray( const elemType *ar, int sz ) ; AArray( const AArray );

virtual ~Array() { delete[] ia; }

AArray& operator=( const AArray & ); int size() const { return size; }

virtual elemType& operator[]( int ix ) { return ia[ix]; }

virtual void sort( int,int ); virtual int find( const elemType& ); virtual elemType min(); virtual elemType max(); protected:

void init( const elemType*, int ); void swap( int, int );

static const int DefaultAArraySize = 12; int size;

elemType * ia;

Вот как может выглядеть шаблон класса Array: };

Ключевое слово template говорит о том, что задается шаблон, параметры которого заключаются в угловые скобки (<>). В нашем случае имеется лишь один параметр elemType; ключевое слово class перед его именем сообщает, что этот параметр представляет собой тип.

При конкретизации класса-шаблона Array параметр elemType заменяется на реальный тип при каждом использовании, как показано в примере:

(f) Курс продажи

2.5. Использование шаблонов

Наш класс IntArray служит хорошей альтернативой встроенному массиву целых чисел. Но в жизни могут потребоваться массивы для сам1х разных типов данных. Можно предположить, что единственным отличием массива элементов типа double от нашего является тип данных в объявлениях, весь остальной код совпадает буквально.

Для решения данной проблема: в С++ введен механизм шаблонов. В объявлениях классов и функций допускается использование параметризованных типов. Типы-параметры заменяются в процессе компиляции настоящими типами, встроенными или определенными пользователем. Мы можем создать шаблон класса Array, заменив в классе IntArray тип элементов int на обобщенн1й тип-параметр. Позже м1 конкретизируем типы-параметры, подставляя вместо них реальные типы int, double и string. В результате появится способ использовать эти конкретизации так, как будто мы на самом деле определили три разных класса для этих трех типов данных.



#include <iostream> #include Array.h

int main() {

const int array size = 4;

elemType заменяется на int Array<int> ia(array size);

elemType заменяется на double Array<double> da(array size);

elemType заменяется на char A\rray<char> ca(array size);

int ix;

for ( ix = 0; ix < array size; ++ix ) { ia[ix] = ix;

da[ix] = ix * 1.75; ca[ix] = ix + a;

for ( ix = 0; ix < array size; ++ix )

cout << [ << ix << ] ia: << ia[ix] << \tca: << ca[ix] << \tda: << da[ix] << endl;

return 0;

Array<int> ia(array size);

Здесь определены три экземпляра класса Array:

Array<double> da(array size); Array<char> ca(array size);

Что делает компилятор, встретив такое объявление? Подставляет текст шаблона Array, заменяя параметр elemType на тот тип, который указан в каждом конкретном случае. Следовательно, объявления членов приобретают в первом случае такой вид:

Array<int> ia(array size); int size; int * ia;

Заметим, что это в точности соответствует определению массива IntArray.

Array<double> da(array size);

Для оставшихся двух случаев м1 получим следующий код:

int size; double * ia;



1 ... 15 16 17 [ 18 ] 19 20 21 ... 395

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