Виртуальные функции-члены создаются при создании экземпляра шаблона класса, но не виртуальные функции-члены создаются только при их вызове.
Это описано в [temp.inst] в стандарте C ++ (в C ++ 11 это §14.7.1 / 10. В C ++ 14 это §14.7.1 / 11, а в C ++ 17 это §17.7.1 / 9. Выдержка из C ++ 17 ниже)
Реализация не должна неявно создавать экземпляр шаблона функции, шаблона переменной, члена
шаблон, не виртуальная функция-член, класс-член, статический член данных шаблона класса или
подстановка оператора constexpr
if (9.4.1), если только такое создание не требуется
Также обратите внимание, что создание экземпляра шаблона класса возможно даже в том случае, если некоторые функции-члены не создаются для заданных параметров шаблона. Например:
template <class T>
class Xyzzy
{
public:
void CallFoo() { t.foo(); } // Invoke T::foo()
void CallBar() { t.bar(); } // Invoke T::bar()
private:
T t;
};
class FooBar
{
public:
void foo() { ... }
void bar() { ... }
};
class BarOnly
{
public:
void bar() { ... }
};
int main(int argc, const char** argv)
{
Xyzzy<FooBar> foobar; // Xyzzy<FooBar> is instantiated
Xyzzy<BarOnly> baronly; // Xyzzy<BarOnly> is instantiated
foobar.CallFoo(); // Calls FooBar::foo()
foobar.CallBar(); // Calls FooBar::bar()
baronly.CallBar(); // Calls BarOnly::bar()
return 0;
}
Это верно, даже если Xyzzy :: CallFoo () не является экземпляром, потому что нет такой вещи, как BarOnly :: foo (). Эта функция часто используется в качестве инструмента метапрограммирования шаблонов.
Обратите внимание, однако, что «создание экземпляра» шаблона напрямую не связано с тем, сколько объектного кода генерируется. Это будет зависеть от вашей реализации компилятора / компоновщика.