Рейтинговые книги
Читем онлайн Освой самостоятельно С++ за 21 день. - Джесс Либерти

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 125 126 127 128 129 130 131 132 133 ... 170

В этом примере используется ключевое слово class, за которым следует идентификатор Т. Это ключевое слово означает, что параметром является тип. Идентификатор T используется в остальной части определения шаблона, указывая тем самым на параметризованный тип. В одном экземпляре этого класса вместо идентификатора T повсюду будет стоять тип int, а в другом — тип Cat.

Чтобы объявить экземпляры параметризованного класса Array для типов int и Cat, следует написать:

Array<int> anIntArray;

Array<Cat> aCatArray;

Объект anIntArray представляет собой массив целых чисел, а объект aCatArray — массив элементов типа Cat. Теперь вы можете использовать тип Array<int> в любом месте, где обычно указывается какой-либо тип — для возвращаемого функцией значения, для параметра функции и т.д. В листинге 19.1 содержится полное объявление уже рассмотренного нами шаблона Array.

Примечание:Программа в листинге 19.1 не завершена!

Листинг 19.1. Шаблон класса Array

1: //Листинг 19.1. Шаблон класса массивов

2: #include <iostream.h>

3: const int DefaultSize = 10;

4:

5: template <class T> // объявляем шаблон и параметр

6: class Array // параметризуемый класс

7: {

8:    public:

9:       // конструкторы

10:      Array(int itsSize = DefaultSize);

11:      Array(const Array &rhs);

12:      ~Array() { delete [] pType; }

13:

14:      // операторы

15:      Array& operator=(const Array&);

16:      T& operator[](int offSet) { return pType[offSet]; }

17:

18:      // методы доступа

19:      int getSize() { return itsSize; }

20:

21:   private:

22:      T *pType;

23:      int itsSize;

24: };

Результат:

Результатов нет. Эта программа не завершена.

Анализ: Определение шаблона начинается в строке 5 с ключевого слова template за которым следует параметр. В данном случае параметр идентифицируется как тип за счет использования ключевого слова class, а идентификатор T используется для представления параметризованного типа.

Со строки 6 и до конца определения шаблона (строка 24) вся остальная часть объявления аналогична любому другому объявлению класса. Единственное отличие заключается в том, что везде, где обычно должен стоять тип объекта, используется идентификатор T. Например, можно предположить, что operator[] должен возвращать ссылку на объект в массиве, а на самом деле он объявляется для возврата ссылки на идентификатор типа T.

Если объявлен экземпляр целочисленного массива, перегруженный оператор присваивания этого класса возвратит ссылку на тип integer. А при объявлении экземпляра массива Animal оператор присваивания возвратит ссылку на объект типа Animal.

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

Внутри объявления класса слово Array может использоваться без спецификаторов. В другом месте программы этот класс будет упоминаться как Array<T>. Например, если не поместить конструктор внутри объявления класса, то вы должны записать следующее:

template <class T>

Array<T>::Array(int size):

itsSize = size

{

   pType = new T[size];

   for (int i = 0; i<size; i++)

      pType[i] = 0;

}

Объявление, занимающее первую строку этого фрагмента кода, устанавливает в качестве параметра тип данных (class T). В таком случае в программе на шаблон можно ссылаться как Array<T>, а объявленную функцию-член вызывать строкой

Array(int size).

Остальная часть функции имеет такой же вид, какой мог быть у любой другой функции. Это обычный и предпочтительный метод создания класса и его функций путем простого объявления до включения в шаблон.

Выполнение шаблона

Для выполнения класса шаблона Array необходимо создать конструктор-копировщик, перегрузить оператор присваивания (operator=) и т.д. В листинге 19.2 показана простая консольная программа, предназначенная для выполнения этого шаблона.

Примечание:Некоторые более старые компиляторы не поддерживают использование шаблонов. Но шаблоны являются частью стандарта ANSI C++, поэтому компиляторы всех основных производителей поддерживают шаблоны в своих текущих версиях. Если у вас очень старый компилятор, вы не сможете компилировать и выполнять упражнения, приведенные в этой главе. Однако все же стоит прочитать ее до конца, а затем вернуться к этому материалу после модернизации своего компилятора.

Листинг 19.2. Использвание шаблона массива

1: #include <iostream.h>

2:

3: const int DefaultSize = 10;

4:

5: // обычный класс Animal для

6: // создания массива животных

7:

8: class Animal

