Шаблоны классов
Шаблон класса -- это обобщённый тип, зависящий от параметров шаблона.
template <class T>
class Stack{
//...
};
Шаблоны классов отличаются от шаблонов функций тем, что их нельзя инстанцировать неявно, т.к. нет "вызова" класса.
MyStack<int> s1;
MyStack<string> s2;
Отметим, что s1 и s2 -- это экземпляры разных типов, они никак не родственны друг другу в смысле ООП.
Не стоит путать экземпляр класса (объект) и специализацию класса (тип). Экземпляр для шаблонного класса создать невозможно, экземпляр можно сделать только для конкретной его специализации:
MyStack s1; -- так делать нельзя!
Методы шаблонных классов являются (должны являться) шаблонными функциями, и это особенно заметно когда их тела описываются вне тела члена класса.
#include <iostream>
using namespace std;
template <class T>
class Encapsulator;
template <class T>
ostream & operator<< (ostream &out, Encapsulator<T> right);
template <class T>
class Encapsulator {
T val;
public:
Encapsulator(T _val):val(_val) {}
Encapsulator<T> operator* (Encapsulator<T> right) const;
Encapsulator<T> operator+ (Encapsulator<T> right) const;
friend ostream & operator<< <T> (ostream &out, Encapsulator<T> right);
};
template <class T>
Encapsulator<T> Encapsulator<T>::operator* (Encapsulator<T> right) const
{
return Encapsulator<T>(val*right.val);
}
template <class T>
Encapsulator<T> Encapsulator<T>::operator+ (Encapsulator<T> right) const
{
return Encapsulator<T>(val + right.val);
}
template <class T>
ostream & operator<< (ostream &out, Encapsulator<T> right)
{
out << right.val;
return out;
}
int main()
{
Encapsulator<int> a(5);
Encapsulator<string> b("asdf");
cout << a << endl;
cout << b << endl;
cout << (a + a) << endl;
cout << (b + b) << endl;
cout << (a*a) << endl;
return 0;
}
Опыт показал, что бинарные операторы для шаблонных классов лучше описывать как методы, а не как дружественные функции.
Перегрузка оператора вывода в поток потребовала предварительного объявления дружественной функции.