编译以下代码时遇到此错误。 在做了一些研究并在不同情况下阅读类似的错误之后,我想出了我需要的解决方案。 但我没有完全理解错误和修复的不正当理由。
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()
来解决它,但我不完全理解为什么编译器无法解决这个问题。
有人可以解释一下为什么吗?
答案 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();
}
};