Perché classi annidate?
Bjarne Stroustrup spiega in " La progettazione e l'evoluzione di C ++ ", l'origine e la logica dietro le classi annidate:
- C ++ originale nel 1984 aveva un singolo spazio per i nomi (pagine 5 e 102).
- l'uso di classi nidificate era un compromesso tra il concetto di una classe come ambito e la necessità di compatibilità con C (pagina 102)
- era inoltre desiderato promuovere il principio di località, cioè pezzi di codice riutilizzabili autonomi. Le classi annidate sembrano contribuire a questo obiettivo (pagina 118)
- I namespace come li conosciamo oggi sono stati aggiunti alla lingua solo nel 1993. Ciò ha permesso finalmente di esprimere la modularità al di sopra della classe e del file.
Relazione tra classe interna ed esterna
Quindi l'annidamento di classi consente di gestire l'ambito e nascondere i dettagli di implementazione.
Se la classe nidificata è pubblica, un approccio valido alternativo sarebbe quello di mettere la classe esterna e quella interna in uno spazio dei nomi intermedio.
Inoltre, Bjarne Stroustrup raccomanda per classi generiche che: " I progettisti di una classe generica dovrebbero considerare attentamente la relazione tra i suoi parametri di tipo e le sue classi nidificate, se una classe interna non dipende da tutti i parametri di tipo, dovrebbe essere spostata all'esterno e sostituita con un alias che minimizzi le dipendenze. ".
Quindi, se dovessi dare accesso alla classe interna agli interni della classe esterna, dovresti infrangere i principi di incapsulamento se scegli di rifattare la tua soluzione su un'alternativa non annidata.
Conclusione
Considerando tutto ciò, appare chiaro che la classe interiore e la classe esterna dovrebbero essere considerate classi normali e obbedire al consueto principio dell'incapsulamento.
La classe interna dovrebbe quindi, se possibile, non essere un amico della classe esterna. Invece, chiama una funzione membro appropriata per impostare il flag :
class A
{
bool bedromm_dirty;
public:
void set_dirty(bool dirt);
inline bool get_dirty() const { return dirty; }
class B // would work also if not nested
{ // no change needed if dirt would be managed with bit flags
public:
void clean_room(class A&) { set_dirty(false); }
};
};