Here is a program that explains my findings, see the comments: If also frD becomes of friend of B and C, the access to b and c is legal from frD. Remember, a friend of D is not a friend of the bases of D. Also remember that friendship is not inherited. Therefore, it is not sufficient for frD to be a friend of B and C alone.// A class D with both a private and public base class, and where frD is a friend of class D.
// Solution to exercise. Does not compile. The errors are marked and explained in the comments.
#include <iostream>
#include <string>
using namespace std;
class D;
class B {
// friend void frD(D &ad);
private:
int b;
public:
B(int b): b(b){}
void Bop(){ // Bop is public in B
cout << "Bop()" << endl;
}
};
class C {
// friend void frD(D &ad);
private:
int c;
public:
C(int c): c(c){}
void Cop(){ // Cop is public in C
cout << "Cop()" << endl;
}
};
class D : private B, public C {
friend void frD(D &ad);
private:
int d;
public:
D(int b, int c, int d): B(b), C(c), d(d){}
void Dop(){ // Dop is public in D
cout << "Dop()" << endl;
Bop();
Cop();
}
};
// The friend of D:
void frD(D &ad){
ad.Dop(); // OK. Dop is public
cout << ad.d << endl; // OK. frD is a friend of D
ad.Bop(); // OK. B is a private base, Bop becomes private in D, frD is a friend of D.
ad.Cop(); // OK. C is public in D.
cout << ad.b << endl; // Illegal: b is private in B.
cout << ad.c << endl; // Illegal: c is private in C. Even with public inheritance!
}
// A non-friend of D: Here we nickname it an 'enemy', therefore the name enD:
void enD(D &ad){
ad.Dop(); // OK. Dop is public
cout << ad.d << endl; // Illegal: enD is not a friend.
ad.Bop(); // Illegal: Because B is a private base, Bop is private in D.
ad.Cop(); // OK: Because C is a public base, Cop is public i D.
cout << ad.b << endl; // Illegal: b is private in B.
cout << ad.c << endl; // Illegal: c is private in C. Even with public inheritance!
}
int main(){
D d(1,2,3);
frD(d);
enD(d);
}