Наследование и шаблоны классов

Последнее обновление: 20.03.2023

При наследовании класса на основе шаблона нам надо указать значения для параметров шаблона базового класса. И в данном случае мы можем также и производный класс определить как шаблон, и использовать его параметры при установке базового класса:

#include <iostream> 
  
template <typename T>
class Person {
public:
    Person(T id, std::string name) : id{id}, name{name} { }
    void print() const 
    {
        std::cout << "Id: " << id << "\tName: " << name << std::endl;
    }
protected:
    T id;
    std::string name;
};

template <typename T>
class Employee: public Person<T> {
public:
    Employee(T id, std::string name, std::string company) : Person<T>{id, name}, company{company} { }
    void print() const 
    {
        Person<T>::print();
        std::cout << Person<T>::name << " works in " << company << std::endl;
    }
private:
    std::string company;
};

int main()
{
    Employee<unsigned> bob{123, "Bob", "Google"};
    bob.print();    // Id: 123 Name: Bob
                    // Bob works in Google
}

В данном случае в начале определен шаблон базового класса Person, который использует параметр шаблона T для установки типа для переменной id. Далее определен шаблон класс Employee, который наследуется от класса Person:

template <typename T>
class Employee: public Person<T>

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

При этом чтобы обратиться к функциональности базового класса, необходимо использовать выражение Person<T> (то есть указывать значение для параметра шаблона Person):

Person<T>{id, name}   // вызов конструктора
Person<T>::print();   // вызов функции print
Person<T>::name       // обращение к переменной name базового класса Person

Далее в программе мы можем типизировать объекты Employee определенным типом, и этот тип будет применяться для фукциональности базового класса:

Employee<unsigned> bob{123, "Bob", "Google"};

Другой вариант наследования состоит в том, что на этапе наследования мы явным образом устанавливаем для базового класса используемые типы:

#include <iostream> 
  
template <typename T>
class Person {
public:
    Person(T id, std::string name) : id{id}, name{name} { }
    void print() const 
    {
        std::cout << "Id: " << id << "\tName: " << name << std::endl;
    }
protected:
    T id;
    std::string name;
};

class Employee: public Person<unsigned> {
public:
    Employee(unsigned id, std::string name, std::string company) : Person{id, name}, company{company} { }
    void print() const 
    {
        Person::print();
        std::cout << name << " works in " << company << std::endl;
    }
private:
    std::string company;
};

int main()
{
    Employee bob{123, "Bob", "Google"};
    bob.print();    // Id: 123 Name: Bob
                    // Bob works in Google
}

В данном случае класс Employee представляет обычный класс, который наследуется от типа Person<unsigned>. То есть теперь для функционала базового класса параметр T будет представлять тип unsigned.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850