subtle C++ inheritance error with protected fields

Solution 1:

Since B is publicly inherited from A, A's protected member(s) become B's protected member(s), so B can access its protected members as usual from its member function(s). That is, the objects of B can access the protected members of B from its member functions.

But A's protected members cannot be accessed outside the class, using object of type A.

Here is the relevant text from the Standard (2003)

11.5 Protected member access [class.protected]

When a friend or a member function of a derived class references a protected nonstatic member function or protected nonstatic data member of a base class, an access check applies in addition to those described earlier in clause 11.102) Except when forming a pointer to member (5.3.1), the access must be through a pointer to, reference to, or object of the derived class itself (or any class derived from that class) (5.2.5). If the access is to form a pointer to member, the nested-name-specifier shall name the derived class (or any class derived from that class).

And the example follows from the Standard (2003) itself as:

[Example:

class B {
  protected:
  int i;
  static int j;
};

class D1 : public B {
};

class D2 : public B {
  friend void fr(B*,D1*,D2*);
  void mem(B*,D1*);
};

void fr(B* pb, D1* p1, D2* p2)
{
  pb->i = 1; // ill-formed
  p1->i = 2; // ill-formed
  p2->i = 3; // OK (access through a D2)
  p2->B::i = 4; // OK (access through a D2, even though naming class is B)
  int B::* pmi_B = &B::i; // ill-formed
  int B::* pmi_B2 = &D2::i; // OK (type of &D2::i is int B::*)
  B::j = 5; // OK (because refers to static member)
  D2::j =6; // OK (because refers to static member)
}
void D2::mem(B* pb, D1* p1)
{
  pb->i = 1; // ill-formed
  p1->i = 2; // ill-formed
  i = 3; // OK (access through this)
  B::i = 4; // OK (access through this, qualification ignored)
  int B::* pmi_B = &B::i; // ill-formed
  int B::* pmi_B2 = &D2::i; // OK
  j = 5; // OK (because j refers to static member)
  B::j = 6; // OK (because B::j refers to static member)
}
void g(B* pb, D1* p1, D2* p2)
{
  pb->i = 1; // ill-formed
  p1->i = 2; // ill-formed
  p2->i = 3; // ill-formed
}
—end example]

Note in the above example fr() is a friend function of D2, mem() is a member function of D2, and g() is neither a friend, nor a member function.

Solution 2:

Consider:

class A {
protected:
  int x;
};

class C : public A
{
};

class B : public A {
protected:
  unique_ptr<A> a;
public:
  B() : a(new C) // a now points to an instance of "C"
  { }

  void foo() {
    int w = a->x;  // B accessing a protected member of a C? Oops.
  }
};

Solution 3:

In Public Inheritance:
All Public members of the Base Class become Public Members of the derived class &
All Protected members of the Base Class become Protected Members of the Derived Class.

As per the above rule:
protected member x from A becomes protected member of class B.

class B can access its own protected members in its member function foo but it can only access members of A through which it was derived not all A classes.

In this case, class B contains a A pointer a, It cannot access the protected members of this contained class.

Why can the B::foo() access the members of the contained class B pointer b?

The rule is:
In C++ access control works on per-class basis, not on per-object basis.
So an instance of class B will always have access to all the members of another instance of class B.

An Code Sample, which demonstrates the rule:

#include<iostream>

class MyClass 
{
    public: 
       MyClass (const std::string& data) : mData(data) 
       {
       }

       const std::string& getData(const MyClass &instance) const 
       {
          return instance.mData;
       }

    private:
      std::string mData;
};

int main() {
  MyClass a("Stack");
  MyClass b("Overflow");

  std::cout << "b via a = " << a.getData(b) << std::endl;
  return 0;
}