Ci sono esempi in cui *abbiamo bisogno* di ereditarietà protetta in C++?
-
09-06-2019 - |
Domanda
Mentre ho visto rari casi in cui privato era necessaria l'eredità, non ho mai riscontrato un caso in cui protetto è necessaria l'eredità.Qualcuno ha un esempio?
Soluzione
Le persone qui sembrano confondere l'ereditarietà della classe protetta e i metodi protetti.
FWIW, non ho mai visto nessuno usare l'ereditarietà della classe protetta e, se ricordo bene, penso che Stroustrup considerasse addirittura il livello "protetto" un errore in C++.C'è ben poco che non puoi fare se rimuovi quel livello di protezione e fai affidamento solo su pubblico e privato.
Altri suggerimenti
Esiste un caso d'uso molto raro di ereditarietà protetta.È dove vuoi usarlo covarianza:
struct base {
virtual ~base() {}
virtual base & getBase() = 0;
};
struct d1 : private /* protected */ base {
virtual base & getBase() {
return this;
}
};
struct d2 : private /* protected */ d1 {
virtual d1 & getBase () {
return this;
}
};
Il frammento precedente tentava di nascondere la sua classe base e di fornire visibilità controllata delle basi e delle loro funzioni, per qualsiasi motivo, fornendo una funzione "getBase".
Tuttavia, fallirà nella struttura d2
, Da d2
non lo sa d1
è derivato da base
.Così, covariance
non funzionerà.Una via d'uscita è derivarli protetti, in modo che l'eredità sia visibile in d2.
Un esempio simile di utilizzo di this è quando si deriva da std::ostream
, ma non vuoi che persone a caso scrivano nel tuo stream.Puoi fornire un file virtuale getStream
funzione che restituisce std::ostream&
.Questa funzione potrebbe preparare il flusso per l'operazione successiva.Ad esempio inserendo determinati manipolatori.
std::ostream& d2::getStream() {
this->width(10);
return *this;
}
logger.getStream() << "we are padded";
Domande frequenti su C++ Lite menziona un caso in cui l’uso dell’ereditarietà privata è una soluzione legittima (cfr [24.3.] Quale dovrei preferire:composizione o eredità privata?).È quando vuoi chiamare la classe derivata dall'interno di una classe base privata tramite una funzione virtuale (in questo caso derivedFunction()
):
class SomeImplementationClass
{
protected:
void service() {
derivedFunction();
}
virtual void derivedFunction() = 0;
// virtual destructor etc
};
class Derived : private SomeImplementationClass
{
void someFunction() {
service();
}
virtual void derivedFunction() {
// ...
}
// ...
};
Ora se vuoi derivare dalla classe Derived e vuoi usare Base::service()
dall'interno della classe derivata (ad esempio, vuoi spostare Derived::someFunction()
alla classe derivata), il modo più semplice per ottenere ciò è modificare l'ereditarietà privata di Base
all'eredità protetta.
Mi dispiace, non riesco a pensare a un esempio più concreto.Personalmente mi piace rendere pubbliche tutte le eredità in modo da evitare di perdere tempo con le discussioni "devo rendere la relazione di eredità protetta o privata".