41. C++ Шаблоны классов / обобщенные классы ().

Шаблоны классов / обобщенные классы.

Аналогично шаблонных функций в C++ можно создавать шаблонные классы, т.е. классы, которые конструируются на этапе компиляции.

template<typename T>
class MyClass
{
public:
    MyClass(T value) {this->value=value;}
    void PrintValue() {cout<<value<<endl;}     
    T getValue(){return this->value;}

private:
    T value;
};

В функции main:

MyClass<int> c_Int(10);
MyClass<string> c_String("Hello");
c_Int.PrintValue();
c_String.PrintValue();

Используя шаблон класса MyClass мы создаем 2 объекта класса c_Int и c_String, работающие с функционалом шаблонного класса, но разными типами данных.

По сути на этапе компиляции вместо T в шаблоне класса подставляется значение, указанное в скобках <int> или <string> и тд.

Типы передаваемых данных (typename T) могут быть любыми, главное чтобы методы шаблонного класса поддерживали работу с ними, например мы можем передать в шаблон свой собственный класс, но в данном случае оператор вывода на консоль << в нем должен быть перегружен.

Как и в случае шаблонных функций мы можем использовать более 1 обобщенного типа переменной, для этого в шаблоне функции пишем:

template<typename T1, typename T2 >
class MyClass {//code};

В функции main вызываем например так:
MyClass<int, string> c_T2(…);

 

Примечание 1:
template<typename T> можно также записать как template<class T> разницы нет, но лично мне больше нравится typename.

Примечание 2:

#include <typeinfo> //иногда работает и без нее
typeid(value).name – функция выдает данные о типе typename T
cout<< typeid(value).name<<endl;

Примечание 3:
При вынесении методов/конструкторов/деструктора из класса необходимо указывать, что класс шаблонный

template<typename T>
MyClass<T>::Metod(){}

Наследование от шаблонного класса с «избавлением» от шаблонности:

class Student : public Person<int>
{
//code
};

Наследование от шаблонного класса с сохранением шаблонности:

template<typename T>
class Student : public Person<T>
{
//code
};

 

Специализация шаблона класса

Иногда возникает ситуация когда для отдельных типов данных нужна отдельная обработка в шаблоне класса, поэтому можно шаблон специализировать (по сути перегрузить)

Рассмотрим на примере:

template<typename T>
class MyClass
{
public:
   MyClass(T value) {this->value=value;}
   void PrintValue() {cout<<value<<endl;}

private:
   T value;
};

 

напишем специализацию для типа int:

template <>
class MyClass<int>
{
public:
    MyClass(int value) {this->value=value;}
    void PrintValue() {cout<<value+1<<endl;}
    void PrintValue_x2() {cout<<value*2<<endl;}

private:
    int value;

тогда в main:

MyClass<int> c_Int(10);
MyClass<string> c_String("Hello");
c_Int.PrintValue(); //выведет 11
c_Int.PrintValue_x2(); //выведет 20
c_String.PrintValue();

Теперь при создании шаблона класса с переменной типа int будет вызываться переопределенный шаблон, соответственно будут доступны все методы и поля переопределенного шаблона.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *