Освой самостоятельно С++ за 21 день.
Шрифт:
Функции шаблона
Если вы хотите передать функции объект массива, нужно передавать конкретный экземпляр массива, а не шаблон. Поэтому, если некоторая функция SomeFunction принимает в качестве параметра целочисленный массив, используйте следующую запись:
void SomeFunction(Array<int>&); // правильно
А запись
void SomeFunction(Array<T>&); // ошибка!
неверна, поскольку отсюда не ясно, что представляет собой выражение T&. Запись
void SomeFunction(Array &); //
тоже ошибочна, так как объекта класса Array не существует — есть только шаблон и его экземпляры.
Чтобы реализовать более общий подход использования объектов, созданных на основе шаблона, нужно объявить функцию шаблона:
template <class T>
void MyTemplateFunction(Array<T>&); // верно
Здесь MyTemplateFunction объявлена как функция шаблона, на что указывает первая строка объявления. Заметьте, что функции шаблонов, подобно другим функциям, могут иметь любые имена.
Функции шаблонов, помимо объектов, заданных в параметризованной форме, могут также принимать и экземпляры шаблона. Проиллюстрируем это на примере:
template <class T>
void MyOtherFunction(Array<T>&, Array<int>&); // верно
Обратите внимание на то, что эта функция принимает два массива: параметризованный массив и массив целых чисел. Первый может быть массивом любых объектов, а второй — только массивом целых чисел.
Шаблоны и друзья
В шаблонах классов могут быть объявлены три типа друзей:
• дружественный класс или функция, не являющиеся шаблоном;
• дружественный шаблон класса или функция, входящая в шаблон;
• дружественный шаблон класса или шаблонная функция, специализированные по типу данных.
Дружественные классы и функции, не являющиеся шаблонами
Можно объявить любой класс или функцию, которые будут дружественны по отношению к вашему классу шаблона. В этом случае каждый экземпляр класса: будет обращаться с другом так, как будто объявление класса-друга было сделано в этом конкретном экземпляре. В листинге 19.3 в определении шаблона класса Array добавлена тривиальная дружественная функция Intrude, а в управляющей.программе делается вызов этой функции. В качестве друга функция Intrude получает доступ к закрытым данным класса Array. Но поскольку эта функция не является функцией шаблона, то ее можно вызывать только для массива заданного типа (в нашем примере для массива целых чисел).
Листинг 18.3. Функция-друг, не являющаяся шаблоном
1: // Листинг 19.3. Использование в шаблонах функций-друзей определенного типа
2:
3: #include <iostream.h>
4:
5: const int DefaultSize = 10;
6:
7: // обьявляем простой класс Animal, чтобы можно
8: // было создать массив животных
9:
10: class Animal
11: {
12: public:
13: Animal(int);
14: Animal;
15: ~Animal { }
16: int GetWeight const { return itsWeight; }
17: void Display const { cout << itsWeight; >
18: private:
19: int itsWeight;
20: };
21:
22: Animal::Animal(intweight):
23: itsWeight(weight)
24: { }
25:
26: Animal::Animal:
27: itsWeight(0)
28: { }
29:
30: template <class T> //
обьявляем шаблон и параметр31: class Array // параметризованный класс
32: {
33: public:
34: // конструкторы
35: Array(int itsSize = DefaultSize);
36: Array(const Array &rhs);
37: ~Array { delete [] pType; }
38:
39: // операторы
40: Array& operator=(const Array&);
41; T& operator[](int offSet) { return pType[offSet]; }
42: const T& operator[](int offSet) const
43: { return pType[offSet]; }
44: // методы доступа
45: int GetSize const { return itsSize; }
46:
47: // функция-друг
48: friend void Intrude(Array<int>);
49
50: private:
51: T *рТуре;
52: int itsSize;
53: };
54:
55: // Поскольку функция-друг не является шаблоном, ее можно использовать только
56: // с массивами целых чисел! Но она получает доступ к закрытым данным класса.
57: void Intrude(Array<int> theArray)
58: {
59: cout << "\n*** Intrude ***\n";
60: for (int i = 0; i < theArray.itsSize; i++)
61: cout << "i: " << theArray.pType[i] << endl;
62: cout << "\n"
63: }
64:
65: // Ряд выполнений...
66:
67: // выполнение конструктора
68: template <class T>
69: Array<T>::Array(int size):
70: itsSize(size)
71: {
72: pType = new T[size];
73: for (int i = 0; i<size; i++)
74: pType[i] = 0;
75: }
76:
77: // конструктор-копировщик
78: template <class T>
79: Array<T>::Array(const Array &rhs)
80: {
81: itsSize = rhs.GetSize;
82: pType = new T[itsSize];
83: for (int i = 0; i<itsSize; i++)
84: pType[i] = rhs[i];
85: }
86:
87: // перегрузка оператора присваивания (=)
88: template <class T>
89: Array<T>& Array<T>::operator=(const Array &rhs)
90: {
91: if (this == &rhs)
92: return *this;
93: delete [] pType;
94: itsSize = rhs.GetSize;
95: pType = new T[itsSize];
96: for (int i = 0; i<itsSize; i++)
97: pType[i] = rhs[i];
98: return *this;
99: }
100:
101: // управляющая программа
102: int main
103: {
104: Array<int> theArray; // массив целых
105: Array<Animal> theZoo; // массив животных