Ответ 1
Виртуальные функции-члены создаются при создании экземпляра класса, но не виртуальные функции-члены создаются только в том случае, если они вызываются.
Это описано в [temp.inst] в стандарте С++ (в С++ 11 это - §14.7.1/10. В С++ 14 это §14.7.1/11, а в С++ 17 это §17.7.1/9. Выдержка из С++ 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(). Эта функция часто используется в качестве инструмента метапрограммирования шаблона.
Обратите внимание, однако, что "экземпляр" шаблона напрямую не коррелирует с тем, как генерируется объектный код. Это будет зависеть от вашей реализации компилятора/компоновщика.