Take these classes as examples:
class B { /*...*/ };
class D_priv : private B { /*...*/ };
class D_prot : protected B { /*...*/ };
class D_publ : public B { /*...*/ };
class Client { B b; /*...*/ };
Public and protected parts of B are ‘private’ in Dpriv, and are ‘protected’ in Dprot. In Dpubl, public parts of B are public (Dprot is-a-kind-of-a B), and protected parts of B remain protected in D_publ. Naturally *none* of the subclasses can access anything that is private in B. Class ‘Client’ can’t even access the protected parts of B (ie: it’s ‘sealed off’).
It is often the case that you want to make some but not all inherited member
functions public in privately/protectedly derived classes. Ex: to make member
fn B::f(int,char,float) public in D_prot, you would say:
class D_prot : protected B {
//...
public:
B::f; //note: not B::f(int,char,float)
};
There are limitations to this technique (can’t distinguish overloaded names,
and you can’t make a feature that was ‘protected’ in the base ‘public’ in the
derived). Where necessary, you can get around these by a call-through fn:
class D_prot : protected B {
public:
short f(int i, char c, float f) { return B::f(i,c,f); }
};