Solo un esempio che ho usato in passato. I metodi protetti sono ottimi per fornire funzioni specifiche dell'implementazione, consentendo al contempo alla classe base di tenere traccia correttamente delle cose. Considera una classe base che fornisce una funzione di inizializzazione sovrascrivibile, ma deve anche avere lo stato per determinare se inizializzata:
class Base
{
private:
bool m_bInitialized;
public:
virtual void Initialize() = 0;
void setInitialized() { m_bInitialized = true; };
bool isInitialized() const { return m_bInitialized; };
}; // eo class Base
Tutto va bene qui. Tranne quando una classe derivata non si preoccupa di chiamare setInitialized()
, non ultimo il fatto che qualcuno può chiamarlo (potremmo farlo protetto qui, e un'altra ragione per usare metodi protetti!). Preferisco di gran lunga una classe che fa uso di membri virtuali protetti:
class Base
{
private:
bool m_bInitialized;
protected:
virtual void InitializeImpl() = 0;
public:
void Initialize()
{
InitializeImpl();
m_bInitialized = true;
}; // eo Initialize
bool isInitialized() const { return m_bInitialized; };
}; // eo class Base
Nella nostra nuova classe, tutte le inizializzazioni sono ancora delegate alla classe derivata. A condizione che sia stata lanciata un'eccezione, manteniamo il contratto "questa classe è inizializzato" che il nostro metodo dice avverrà.