Accessing protected members in a derived class

C++

C++ Problem Overview


I ran into an error yesterday and, while it's easy to get around, I wanted to make sure that I'm understanding C++ right.

I have a base class with a protected member:

class Base
{
  protected:
    int b;
  public:
    void DoSomething(const Base& that)
    {
      b+=that.b;
    }
};

This compiles and works just fine. Now I extend Base but still want to use b:

class Derived : public Base
{
  protected:
    int d;
  public:
    void DoSomething(const Base& that)
    {
      b+=that.b;
      d=0;
    }
};

Note that in this case DoSomething is still taking a reference to a Base, not Derived. I would expect that I can still have access to that.b inside of Derived, but I get a cannot access protected member error (MSVC 8.0 - haven't tried gcc yet).

Obviously, adding a public getter on b solved the problem, but I was wondering why I couldn't have access directly to b. I though that when you use public inheritance the protected variables are still visible to the derived class.

C++ Solutions


Solution 1 - C++

A class can only access protected members of instances of this class or a derived class. It cannot access protected members of instances of a parent class or cousin class.

In your case, the Derived class can only access the b protected member of Derived instances, not that of Base instances.

Changing the constructor to take a Derived instance will solve the problem.

Solution 2 - C++

protected members can be accessed:

  • through this pointer
  • or to the same type protected members even if declared in base
  • or from friend classes, functions

To solve your case you can use one of last two options.

Accept Derived in Derived::DoSomething or declare Derived friend to Base:

class Derived;

class Base
{
  friend class Derived;
  protected:
    int b;
  public:
    void DoSomething(const Base& that)
    {
      b+=that.b;
    }
};

class Derived : public Base
{
  protected:
    int d;
  public:
    void DoSomething(const Base& that)
    {
      b+=that.b;
      d=0;
    }
};

You may also consider public getters in some cases.

Solution 3 - C++

As mentioned, it's just the way the language works.

Another solution is to exploit the inheritance and pass to the parent method:

class Derived : public Base
{
  protected:
    int d;
  public:
    void DoSomething(const Base& that)
    {
      Base::DoSomething(that);
      d=0;
    }
};

Solution 4 - C++

You have access to the protected members of Derived, but not those of Base (even if the only reason it's a protected member of Derived is because it's inherited from Base)

Solution 5 - C++

You can try with static_cast< const Derived>(pBase)->Base::protected_member* ...

class Base
{
  protected:
    int b;

  public:
    ...
};

class Derived : public Base
{
  protected:
    int d;

  public:
    void DoSomething(const Base& that)
    {
      b += static_cast<const Derived*>(&that)->Base::b;
      d=0;
    }
    void DoSomething(const Base* that)
    {
      b += static_cast<const Derived*>(that)->Base::b;
      d=0;
    }
};

Solution 6 - C++

class Derived : public Base
{
  protected:
    int d;
  public:
    void DoSomething()
    {
      b+=this->b;
      d=0;
    }
};

//this will work

Solution 7 - C++

Following the hack for stl I wrote a small code which seems to solve the problem of accessing the protected members in derived class

#include <iostream>

class B
{
protected:
	int a;
public:
	void dosmth()
	{
		a = 4;
	}
	
	void print() {std::cout<<"a="<<a<<std::endl;}
};

class D: private B
{
public:
	void dosmth(B &b)
	{
		b.*&D::a = 5;
	}
};

int main(int argc, const char * argv[]) {
	
	B b;
	D d;
	b.dosmth();
	b.print();
	d.dosmth(b);
	b.print();
	
	return 0;
}

Prints

a=4
a=5

Solution 8 - C++

Use this pointer to access protected members

class Derived : public Base
{
  protected:
    int d;
  public:
    void DoSomething(const Base& that)
    {
      this->b+=that.b;
      d=0;
    }
};

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmikedView Question on Stackoverflow
Solution 1 - C++SLaksView Answer on Stackoverflow
Solution 2 - C++Sergei KrivonosView Answer on Stackoverflow
Solution 3 - C++sje397View Answer on Stackoverflow
Solution 4 - C++James CurranView Answer on Stackoverflow
Solution 5 - C++Martin.BofView Answer on Stackoverflow
Solution 6 - C++vishnu singhView Answer on Stackoverflow
Solution 7 - C++Stiv ZhopsView Answer on Stackoverflow
Solution 8 - C++user5595410View Answer on Stackoverflow