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