Такой подход крайне неэффективен, поскольку объект Animal уже инициализирован должным образом. Однако эту строку нельзя удалить, потому что при создании массива целочисленные значения не будут автоматически инициализироваться нулевыми значениями. Выход состоит в том, чтобы объявить в шаблоне дополнительный специализированный конструктор для создания массива объектов Animal.
Эта идея реализована в листинге 19.6 путем явного выполнения класса Animal.
Листинг 19.6. Специальные реализации шаблона
1: #include
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 // обьявляем шаблон и параметр
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&);
68:
69: private:
70: T *pType;
71: int itsSize;
72: };
73:
74: template
75: Array::Array(int size = DefaultSize):
76: itsSize(size)
77: {
78: pType = new T[size];
79: for (int i = 0; i
80: pType[i] = (T)0;
81: }
82:
83: template
84: Array& Array::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
92: pType[i] = rhs[i];
93: return *this;
94: }
95: template
96: Array::Array(const Array &rhs)
97: {
98: itsSize = rhs.GetSize();
99: pType = new T[itsSize];
100: for (int i = 0; i
101: pType[i] = rhs[i];
102: }
103:
104:
105: template
106: ostream& operator<< (ostream& output, const Array& theArray)
107: {
108: for (int i = 0; i
109; output << "[" << i << "] " << theArray[i] << endl;
110: return output;
111: }
112:
113:
114: Array::Array(int AnimalArraySize):
115: itsSize(AnimalArraySize)
116: {
117: pType = new Animal[AnimalArraySize];
118: }
119:
120:
121: void IntFillFunction(Array& theArray);
122: void AnimalFillFunction(Array& theArray);
123:
124: int main()
125: {
126: Array intArray;
127: Array 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& 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& theArr,
157: {
158: Animal * pAnimal;
159: for (int i = 0; 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.
Читать дальше