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 }
当我编译代码时,我收到以下错误:
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 :(得分:1)
年龄是模板内的名称。标准定义了两种名称:
在第cout << age << endl
行,age是一个非依赖名称,应在模板定义时解析。此时,编译器仍然不知道年龄是多少,因为Top :: sub可以/稍后可以专用。因此它不会在基类中查找名称,而只是在封闭范围内。由于封闭范围内没有年龄,编译器会抱怨。
添加此 - &gt;或者Top :: on age使其依赖,因此查找规则会发生变化。现在,在模板的实例化时解决了年龄问题,编译器完全理解了基类,并且可以正确地解析名称。
答案 1 :(得分:0)
class Top<T>::Derived : public Top<T>::Sub
是另一种思考Derived
继承的方法。如果考虑到这种方式,则Sub
中的变量似乎取决于类型T
。当您使用依赖于template
参数类型的变量时,您通常需要明确(Sub::age
)或明确它是成员(this->age
)。
现在在这种情况下,虽然基数似乎依赖于T
,但您可以证明基数是什么。然而,这最终取决于标准中的一些精细措辞,以及编译器对该极端情况的实现(成功与否)。
因此,要解决您的问题,请在这种情况下使用this->age
。
答案 2 :(得分:0)
age
取决于模板类型参数,因此其评估是模板即时阶段。正如您在this thread中看到的那样,继承和模板不能很好地工作。在第一个(声明)阶段检查派生类上成员的使用,并且(如上所述),在第二阶段声明(“解析”)成员。所以编译器没有声明这些内容。
解决这个问题的一种方法是通过this
指针访问memeber,强制编译器检查基类。