miked
miked

Reputation: 3598

Accessing protected members in a derived class

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.

Upvotes: 92

Views: 133593

Answers (8)

Serg Kryvonos
Serg Kryvonos

Reputation: 4677

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.

Upvotes: 14

SLaks
SLaks

Reputation: 888167

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.

Upvotes: 70

Stiv Zhops
Stiv Zhops

Reputation: 21

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

Upvotes: 2

Martin.Bof
Martin.Bof

Reputation: 56

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;
    }
};

Upvotes: 3

vishnu singh
vishnu singh

Reputation: 31

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

//this will work

Upvotes: 1

user5595410
user5595410

Reputation: 27

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;
    }
};

Upvotes: -2

sje397
sje397

Reputation: 41862

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;
    }
};

Upvotes: 10

James Curran
James Curran

Reputation: 103575

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)

Upvotes: 4

Related Questions