Может ли шаблонный метод быть виртуальным?

«Может ли шаблонный метод быть виртуальным?» — вопрос из категории Шаблоны, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, но с важными ограничениями.

В C++ виртуальный метод не может быть шаблоном функции (function template). Однако метод шаблонного класса может быть виртуальным. Разница ключевая:

  • НЕЛЬЗЯ: Объявить виртуальный метод, который сам является шаблоном с параметром typename T.
  • МОЖНО: Объявить виртуальный метод внутри шаблонного класса. При этом виртуальность работает для конкретной инстанциации (специализации) этого класса.

Пример корректного использования (виртуальный метод в шаблонном классе):

template <typename T>
class Processor {
public:
    // Виртуальный метод шаблонного класса.
    // Для каждой специализации Processor<int>, Processor<double> и т.д.
    // создается своя виртуальная таблица.
    virtual void process(const T& value) {
        std::cout << "Base processing: " << value << 'n';
    }
    virtual ~Processor() = default;
};

class IntProcessor : public Processor<int> {
public:
    // Переопределение виртуального метода для специализации Processor<int>
    void process(const int& value) override {
        std::cout << "IntProcessor: " << value * 2 << 'n';
    }
};

int main() {
    Processor<int>* p = new IntProcessor();
    p->process(5); // Вывод: IntProcessor: 10
    delete p;
}

Пример, который вызовет ошибку компиляции:

class InvalidBase {
public:
    // ОШИБКА: виртуальный метод не может быть шаблоном функции.
    template <typename T>
    virtual void templateMethod(T arg) {}
};

Почему такое ограничение? Механизм виртуальных вызовов (vtable) требует, чтобы сигнатура метода (включая тип возвращаемого значения) была известна на этапе компиляции для построения таблицы. Шаблон функции инстанцируется в разные типы методов в процессе компиляции, что делает невозможным создание единой таблицы для всех возможных инстанциаций.