Hemant Sharma Hemant Sharma - 3 months ago 13
C++ Question

Can a friend class object access base class private members on a derived class object?

I'm surprised that the code below compiles.

It seems that a class befriended to the (publicly inherited) base class can access a member of the base class provided an instance of the derived class.

If the inheritance is changed to

private
then compilation fails.

In short, how is
d.b_var
valid within
F::func(D& d)
?

#include <iostream>
#include <string>
using namespace std;

class B{
int b_var;
friend class F;
};

class D: public B{
int d_var;
};

class F{
public:
void func(D &d){
d.b_var = 5;
}
};

int main()
{
cout<<"fine";
}

Answer

Object of class D is composed of 2 separate parts :

part containing members of B 
part containing members of D

That why the concept of object slicing works when we do:

D objD;
B objB = objD;

Now we can access from inside object of class D, the part containing members of B via objB. Compiler remembers or can distinguish between the two parts inside class D. So compiler know what is being accessed via what.

The statement friend class F; inside class B simply tells that member functions of class F can accesses the private, protected and public members of class B. That is, for member functions of class F all the members of class B are public.

Actually, inside every class there are three sections w.r.t accessibility:

public
protected
private 

So when we declare some class B:

class B
{
    public:
        int a;
    protected:
        int b;
    public:
        int c;
};

then following 3 sections get created inside class B as shown above.

Now when we declare some class F to be a friend of class B:

class B
{
    friend class F;
    private:
        int a;
    protected:
        int b;
    public:
        int c;            
};

then the compiler creates the sections as follows:

class B
{
    friend class F;
    private:
        int a;
    protected:
        int b;
    public:
        int c;
        //int a;  only for member functions of class F
        //int b;  only for member functions of class F             
};

Note that int a; and int b; are now public for member functions of class F.

Now when class D is derived publicly from class B then the public section of class B becomes public section of class D. Similary, the protected section of class B becomes protected section of class D. Therefore, the public section part of class B can be accessed via object of class D. And since B::a; and B::b; are in public section for members functions of class F, therefore B::a and B::b can be accessed via object of class D. Also note that although after derivation int a; and int b; become members of class D, still compiler is able to distinguish them and considers them a part of class B.

Now when class D is derived privately from class B then the public section of class B becomes private section of class D. Similary, the protected section of class B becomes protected section of class D. Therefore, now the public section part inside of class B cannot be accessed via object of class D. Recall that in class B, B::a; and B::b; are originally in public section for members functions of class F but after private derivation, the members of class B i.e B::a and B::b are now in private section of class D. Therefore, B::a and B::b cannot be accessed via object of class D. Also note that although after derivation int a; and int b; become members of class D, still compiler is able to distinguish them and considers them a part of class B. After derivation the accessibility and rules of some members of class B have changed.

Since this question somewhat relates to effect of public, protected and private derivation, therefore for completeness please see: Why can a derived class not access a protected member of its base class through a pointer to base?