Reputation: 147
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 }
when I complie the codes, I get the following errors:
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;
But if it's not a template, it will be ok. I'm glad to receive your answers.
Upvotes: 4
Views: 113
Reputation: 2397
age in Derived is name inside a template. There are 2 kind of name defined by the standard:
At the line cout << age << endl
, age is a Non dependent name that shall be resolved at the point of the template’s definition. At that point, the compiler still doesn’t know what age is, because Top::sub could be/can be specialized later. So it doesn’t look names up in the base class, but only in the enclosing scope. Since there’s no age in the enclosing scope, the compiler complains.
Adding this-> or Top:: on age makes it dependent, hence the lookup rule changes. Now age is resolved at the point of the template’s instantiation, where the compiler has full understanding of the base class and can resolve the name correctly.
Upvotes: 1
Reputation: 14184
age
depends on a template type parameter, so its evaluation is to the template instantation phase. As you can see in this thread, inheritance and templates don't work very well. The use of a member on the derived class is checked at the first (declaration) phase, and (as I said above), the memeber is declared ("parsed") at the second phase. So the compiler things that the memeber was not declared.
One way to solve that is to access the memeber through this
pointer, to force the compiler to check the base class.
Upvotes: 0
Reputation: 275966
class Top<T>::Derived : public Top<T>::Sub
is another way to think of Derived
s inheritance. If thought of this way, then variables from Sub
appear to be dependent on the type T
. When you use variables dependent on the template
parameter type you often need to be either explicit (Sub::age
) or make it clear it is a member (this->age
).
Now in this case, while it appears that base is dependent on T
, you can prove what is in base. However this will end up depending on some fine wording in the standard, and the compiler's implementation of that corner case (either successful or not).
So to fix your problem, use this->age
in that situation.
Upvotes: 0