请查看以下代码:
template<class MT>
class ClassA {
public:
int cnt;
};
template<class MT>
class ClassB : public ClassA<MT> {
public:
void test() {
cnt++ ;
}
};
编译时,g ++会给出错误&#34; cnt&#34;未在范围内宣布。
如果我将cnt改为this-&gt; cnt,它就可以了。但是,我很困惑。有人可以解释为什么它不起作用?
答案 0 :(得分:5)
原因是cnt
不是依赖名称(不依赖于模板参数),因此必须使用this->
或{{1来限定它的语言规则}}。
答案 1 :(得分:2)
我想我会扩展Mark B的答案(虽然他完全正确)。
语言规则,您必须使用此属性进行限定 - &gt;或基地
语言规则存在,因为在很多情况下编译器根本无法知道在编译时在哪里查找该名称:cnt可能存在于父类中,或者它不能存在。
采用以下示例:
template<class MT>
class ClassA {
public:
};
template<class MT>
class ClassB : public ClassA<MT> {
public:
void test() {
cnt++ ;
}
};
template<>
class ClassA<int>
{
public:
int cnt;
};
编译器如何知道在哪里找到cnt?父母的成员在宣布时间不存在。你可以随时专攻,所以这个专业可以在一个不同的文件中,并且不同编译单元的专业化不能达成一致(古怪)。子类可以具有任何类型的父结构。所以编译器甚至不会查看父项(在实例化时间之前它不存在),直到你告诉它为止。
这导致下面的奇怪(但完全合乎逻辑)行为:
template<class MT>
class ClassA {
public:
};
int cnt = 50;
template<class MT>
class ClassB : public ClassA<MT> {
public:
void test() {
cnt++ ;
}
};
template<>
class ClassA<int>
{
public:
int cnt;
ClassA(){cnt=0;}
};
template <>
class ClassB<int> : public ClassA<int>
{
public:
void test() {
cnt++ ;
}
};
int main () {
ClassB<int> bi;
ClassB<float> bf;
bi.test();
bf.test();
std::cout << cnt << std::endl;
std::cout << bi.cnt << std::endl;
}
哪个收益
51
1
(因此通用模板中的cnt与专业化中的cnt不匹配。)
答案 2 :(得分:0)
编译模板不会自动查看名称的基类。这是我在短时间内找到的唯一解释:http://gcc.gnu.org/onlinedocs/gcc/Name-lookup.html
一个简单的解决方法是添加
using ClassA<MT>::cnt;
在某个地方定义你的ClassB。