2013-10-31 250 views
4
1 #include <iostream> 
2 using namespace std; 
3 template<typename T> 
4 class Top { 
5 public: 
6  class Sub { 
7   protected: 
8    T age; 
9  }; 
10  class Derived : public Sub { 
11   public: 
12    void printAge() { 
13     cout << age << endl; 
14    } 
15  }; 
16 }; 
17 int main() 
18 { 
19  return 0; 
20 } 

当我complie代码,我得到以下错误:模板类已经嵌套类

test.cpp: In member function ‘void Top<T>::Derived::printAge()’: 
test.cpp:13:25: error: ‘age’ was not declared in this scope 
      cout << age << endl; 

但是,如果它不是一个模板,这将是确定。 我很高兴收到你的答案。

+0

用cout << Sub :: age << endl;替换'cout << age << endl;'适用于我。不知道我可以解释它! –

+0

适用于VS2010 –

+0

“this-> age”也可以工作 – user1233963

回答

1

衍生是一个模板里的名字。有2种名的标准所定义的:

  • 相关:名字依赖于模板参数,但不是在模板内声明 。
  • 非依赖:不依赖于模板参数的名称,以及模板本身的名称和在其中声明的名称。

在生产线cout << age << endl,年龄是一个非依赖名称应在模板的定义点来解决。那时,编译器仍然不知道年龄是多少,因为Top :: sub可能会/可以在以后专用。所以它不会在基类中查找名称,但只能在封闭范围内查找。由于在封闭范围内没有年龄,编译器抱怨。

加上this-> or Top :: on age使其依赖于,因此查找规则改变。现在年龄在模板实例化的时候解决了,编译器已经充分了解了基类,并且可以正确解析名称。

0
class Top<T>::Derived : public Top<T>::Sub 

是另一种思考Derived继承的方法。如果这样想,那么来自Sub的变量似乎取决于类型T。当您使用依赖于template参数类型的变量时,您通常需要明确(Sub::age)或将其清除为成员(this->age)。

现在在这种情况下,虽然看起来基数取决于T,但您可以证明基数是什么。然而,这将取决于标准中的一些精美的措辞,以及编译器对该角落案例的实施(无论是否成功)。

所以要解决你的问题,在这种情况下使用this->age

0

age依赖于模板类型参数,因此其评估是在模板即时阶段。正如您在this thread中看到的,继承和模板不能很好地工作。在第一阶段(声明)阶段检查派生类中成员的使用,并且(如我上面所述),在第二阶段声明(“解析”)成员。所以编译器没有声明memeber的东西。

解决这个问题的一种方法是通过this指针访问memeber,强制编译器检查基类。