Липпман - C++ для начинающих стр 13.

Шрифт
Фон

ia[ix]

"\tca: " ca[ix]

"\tda: " da[ix] endl;

return 0;

}

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

Arrayint ia(array_size);

Arraydouble da(array_size);

Arraychar ca(array_size);

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

// Arrayint ia(array_size);

int _size;

int *_ia;

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

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

// Arraydouble da(array_size);

int _size;

double *_ia;

// Arraychar ca(array_size);

int _size;

char *_ia;

Что происходит с функциями-членами? В них тоже тип-параметр elemType заменяется на реальный тип, однако компилятор не конкретизирует те функции, которые не вызываются в каком-либо месте программы. (Подробнее об этом в разделе 16.8.)

При выполнении программа этого примера выдаст следующий результат:

[ 0 ] ia: 0 ca: a da: 0

[ 1 ] ia: 1 ca: b da: 1.75

[ 2 ] ia: 2 ca: c da: 3.5

[ 3 ] ia: 3 ca: d da: 5.25

Механизм шаблонов можно использовать и в наследуемых классах. Вот как выглядит определение шаблона класса ArrayRC:

#include cassert

#include "Array.h"

template class elemType

class ArrayRC : public ArrayelemType {

public:

ArrayRC( int sz = DefaultArraySize )

: ArrayelemType( sz ) {}

ArrayRC( const ArrayRC r )

: ArrayelemType( r ) {}

ArrayRC( const elemType *ar, int sz )

: ArrayelemType( ar, sz ) {}

elemType ArrayRCelemType::operator[]( int ix )

{

assert( ix = 0 ix ArrayelemType::_size );

return _ia[ ix ];

}

private:

// ...

};

Подстановка реальных параметров вместо типа-параметра elemType происходит как в базовом, так и в производном классах. Определение

ArrayRCint ia_rc(10);

ведет себя точно так же, как определение IntArrayRC из предыдущего раздела. Изменим пример использования из предыдущего раздела. Прежде всего, чтобы оператор

// функцию swap() тоже следует сделать шаблоном

swap( ia1, 1, ia1.size() );

был допустимым, нам потребуется представить функцию swap() в виде шаблона.

#include "Array.h"

template class elemType

inline void

swap( ArrayelemType array, int i, int j )

{

elemType tmp = array[ i ];

array[ i ] = array[ j ];

array[ j ] = tmp;

}

При каждом вызове swap() генерируется подходящая конкретизация, которая зависит от типа массива. Вот как выглядит программа, использующая шаблоны Array и ArrayRC:

#include iostream

#include "Array.h"

#include "ArrayRC.h"

template class elemType

inline void

swap( ArrayelemType array, int i, int j )

{

elemType tmp = array[ i ];

array[ i ] = array[ j ];

array[ j ] = tmp;

}

int main()

{

Arrayint ia1;

ArrayRCint ia2;

cout "swap() with Arrayint ia1" endl;

int size = ia1.size();

swap( ia1, 1, size );

cout "swap() with ArrayRCint ia2" endl;

size = ia2.size();

swap( ia2, 1, size );

return 0;

}

Упражнение 2.13

Пусть мы имеем следующие объявления типов:

templateclass elemType class Array;

enum Status { ... };

typedef string *Pstring;

Есть ли ошибки в приведенных ниже описаниях объектов?

(a) Array int* pri(1024);

(b) Array Arrayint aai(1024);

(c) Array complex double acd(1024);

(d) Array Status as(1024);

(e) Array Pstring aps(1024);

Упражнение 2.14

Перепишите следующее определение, сделав из него шаблон класса:

class example1 {

public:

example1 (double min, double max);

example1 (const double *array, int size);

double operator[] (int index);

bool operator== (const example1) const;

bool insert (const double*, int);

bool insert (double);

double min (double) const { return _min; };

double max (double) const { return _max; };

void min (double);

void max (double);

int count (double value) const;

private:

int size;

double *parray;

double _min;

double _max;

}

Упражнение 2.15

Имеется следующий шаблон класса:

template class elemType class Example2 {

public:

explicit Example2 (elemType val=0) : _val(val) {};

bool min(elemType value) { return _val value; }

void value(elemType new_val) { _val = new_val; }

void print (ostream os) { os _val; }

private:

elemType _val;

}

template class elemType

ostream operator(ostream os,const Example2elemType ex)

{ ex.print(os); return os; }

Какие действия вызывают следующие инструкции?

(a) Example2Arrayint* ex1;

(b) ex1.min (ex1);

(c) Example2int sa(1024),sb;

(d) sa = sb;

(e) Example2string exs("Walden");

(f) cout "exs: " exs endl;

Ваша оценка очень важна

0
Шрифт
Фон

Помогите Вашим друзьям узнать о библиотеке