Sólo un ejemplo que he usado en el pasado. Los métodos protegidos son excelentes para proporcionar funciones específicas de implementación, mientras que también permiten que la clase base realice un seguimiento adecuado de las cosas. Considere una clase base que proporcione una función de inicialización reemplazable, pero también debe tener un estado para determinar si se inicializó:
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
Todo está muy bien aquí. Excepto cuando una clase derivada no se molesta en llamar a setInitialized()
, no menos importante el hecho de que cualquiera pueda llamarlo (¡podríamos hacer que esté protegido aquí, y otra razón para usar métodos protegidos!). Prefiero una clase que haga uso de miembros protegidos virtuales:
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
En nuestra nueva clase, toda la inicialización aún está delegada a la clase derivada. Siempre que se haya lanzado una excepción, mantenemos el contrato "esta clase está inicializada" que nuestro método dice que sucederá.