Exercises in this lecture   Go to the notes, in which this exercise belongs -- Keyboard shortcut: 'u'   Alphabetic index   Course home   

Exercise solution:
Friends and 'enemies' of a class with private and public bases


Here is a program that explains my findings, see the comments:

// 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);
}

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.