0

Possible Duplicate:
C++ Inherited template classes don't have access to the base class

I'm experiencing problems with templates and inheritance. Simply, I have a template class which I want another template class to inherit from. I don't understand why members of base class are not visible within deriving class? Though without using templates everything works as expected. For example:

template <typename T>
class Foo
{
public:
    T x;
    T y;
    void doX(){ x = x+1; }
    void doY(){y++;}
protected:
    T a;
    T b;
    void doA(){a++;}
};

template <typename T>
class Bar : public Foo<T>
{
public:
    void doX(){x++; y++;} // ERROR
    void doY(){x++; y++;} // ERROR
    void doA(){a++;b++;}  // ERROR
};
Community
  • 1
  • 1
sorush-r
  • 10,490
  • 17
  • 89
  • 173
  • Compiles fine for me using DevStudio 2005 and instantiating with `int`. How are you instantiating it? – Skizz Jul 04 '12 at 12:35
  • Members of base class (`Foo`) are not visible in the `Bar` : `error: 'x' was not declared in this scope` – sorush-r Jul 04 '12 at 12:35
  • I'm using: "Thread model: posix, gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)" I'm not even instantiating! – sorush-r Jul 04 '12 at 12:37
  • @Skizz: It sounds like your compiler doesn't perform two-phase lookup correctly - a lot of compilers used to get that wrong, and unfortunately some are still in widespread use. – Mike Seymour Jul 04 '12 at 12:42
  • @mfontanini: Oops! Actually no. Sorry it's my hastiness. – sorush-r Jul 04 '12 at 12:46

4 Answers4

8

These variables are dependent names (read The Dreaded Two-Phase Name Lookup for details), so you need to use this as:

void doX(){ this->x++; this->y++; } 

Usually this-> is not required as it is implicit. But here it is required. Actually explicit this-> tells the compiler to look up the name in the second phase when the base class is instantiated, as this case uses two-phase name lookup mechanism.

Or you could qualify them with base class as:

template <typename T>
class Bar : public Foo<T>
{
    typedef Foo<T> base; //add this friendly typedef!
public:
    void doX(){  base::x++; base::y++;} 
    //...
};

In this case, the fact that the names cannot be looked-up untill base (which is a typedef of Foo<T>) is instantiated, becomes more obvious (to humans eyes) in my opinion.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • Am I wrong to say that inside classes, one should always precede non-static class members with "this->"? Even though you write more, it improves code clarity. – Mihai Todor Jul 04 '12 at 12:45
  • @MihaiTodor: In this case, you're *required* to write `this`, in other cases `this` is *implicit*. – Nawaz Jul 04 '12 at 12:46
  • 1
    Accepting for the link. Thanks. – sorush-r Jul 04 '12 at 12:48
  • I've been always recommended to use `this->` in C++ in every case. I thought that was just a matter of code readability. But here, seems to be necessary :| – sorush-r Jul 04 '12 at 12:50
  • 2
    @sorush-r: Yes. Here it is *needed*. Actually explicit `this->` tells the compiler to look up the name in the **second** phase when the base class is instantiated, as this case uses two-phase name lookup mechanism. – Nawaz Jul 04 '12 at 12:53
7

If the base class depends on a template parameter, then its members aren't directly available in the derived class definition. Until the template is instantiated, the compiler doesn't know what the base class will contain, and so it won't look up any names from there.

You can force it to treat the names as members by qualifying them:

void doX(){this->x++; Foo<T>::y++;}  // OK: both forms specify that it's a member
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
3

Write this->x, this->y instead of x, y in derived class functions.

ForEveR
  • 55,233
  • 2
  • 119
  • 133
1

Try referring to the variables using the base class scope:

Foo<T>::x

or use this

this->x
juanchopanza
  • 223,364
  • 34
  • 402
  • 480