Ответ
Нет, виртуальный метод не может быть шаблонным. Это прямое ограничение языка C++. Шаблонная функция (метод) инстанцируется (создается конкретная версия) во время компиляции для каждого используемого типа. Виртуальный же метод разрешается во время выполнения через механизм виртуальной таблицы (vtable). Компилятор не может заранее знать, для каких типов будет вызван шаблонный виртуальный метод, и поэтому не может построить корректную vtable.
Попытка скомпилировать такой код вызовет ошибку:
class Base {
public:
template <typename T>
virtual void process(T value) { // Ошибка: `virtual` cannot be specified on member function templates
// ...
}
};
Обходной путь (шаблонный метод + перегрузка виртуальных функций): Часто используется идиома, где публичный невиртуальный шаблонный метод делегирует вызов приватной виртуальной функции. Это позволяет сохранить полиморфный интерфейс с разными типами.
#include <iostream>
#include <string>
class Serializer {
public:
// Публичный шаблонный интерфейс
template <typename T>
void serialize(const T& value) {
serialize_impl(value); // Статическая диспетчеризация (во время компиляции)
}
private:
// Приватные виртуальные реализации для конкретных типов
virtual void serialize_impl(int value) {
std::cout << "Serializing int: " << value << 'n';
}
virtual void serialize_impl(const std::string& value) {
std::cout << "Serializing string: " << value << 'n';
}
// Можно добавить общую реализацию по умолчанию
virtual void serialize_impl(...) {
std::cout << "Serializing unknown typen";
}
};
class JsonSerializer : public Serializer {
private:
void serialize_impl(int value) override {
std::cout << "{"value": " << value << "}" << 'n';
}
void serialize_impl(const std::string& value) override {
std::cout << "{"value": "" << value << ""}" << 'n';
}
};
int main() {
JsonSerializer serializer;
Serializer* ptr = &serializer;
ptr->serialize(42); // Вызовет JsonSerializer::serialize_impl(int)
ptr->serialize(std::string("Hello")); // Вызовет JsonSerializer::serialize_impl(string)
return 0;
}
Этот подход комбинирует полиморфизм времени выполнения для выбора реализации (JsonSerializer vs Base Serializer) и статический полиморфизм (шаблоны) для выбора перегруженной функции по типу аргумента.