La necessità per la parola chiave public
è proprio quella per le classi definite con la parola chiave class
, il modificatore di accesso predefinito (per tutto - membri dati, funzioni membro e classi base) è private
. Così
class World : State {};
è lo stesso:
class World : private State {};
e che probabilmente non è ciò che si vuole - significa che la classe base è accessibile solo all'interno della classe World
. Gli estranei "non sanno" che l'eredità esiste.
Per classi definite con la parola chiave struct
, il modificatore di accesso di default è public
, in modo da potrebbe scrittura:
struct World : State {};
e ottenere qualcosa che sia sembra e si comporta un po 'come tutte le altre lingue con l'ereditarietà. Ma la parola chiave struct
e il fatto che definisce una classe, è in realtà solo lì per compatibilità con C.Non troverai molte guide in stile C++ che consigliano di utilizzarlo solo per ottenere l'accessibilità pubblica predefinita, in genere viene utilizzato solo per le classi che sono POD, o forse solo per le classi senza funzioni membro.
Per quanto riguarda il motivo per cui C++ ha ereditarietà privata in primo luogo: per la maggior parte degli scopi, l'ereditarietà privata è una forma di composizione. Composizione normale:
class World {
State state;
public:
void foo() {
state.bar();
state.baz();
and so on
}
};
Cioè, il mondo di classe sa che è implementato utilizzando uno Stato, e il mondo esterno non sa come mondiale è implementato.
vs.
class World : private State {
public:
void foo() {
bar();
baz();
and so on
}
};
Cioè, il mondo di classe sa che è implementato da essendo uno Stato, e il mondo esterno non sa come è implementato. Ma puoi esporre selettivamente parti dell'interfaccia di stato inserendo ad esempio using State::bar;
nella parte pubblica della definizione di World. L'effetto è come se scriveste faticosamente una funzione (o diversi sovraccarichi) in World, ognuno dei quali delega alla stessa funzione su State.
Oltre a evitare la digitazione, un uso comune dell'ereditarietà privata è quando la classe è vuota, ovvero non ha membri di dati. Quindi se si tratta di un membro di World
, deve occupare spazio (ovviamente, a seconda del layout dell'oggetto questo potrebbe essere lo spazio che altrimenti sarebbe solo il padding, quindi non necessariamente aumenta la dimensione di World
), ma se è una classe base quindi una cosa chiamata "ottimizzazione della classe base vuota" entra in gioco e può essere a dimensione zero. Se stai creando un lotto, questo potrebbe importare. L'ereditarietà privata consente l'ottimizzazione, ma il mondo esterno non inferisce una relazione "è-a", perché non vede l'ereditarietà.
È una bella differenza. In caso di dubbio, usa solo la composizione esplicita. L'introduzione dell'ereditarietà per risparmiare la digitazione è molto buona fino a quando non ha conseguenze inaspettate.
Intendevi scrivere 'class World: private State {}'? In quello che hai effettivamente scritto, l'eredità è pubblica. –
Intendevi 'class World: private State'? – detunized
@Steve, @detunized Mi dispiace per il mio stupido errore. Ho modificato la domanda. – Eonil