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";
}
Private members of the base class cannot be used by the derived class unless friend declarations within the base class explicitly grant access to them.
If a base class has a friend function, then the function doesn't become a friend of the derived class(es). For example, the following program prints an error because the show() which is a friend of base class A tries to access private data of derived class B.
Explanation: A base class pointer can point to a derived class object, but we can only access base class member or virtual functions using the base class pointer because object slicing happens when a derived class object is assigned to a base class object.
On the other hand, multiple levels of inheritance means a class has been derived from a base class and the base class itself has been derived from another base class. Multiple inheritance is not permitted in C#.NET. 2. An object of a derived class cannot access private members of base class.
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With