Ciao MagoAntò,
si usa l' ereditarieta pubblica quando quando la relazione tra le classi può essere espressa con la relazione E'-UN, se invece vale la relazione (come nel tuo caso) E'-IMPLEMENTATO-IN-TERMINI_DI bisogna usare l' ereditarietà non pubblica (o meglio ancora il contenimento).
Se la classe nodo_RB deriva in maniera protetta da nodo_BST non puoi scrivere nodo_BST* b = new nodo_RB();
class nodo_RB: protected nodo_BST
{
...
};
nodo_BST* b = new nodo_RB(); // errore
A questo punto la classe derivata rimappa le funzioni della class base controllandone il tipo:
void nodo_RB::set_dx(nodo_RB *destra)
{
nodo_BST::set_dx(destra);
}
nodo_RB* nodo_RB::get_dx()
{
return (nodo_RB*) nodo_BST::get_dx();
}
In pratica la classe derivata sfrutta l' implementazione della classe base derivando in maniera protetta e impone che la costruzione dell' albero avvenga solo attraverso oggetti 'nodo_RB'.
nodo_RB* root = new nodo_RB();
root->set_dx(new nodo_RB());
nodo_RB* child = root->get_dx();
...
root->set_dx(new nodo_BST()); // sbagliato, errore di compilazione
Spero di aver reso un poco l' idea, per approfondimenti puoi vedere 'Exceptional C++' di Herb Sutter.