C ++模板继承不会看到基类成员

时间:2014-03-21 17:29:32

标签: c++ inheritance

请查看以下代码:

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,它就可以了。但是,我很困惑。有人可以解释为什么它不起作用?

3 个答案:

答案 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。