При наследовании класса на основе шаблона нам надо указать значения для параметров шаблона базового класса. И в данном случае мы можем также и производный класс определить как шаблон, и использовать его параметры при установке базового класса:
#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.