Листинг 19.6. Специальные реализации шаблона
1: #include <iostream.h>
2:
3: const int DefaultSize = 3;
4:
5: // Обычный класс, из объектов которого создается массив
6: class Animal
7: {
8: public:
9: // конструкторы
10: Animal(int);
11: Animal();
12: ~Animal();
13:
14: // методы доступа
15: int GetWeight() const { return itsWeight; }
16: void SetWeight(int theWeight) { itsWeight = theWeight; }
17:
18: // дружественные операторы
19: friend ostream& operator<< (ostream&, const Animal&);
20:
21: private:
22: int itsWeight;
23: };
24:
25: // оператор вывода обьектов типа Animal
26: ostream& operator<<
27: (ostream& theStream, const Animal& theAnimal)
28: {
29: theStream << theAnimal.GetWeight();
30: return theStream;
31: }
32:
33: Animal::Animal(int weight):
34: itsWeight(weight)
35: {
36: cout << "animal(int) ";
37: }
38:
39: Animal::Animal():
40: itsWeight(0)
41: {
42: cout << "animal() ";
43: }
44:
45: Animal::~Animal()
46: {
47: cout << "Destroyed an animal...";
48: }
49:
50: template <class T> // обьявляем шаблон и параметр
51: class Array // параметризованный класс
52: {
53: public:
54: Array(int itsSize = DefaultSize);
55: Array(const Array &rhs);
56: ~Array() { delete [] pType; }
57:
58: // операторы
59: Array& operator=(const Array&);
60: T& operator[](int offSet) { return pType[offSet]; }
61: const T& operator[](int offSet) const
62: { return pType[offSet]; }
62:
63: // методы доступа
64: int GetSize() const { return itsSize; }
65:
66: // функция-друг
67: friend ostream& operator<< (ostream&, const Array<T>&);
68:
69: private:
70: T *pType;
71: int itsSize;
72: };
73:
74: template <class T>
75: Array<T>::Array(int size = DefaultSize):
76: itsSize(size)
77: {
78: pType = new T[size];
79: for (int i = 0; i<size; i++)
80: pType[i] = (T)0;
81: }
82:
83: template <class T>
84: Array<T>& Array<T>::operator=(const Array &rhs)
85: {
86: if (this == &rhs)
87: return *this;
88: delete [] pType;
89: itsSize = rhs.GetSize();
90: pType = new T[itsSize];
|
|
91: for (int i = 0; i<itsSize; i++)
92: pType[i] = rhs[i];
93: return *this;
94: }
95: template <class T>
96: Array<T>::Array(const Array &rhs)
97: {
98: itsSize = rhs.GetSize();
99: pType = new T[itsSize];
100: for (int i = 0; i<itsSize; i++)
101: pType[i] = rhs[i];
102: }
103:
104:
105: template <olass T>
106: ostream& operator<< (ostream& output, const Array<T>& theArray)
107: {
108: for (int i = 0; i<theArray.GetSize(); i++)
109; output << "[" << i << "] " << theArray[i] << endl;
110: return output;
111: }
112:
113:
114: Array<Animal>::Array(int AnimalArraySize):
115: itsSize(AnimalArraySize)
116: {
117: pType = new Animal[AnimalArraySize];
118: }
119:
120:
121: void IntFillFunction(Array<int>& theArray);
122: void AnimalFillFunction(Array<Animal>& theArray);
123:
124: int main()
125: {
126: Array<int> intArray;
127: Array<Animal> animalArray;
128: IntFillFunction(intArray);
129: AnimalFillFunction(animalArray);
130: cout << "intArray...\n" << intArray;
131: cout << "\nanimaiArray...\n" << animalArray << endl;
132: return 0;
133: }
134:
135: void IntFillFunction(Array<int>& theArray)
136: {
137: bool Stop = false;
138: int offset, value;
139: while (!Stop)
140: {
141: cout << "Enter an offset (0-9) and a value, ";
142: cout << "(-1 to stop): ";
143: cin >> offset >> value;
144: if (offset < 0)
145: break;
146: if (offset > 9)
147: {
148: cout << "***Please use values between 0 and 9.***\n";
149: continue;
150: }
151: theArray[offset] = value;
152: }
153: }
154:
155:
156: void AnimalFillFunction(Array<Animal>& theArr,
157: {
158: Animal * pAnimal;
159: for (int i = 0; i<theArray.GetSize(); i++)
160: {
161: pAnimal = new Animal(i*10);
162: theArray[i] = *pAnimal;
163: delete pAnimal;
164: }
165: }
Примечание: Для облегчения анализа в приведенные ниже результаты работы программы добавлены номера строк, но в действительности они не выводятся.
|
|
Результат:
1: animal() animal() animal() Enter an offset (0-9) and a value. (-1 to stop): 0 0
2: Enter an offset (0-9) and a value. (-1 to stop): 1 1
3: Enter an offset (0-9) and a value. (-1 to stop): 2 2
4: Enter an offset (0-9) and a value. (-1 to stop): 3 3
5: Enter an offset (0-9) and a value. (-1 to stop): -1 -1
6: animal(int) Destroyed an animal...animal(int) Destroyed an animal...animal(int) Destroyed an animal...initArray...
7: [0] 0
8: [1] 1
9: [2] 2
10:
11: animal array
12: [0] 0
13: [1] 10
14: [2] 20
15:
16: Destroyed an animal...Destroyed an animal...Destroyed an animal
17: <<< Second run >>>
18: animal(int) Destroyed an animal..
19: animal(int) Destroyed an animal..
20: animal(int) Destroyed an animal..
21: Enter an offset (0-9) and a value. (-1 to stop): 0 0
22: Enter an offset (0-9) and a value. (-1 to stop): 1 1
23: Enter an offset (0-9) and a value. (-1 to stop): 2 2
24: Enter an offset (0-9) and a value. (-1 to stop): 3 3
25: animal(int)
26: Destroyed an animal...
27: animal(int)
28: Destroyed an animal...
29: animal(int)
30: Destroyed an animal...
31: initArray. . .
32: [0] 0
33: [1] 1
34: [2] 2
35:
36: animal array
37: [0] 0
38: [1] 10
39: [2] 20
40:
41: Destroyed an animal...
42: Destroyed an animal...
43: Destroyed an animal...
Анализ: В листинге 19.6 оба класса воспроизведены во всей своей полноте, чтобы лучше наблюдать за созданием и удалением временных объектов Animal. Для упрощения результатов работы значение DefaultSize было уменьшено до 3.
Все конструкторы и деструкторы класса Animal (строки 33—48) выводят на экран сообщения, сигнализирующие об их вызове.
|
|
В строках 74-81 объявляется конструктор класса Array. В строках 114-118 показан специализированный конструктор Array для массива объектов типа Animal. Обратите внимание, что в этом специализированном конструкторе не делается никаких явных присвоений и исходные значения для каждого объекта Animal устанавливаются стандартным конструктором.
При первом выполнении этой программы на экран выводится ряд сообщений. В строке 1 результатов выполнения программы зафиксированы сообщения трех стандартных конструкторов, вызванных при создании массива. Затем пользователь вводит четыре числа, которые помещаются в массив целых чисел.
После этого управление передается функции AnimalFillFunction(). Здесь в области динамического обмена создается временный объект Animal (строка 161), а его значение используется для модификации объекта Animal в массиве (строка 162). В следующей же строке (с номером 163) временный объект Animal удаляется. Этот процесс повторяется для каждого члена массива и отражен в строке 6 результатов выполнения программы.
В конце программы созданные массивы удаляются, а при вызове их деструкторов также удаляются и все их объекты. Процесс удаления отражен в строке 16 результатов выполнения программы.
|
|
При следующем выполнении программы (результаты показаны в строках 18-43) были закомментированы несколько строк программного кода (со 114 по 118), содержащие специализированный конструктор класса Array. В результате при выполнении программы для создания массива объектов Animal вызывается конструктор шаблона, показанныйвстроках74-81.
Это приводит к созданию временных объектов Animal для каждого члена массива (строки программы 79 и 80), что отражается в строках 18-20 результатов выполнения программы.
Во всех остальных аспектах, результаты выполнения двух вариантов программы, как и следовало ожидать, идентичны.
Статические члены и шаблоны
В шаблоне можно объявлять статические переменные-члены. В результате каждый экземпляр шаблона будет иметь собственный набор статических данных. Например, если добавить статическую переменную-член в шаблон Array (например, для подсчета количества созданных массивов), то в рассмотренной выше программе будут созданы две статические переменные-члена: одна для подсчета массивов объектов типа Animal и другая для массивов целых чисел. Добавление статической переменной-члена и статической функции в шаблон Array показано в листинге 19.7.
Дата добавления: 2019-02-12; просмотров: 212; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!