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 in
- It seems that somehow friendship is inherited and a friend class can access a member of the derived class.
In short, how isd.b_var
valid withinF::func(D& d)
?
d.b_var
might be misleading. To be more precise (another way to see it), b_var
is not (direct) member of derived class D
. Instead, the object of D
contains a subobject of base class B
, which has member b_var
, and could be accessed by the friend F
. (As we can also write d.b_var
as d.B::b_var
.)
$10/3 Derived classes [class.derived]:
The base-specifier-list specifies the type of the base class subobjects contained in an object of the derived class type. [ Example:
struct Base { int a, b, c; }; struct Derived : Base { int b; }; struct Derived2 : Derived { int c; };
Here, an object of class
Derived2
will have a subobject of classDerived
which in turn will have a subobject of classBase
. — end example ]
And
- If the inheritance is changed to
private
then compilation fails.
Because
class B {
int b_var;
friend class F;
};
class D: private B {
int d_var;
};
class F{
public:
void func(D &d) {
d.b_var = 5; // Fail. Can't access subobject of B
d.d_var = 5; // Fail. Can't access member of D
}
};
Then
class B {
int b_var;
};
class D: private B {
friend class F;
int d_var;
};
class F{
public:
void func(D &d) {
d.b_var = 5; // Fail. Can't access b_var of subobject of B
d.d_var = 5; // Fine.
}
};
Note that in last case, even F
is friend of class D
, it could access all the private/protected members of D
, but not including members in subobject B
, because they're not (direct) members of class D
.