以下是重新创建我遇到的问题的代码。 Base
类是具有虚函数foo
的模板类。 foo
有一个默认实现,用于添加传入的参数。
SimpleDerived
来自Base
,专门用std::string
。 SimpleDerived
重载虚拟Base<T>::foo()
函数。在foo
中调用时,此类会按预期编译精细及其main
输出。
#include <iostream>
template<class T>
struct Base
{
virtual void foo(T val)
{
T local = val + val; // THE OFFENDING LINE OF CODE
std::cout << "Base" << std::endl;
}
};
struct SimpleDerived : public Base<std::string>
{
virtual void foo(std::string val)
{
std::cout << "SimpleDerived" << std::endl;
}
};
struct SimpleObject
{
int value;
};
struct ComplexDerived : public Base<SimpleObject>
{
virtual void foo(SimpleObject val)
{
std::cout << "ComplexDerived" << std::endl;
}
};
int main(void)
{
Base<int> base;
base.foo(2);
SimpleDerived simpleDerived;
simpleDerived.foo("hello world");
SimpleObject object;
ComplexDerived complexDerived;
complexDerived.foo(object);
return 0;
}
ComplexDerived
派生自Base
,专门用自定义结构SimpleObject
。 ComplexDerived
也会重载foo
。但是,这是问题的根源。如果我尝试编译这个,我得到:
quicktest.cpp: In member function ‘void Base<T>::foo(T) [with T = SimpleObject]’:
quicktest.cpp:47:1: instantiated from here
quicktest.cpp:8:19: error: no match for ‘operator+’ in ‘val + val’
显然,SimpleObject
没有运算符“+”。但这是我的困惑..编译器被要求实现Base<SimpleObject>::foo
,因为这是ComplexDerived
继承的。但是,我从不使用或致电Base<SimpleObject>::foo
。那么编译器是否应该尝试生成这个基类函数?
答案 0 :(得分:9)
C ++ 11标准的第14.7.1 / 10段规定:
实现不应隐式实例化功能模板,成员模板,非虚拟 成员函数,成员类或不需要实例化的类模板的静态数据成员。 未指定实现是否隐式实例化 如果虚拟成员函数不会被实例化,则为类模板的虚拟成员函数。 [...]
换句话说,这种情况下的行为是特定于实现的。
虽然理论上编译器可以弄清楚不会调用对基类的foo()
实现的调用(因为函数调用不是通过引用或指针)并避免实例化它,标准不强制要求这种行为。