2

As we know a private member is inaccessible (not just private) in derived classes while public and protected are directly accessible there.

  • If a class declares another class as a friend then the latter has full-access to the members of the first.

Here is an example I've tried to understand but in vain:

class A
{
    public:
       int pub;
    private:
       int priv;
    protected:
        int prot;
    friend class D;
};

class B : public A // public inheritance
{
    int b = 0;
};

class C : private A
{
    int c = 0;

};

class D
{
     public:
        void foo(B);
        void bar(C);
};

void D::foo(B b)
{
    b.pub = 0;
    b.prot = 0;
    b.priv = 0; // why this works? although A::priv is inaccessible in derived classes because it is private in base class?
   // b.b = 0; // error. ok because b is private
}

void D::bar(C c)
{
 //   c.pub = 0; // error ok
 //   c.prot = 0; // error ok
 //   c.priv = 0; // error ok
 //   c.c = 0; // error. ok because c is private
}
  • The problem: Why D::foo can access private member of A through an object from a publicly inherited from Base A although we know private is inaccessible in derived classes? so why b.priv = 0; works? We know that friendship is neither transitive nor inherited?
H.S.
  • 11,654
  • 2
  • 15
  • 32
Maestro
  • 2,512
  • 9
  • 24
  • 1
    *"We know that friendship is neither transitive nor inherited?"* - Your example doesn't violate that. Only the `A` part is being accessed. – StoryTeller - Unslander Monica Jun 26 '20 at 01:02
  • @StoryTeller-UnslanderMonica: But why instances of B in D's member functions can access even private members of A while instances of C cannot? I guess this has a relation to type of inheritance. can you explain? thank you! – Maestro Jun 26 '20 at 09:54

1 Answers1

1

class D is friend of class A, it has full access to its public, protected and private members. class B publicly inherit class A, that means, class D has access1) to base class of class B. Hence, the access of priv member of class A using object of class B is allowed in class D.


Read below part of answer only if you are thinking that access of pub, prot and priv, in D::bar(C) function of friend class D, is giving error because class A is privately inherited by class C.

In case of class C, it privately inherit class A. As you have pointed out that the statements c.pub, c.prot and c.priv of D::bar(C) function are giving error. It's because of class C inherit class A privately.

If I uncomment them and compile, the errors I am getting in D::bar(C) function are:

p.cpp:44:5: error: cannot cast 'C' to its private base class 'A'
    c.pub = 0;
    ^
p.cpp:21:11: note: declared private here
class C : private A
          ^~~~~~~~~
p.cpp:44:7: error: 'pub' is a private member of 'A'
    c.pub = 0;
      ^
p.cpp:21:11: note: constrained by private inheritance here
class C : private A
          ^~~~~~~~~
p.cpp:8:12: note: member is declared here
       int pub;

Same errors for prot and priv members as well.

These errors are due to private inheritance of class A and has nothing to do with friend class D. Try access it in similar way outside of friend class D and you will get same errors.

Using C style cast you can cast a derived class to private base class, like this:

void D::bar(C c)
{
    ((A*)&c)->pub = 0;
    ((A*)&c)->prot = 0;
    ((A*)&c)->priv = 0;
    //c.c = 0; // error. ok because c is private
}

With this now you can access class C privately inherit base class (class A) private members in its friend class class D. Note that priv member access using C style cast in D::bar(C) function is working fine only because class D is friend of class A. If you try to access the private member of privately inherit base class in derived class using C style cast, its not allowed:

class C : private A {
    int c = 0;
    public:
      void Cfoo();

};

void C::Cfoo() {
        ((A*)this)->pub = 100;
        ((A*)this)->priv = 100;   // error: 'priv' is a private member of 'A'
}

1). Quoting from this answer:

Let's consider a class Base and a class Child that inherits from Base.

  • If the inheritance is public, everything that is aware of Base and Child is also aware that Child inherits from Base.
  • If the inheritance is protected, only Child, and its children, are aware that they inherit from Base.
  • If the inheritance is private, no one other than Child is aware of the inheritance.
H.S.
  • 11,654
  • 2
  • 15
  • 32