Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple template inheritance issue C++

template <class T>
class baseclass{
protected:
    T data;
public:
    baseclass(){};
    void setData(T d);
};

template<class T>
void baseclass<T>::setT(T d){
    data = d;
}

Shown above is my base class, one protected member variable, one setter.

template <class T>
class aclass : public baseclass<T>
{
    public:
        aclass(T d);
};

template<class T>
aclass<T>::aclass(T d){
     setData(d); <---WORKS
     data = d;   <---DOESN'T WORK
}

Now this is my subclass of the first. For some reason, accessing the protected member variable directly is not working though I believe it ought to. However, accessing the setter works fine. I'm a noob with C++, I'm sure I'm missing something obvious.

like image 788
jakev Avatar asked Feb 10 '11 06:02

jakev


1 Answers

The reason that this doesn't work is a quirk in the way that C++ templates do name resolution. In particular, if you have a template class that inherits from another class that depends on a template type (as you're doing in this case), you cannot access the members of that base class directly without giving the compiler a hint about where to look. This is the cause of the error you're getting.

To fix this, you can rewrite your constructor as

template<class T>
aclass<T>::aclass(T d){
     setData(d);
     this->data = d;
}

Now that the compiler knows that data must somehow be a member of aclass<T>, it can find what it's looking for.

Interestingly, you should also be getting an error on the previous line for the same reason. I'm not sure why it decided to compile. To fix this, you can either do this:

template<class T>
aclass<T>::aclass(T d){
     this->setData(d);
     this->data = d;
}

Alternatively, you can add a using declaration to tell the compiler that aclass inherits the setData method from its parent class. In the class declaration, consider adding this line:

template <class T>
class aclass : public baseclass<T>
{
    public:
        aclass(T d);

        using baseclass<T>::setData;
};

Like the this-> for data members, this trick makes it unambiguous where the name setData comes from and helps the compiler know what you're talking about.

Hope this helps!

like image 128
templatetypedef Avatar answered Nov 09 '22 00:11

templatetypedef