MajinSaha
MajinSaha

Reputation: 198

Cannot access protected class member on the second level of inheritance of class templates in C++

I'm experiencing a problem accessing a protected class member from a class template derived from another class template. I have three class templates, the second derived from the first, and and third one derived from the second. Specifically,

class1.h:

template <typename T> class class1
{
protected:
    T data;
    int a;
public:
    class1();
    void someMethod();
};

class2.h:

#include "class1.h"

template <typename T> class class2: public class1<T>
{
    using class1<T>::a;
    T otherData;
public:
    class2();
};

class3.h:

#include "class2.h"

template <typename T> class class3: public class2<T>
{
    using class2<T>::a;
public:
    class3();
};

class2.cpp:

#include "class2.h"
#include <iostream>

template <typename T> class2<T> :: class2()
{
    std::cout<<"Creating class2 object!"<<std::endl;
    a = 2;
}

template class class2<double>;

Finally, class3.cpp:

#include "class3.h"
#include <iostream>

template <typename T> class3<T> :: class3()
{
    std::cout<<"Creating class3 object!"<<std::endl;
    a = 3;
}

template class class3<double>;

When I compile class2.cpp into an object file, like this:

g++ -c -O3 -std=c++11 -Wall -o class2.o class2.cpp

everything goes well. However, a get an error when compiling class3.cpp in the same way. A following error pops up:

In file included from class2.h:4:0,
                 from class3.h:4,
                 from class3.cpp:1:
class3.h: In instantiation of ‘class class3<double>’:
class3.cpp:11:16:   required from here
class1.h:9:6: error: ‘int class1<double>::a’ is protected
  int a;
      ^

Replacing using class2<T>::a; with using class1<T>::a; in class3 doesn't help. What's causing this error exactly and how can I avoid it if I really need to access variable a from within class3? Why is it that the first level of inheritance (class2) doesn't detect any problems, and the second one (class3) does? Thanks for any comments.

NOTE: I tried the same type of inheritance, but without templates and removed both lines containing using, and compilation goes well (access to variable a is now granted in class3). The problem definitely has to do with templates.

Upvotes: 2

Views: 1846

Answers (1)

Constructor
Constructor

Reputation: 7473

Your class2 definition is the same as the following:

template <typename T> class class2: public class1<T>
{
private: // default section
    using class1<T>::a;
    T otherData;
public:
    class2();
};

It is because private is the default section for the members of classes. So the a member becomes private here and can't be inherited by the class3. You should explicitly place using class1<T>::a; statement in protected or public section of the class2 definition:

template <typename T> class class2: public class1<T>
{
    T otherData;
protected: // <-- added
    using class1<T>::a;
public:
    class2();
};

Now it can be accessed from the class2 derived classes (including class3).

Upvotes: 2

Related Questions