5

I'm trying several programs about inheritance, and it turned out that the following caused an error but I don't really know the rationale.

#include <iostream>

using namespace std;

class Base {
protected:
    int x = 0;
};

class Derived: public Base {

    // OK: access protected member via this
    void g() { cout<<x; } 

    // OK: access protected member of other Derived
    void h(Derived& d) { cout<<d.x; } 

    // FAIL: access Base class's protected member, why?
    void f(Base& b) { cout<<b.x; } 
};

int main() {}

I expect that the Derived class could access the ​Base class's public or protected data members and member function.

However it didn't work as what I was thinking about, could anyone help me light up my concepts?

Useless
  • 64,155
  • 6
  • 88
  • 132
Sean Tsai
  • 53
  • 3
  • "Didn't work" how? Did it compile? If not, the error should be in your question. – Useless Apr 05 '19 at 10:07
  • Really sorry for the unclear description, the program can't compile and I don't really know the rationale behind clearly. – Sean Tsai Apr 05 '19 at 10:09
  • 2
    Possible duplicate of [Accessing protected members in a derived class](https://stackoverflow.com/questions/3247671/accessing-protected-members-in-a-derived-class) - it's exactly the same question. – Samer Tufail Apr 05 '19 at 10:09
  • It's just disallowed explicitly by the standard in [class.protected], and there is an identical example as yours. – felix Apr 05 '19 at 10:10
  • You should access the member variable `x` as it is. E.g. `void f(Base& b) {cout<< x;}`. If you refer to it like `b.x` you assume, that `x` is public in the class `B`, however accessing it directly, assumes, that you refer to it like `this->x`. – vahancho Apr 05 '19 at 10:13
  • Otherwise, you will be able to "steal" protect member from whichever class hierarchy you want by simply deriving from it. – felix Apr 05 '19 at 10:20
  • 1
    @SeanTsai no problem - I just reordered your code a little so it was easier to see which case failed. – Useless Apr 05 '19 at 10:21
  • @Useless the answer that you linked doesn't explain why it happens, however my understanding atleast from the end of the question is that OP is interested in finding the cause of why this behavior is Illegal, it happens because of the way most compilers execute inheritance and I don't find that anywhere in the linked question. – anand_v.singh Apr 05 '19 at 10:35
  • I believe the linked question explains it about as well as the accepted answer: they just confirm that this behaviour is intended by the standard, and neither explains the motivation. Of course you're welcome to vote to reopen if you disagree. – Useless Apr 05 '19 at 12:08

4 Answers4

2
void f(Base& b) {cout<<b.x;}

Here you are trying to access a protected member of a different class. It does not matter that you also share the same base class. (still looking for a source)

void g() {cout<<x;}

In this example you are acccessing your own private member. (protected members of base class are inherited and protected in derived class)

void h(Derived& d) {cout<<d.x;}

Here you are accessing the private member of the same class. But for more on this look at this post: Access private elements of object of same class

FloIsAwsm
  • 156
  • 1
  • 5
2

There is not more to it than you already discovered. Derived instances may acces their protected members and those of other derived instances but not those of base class instances. Why? Because thats how protected works by definition.

For more details I refer you to cppreference (emphasize mine):

A protected member of a class Base can only be accessed

1) by the members and friends of Base

2) by the members and friends (until C++17) of any class derived from Base, but only when operating on an object of a type that is derived from Base (including this)

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
1

From this documentation

A protected member of a class Base can only be accessed

  1. by the members and friends of Base

    this is not your case

  2. by the members and friends (until C++17) of any class derived from Base, but only when operating on an object of a type that is derived from Base (including this)

    this is your case, but the argument b is not such a derived type

The reason for protected member access is to allow a base class to define an interface for use by derived classes. That's not the same as allowing every different derived type special access to every base class object.

Community
  • 1
  • 1
Useless
  • 64,155
  • 6
  • 88
  • 132
0

The code in your question seems like the example in the cppreference website and there we can see a good explanation for that limitation in the code comments:

struct Base {
 protected:
   int i;
 private:
   void g(Base& b, struct Derived& d);
};

struct Derived : Base {
   void f(Base& b, Derived& d) // member function of a derived class
   {
      ++d.i; // okay: the type of d is Derived
      ++i; // okay: the type of the implied '*this' is Derived
//    ++b.i; // error: can't access a protected member through Base
//             (Otherwise it would be possible to change other derived classes, 
//                  like a hypothetical Derived2, base implementation)
    }
};

So, if you have a

class Derived2: public Base {
};

The Derived class shall not be allowed to access Derived2 protected attributes as it is not a child of Derived2. The purpose of protected is not to allow siblings but children class access to members.

Full details in the standard:

olivecoder
  • 2,858
  • 23
  • 22