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 }

当我编译代码时,我收到以下错误:

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;

但如果它不是一个模板,那就没问题了。我很高兴收到您的答复。

4

3 回答 3

1

Derived中的年龄是模板中的名称。标准定义了两种名称:

  • Dependent :依赖于模板参数但未在模板中声明的名称。
  • Nondependent :不依赖于模板参数的名称,加上模板本身的名称和在其中声明的名称。

在这一行cout << age << endl,age 是一个非依赖名称,应在模板定义处解析。那时,编译器仍然不知道年龄是多少,因为 Top::sub 以后可能/可以特化。所以它不在基类中查找名称,而只在封闭范围内查找名称。由于封闭范围内没有年龄,编译器会抱怨。

在 age 上添加 this-> 或 Top:: 会使其变得依赖,因此查找规则会发生变化。现在年龄在模板的实例化点被解析,编译器完全理解基类并且可以正确解析名称。

于 2013-10-31T12:41:24.020 回答
0
class Top<T>::Derived : public Top<T>::Sub

是考虑Derived继承的另一种方式。如果这样想,那么变量 fromSub似乎依赖于 type T。当您使用依赖于template参数类型的变量时,您通常需要显式 ( Sub::age) 或明确它是成员 ( this->age)。

现在在这种情况下,虽然看起来 base 依赖于T,但您可以证明 base 中的内容。然而,这最终将取决于标准中的一些精细措辞,以及编译器对该极端情况的实现(成功与否)。

因此,要解决您的问题,请this->age在这种情况下使用。

于 2013-10-31T12:40:01.610 回答
0

age取决于一个模板类型参数,所以它的评估是到模板实例化阶段。正如您在这个线程中看到的,继承和模板不能很好地工作。在第一个(声明)阶段检查派生类上成员的使用,并且(正如我上面所说的),在第二个阶段声明(“解析”)成员。所以编译器没有声明成员的东西。

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

于 2013-10-31T12:40:40.800 回答