I figured I'd expand Mark B's answer (though he is totally right).
the rules of the language state that you have to qualify it with this-> or base
The rules of the language are there because there are many situations where the compiler simply cannot know where to look for that name at compile time: cnt could exist in the parent class, or it could not.
Take the following example:
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;
};
How does the compiler know where to find cnt? The parent's members don't exist at declaration time. You can specialize at any time, so this specialization could be in a different file all together, and the specialization in different compilation units could not agree (wacky). The child class could have any sort of parent structure. So the compiler won't even look in the parent (which doesn't exist until instantiation time) until you tell it to.
This leads to the weird (but perfectly logical) behavior below:
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;
}
Which yields
51
1
(so the cnt in the general template does not match the cnt in the specialization).