模板继承:没有依赖于模板参数的参数

时间:2016-09-23 18:44:45

标签: c++ templates inheritance

编译以下代码时遇到此错误。 在做了一些研究并在不同情况下阅读类似的错误之后,我想出了我需要的解决方案。 但我没有完全理解错误和修复的不正当理由。

template <typename T>
class TestA {
    int a;
    T temp;

protected:
    int b; 

public: 
    int c;

    TestA(T te): a{10}, b{20}, c{30}, temp{te} {}

    int geta(){ return a; }
    int getb(){ return b; }
    int getc(){ return c; }
};

template <typename T>
class TestB {
    int atb;
    T tempb;

protected:
    int btb; 

public: 
    int ctb;

    TestB(T te) atb{10}, btb{20}, ctb{30}, tempb{te} {}
};

template <typename T>
class TestInh : public TestA<T>, public TestB<T> {
    int aa;
    T temptemp;

protected:
    int bb; 
    int b;

public: 
    int cc;

    TestInh(T te) : TestA<T>{te}, TestB<T>{te}, bb{10000}, b{-1000} {}

    int get_total() {
        // The error happens here!
        return geta();
    }
};

int main(int argc, char const *argv[]) {
    char text = 'a';
    TestInh<char> test(text);

    //std::cout << test.geta() << std::endl;
    std::cout << test.get_total() << std::endl;
    //std::cout << test.c << std::endl;
    return 0;
}

编译此代码时,出现此错误:

testtemplate.cc: In member function ‘int TestInh<T>::get_total()’:
testtemplate.cc:54:32: error: there are no arguments to ‘geta’ that depend on a template parameter, so a declaration of ‘geta’ must be available [-fpermissive]
int get_total() {return geta();}
                            ^
testtemplate.cc:54:32: note: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)

通过调用this->geta()而不仅仅是geta()来解决它,但我不完全理解为什么编译器无法解决这个问题。

有人可以解释一下为什么吗?

1 个答案:

答案 0 :(得分:5)

在扩展依赖于模板参数的类时,this会成为依赖名称。

问题在于,在执行两阶段名称查找时,编译器无法知道他在哪里可以找到函数geta。他不知道它来自父母。因为模板特化是一个事物,TestA<int>TestA<double>可能是两个完全不同的clas,它们具有不同的功能和成员。

添加this关键字后,编译器知道geta必须是成员函数。

如果没有它,它可以是成员函数或非成员函数,也可以是TestB的成员函数。

想象一下模板代码,它将从geta调用函数TestA,从geta调用TestB,具体取决于某些模板条件。哎哟。编译器希望确保代码对于每个模板实例都是一致的。

另一种向编译器说这个函数作为成员函数存在的方法是添加一个using语句:

template <typename T> 
struct TestInh : TestA<T>, TestB<T> {
    // some code...

    using TestA<T>::geta;

    int get_total() {
        // works! With the above using statement,
        // the compiler knows that 'geta()' is
        // a member function of TestA<T>!
        return geta();
    }
};