9: {

10:   public:

11:      Animal(int);

12:      Animal();

13:      ~Animal() { }

14:      int GetWeight() const { return itsWeight; }

15:      void Display() const { cout << itsWeight; }

16:   private:

17:      int itsWeight;

18: };

19:

20: Animal::Animal(int weight):

21: itsWeight(weight)

22: { }

23:

24: Animal::Animal():

25: itsWeight(0)

26: { }

27:

28:

29: template <class T> // обьявляем шаблон и параметр

30: class Array // параметризованный класс

31: {

32:    public:

33:       // конструкторы

34:       Array(int itsSize - DefaultSize);

35:       Array(const Array &rhs);

36:       ~Array() { delete [] pType; }

37:

38:       // операторы

39:       Array& operator=(const Array&);

40:       T& operator[](int offSet) { return pType[offSet]; }

41:       const T& operator[](int offSet) const

42:          { return pType[offSet]; }

43:       // методы доступа

44:       int GetSize() const { return itsSize; }

45:

46:    private:

47:       T *рТуре;

48:       int itsSize;

49: };

50:

51: // выполнения...

52:

53: // выполняем конструктор

54: template <class T>

55: Array<T>::Array(int size):

56: itsSize(size)

57: {

58:    pType = new T[size];

59:    for (int i = 0; i<size; i++)

60:       pType[i] = 0;

61: }

62:

63: // конструктор-копировщик

64: template <class T>

65: Array<T>::Array(const Array &rhs)

66: {

67:    itsSize = rhs.GetSize();

68:    pType = new T[itsSize];

69:    for (int i = 0; i<itsSize; i++)

70:       pType[i] = rhs[i];

71: }

72:

73: // оператор присваивания

74: template <class T>

75: Array<T>& Array<T>::operator=(const Array &rhs)

76: {

77:    if (this == &rhs)

78:       return *this;

79:    delete [] pType;

80:    itsSize = rhs.GetSize();

81:    pType = new T[itsSize];

82:    for (int i = 0; i<itsSize: i++)

83:       pType[i] = rhs[i];

84:    return *this;

85: }

86:

87: // исполняемая программа

88: int main()

89: {

90:    Array<int> theArray; // массив целых

91:    Array<Animal> theZoo; // массив животных

92:    Animal *pAnimal;

93:

94:    // заполняем массивы

95:    for (int i = 0; i < theArray.GetSize(); i++)

96:    {

97:       theArray[i] = i*2;

98:       pAnimal = new Animal(i*3);

99:       theZoo[i] = *pAnimal;

100:      delete pAnimal;

101:   }

102:   // выводим на печать содержимое массивов

103:   for (int j = 0; j < theArray.GetSize(); j++)

104:   {

105:      cout << "theArray[" << j << "]:t";

106:      cout << theArray[j] << "tt";

107:      cout << "theZoo[" << j << "]:t";

108:      theZoo[j].Display();

109:      cout << endl;

110:   }

111:

112:   return 0;

113: }

Результат:

theArray[0] 0 theZoo[0] 0

theArray[1] 2 theZoo[1] 3

theArray[2] 4 theZoo[2] - 6

theArray[3] 6 theZoo[3] 9

theArray[4] 8 theZoo[4] 12

theArray[5] 10 theZoo[5] 15

theArray[6] 12 theZoo[6] 18

theArray[7] 14 theZoo[7] 21

theArray[8] 16 theZoo[8] 24

theArray[9] 18 theZoo[9] 27

Анализ: В строках 8-26 выполняется создание класса Animal, благодаря которому объекты определяемого пользователем типа можно будет добавлять в массив.

Содержимое строки 29 означает, что в следующих за ней строках объявляется шаблон, параметром для которого является тип, обозначенный идентификатором Т. Класс Array содержит два конструктора, причем первый конструктор принимает размер и по умолчанию устанавливает его равным значению целочисленной константы DefaultSize.

Затем объявляются операторы присваивания и индексирования, причем объявляются константная и не константная версии оператора индексирования. В качестве единственного метода доступа служит функция GetSize(), которая возвращает размер массива.

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

Раздел закрытых данных содержит переменные-члены размера массива и указатель на массив объектов, реально помещенных в память.

Функции шаблона

1 ... 125 126 127 128 129 130 131 132 133 ... 170
На этой странице вы можете бесплатно читать книгу Освой самостоятельно С++ за 21 день. - Джесс Либерти бесплатно.

Оставить комментарий