重载C ++模板类虚函数

时间:2013-06-14 22:39:23

标签: c++ function templates virtual overloading

以下是重新创建我遇到的问题的代码。 Base类是具有虚函数foo的模板类。 foo有一个默认实现,用于添加传入的参数。

SimpleDerived来自Base,专门用std::stringSimpleDerived重载虚拟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,专门用自定义结构SimpleObjectComplexDerived也会重载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。那么编译器是否应该尝试生成这个基类函数?

1 个答案:

答案 0 :(得分:9)

C ++ 11标准的第14.7.1 / 10段规定:

  

实现不应隐式实例化功能模板,成员模板,非虚拟   成员函数,成员类或不需要实例化的类模板的静态数据成员。 未指定实现是否隐式实例化   如果虚拟成员函数不会被实例化,则为类模板的虚拟成员函数。 [...]

换句话说,这种情况下的行为是特定于实现的。

虽然理论上编译器可以弄清楚不会调用对基类的foo()实现的调用(因为函数调用不是通过引用或指针)并避免实例化它,标准不强制要求这种行为。