Escenarios del mundo real para métodos protegidos

14

Hoy me di cuenta de que básicamente nunca uso los métodos protected en el código C ++, porque rara vez siento la necesidad de llamar a métodos no públicos de un padre. Utilizo protegido en Java en el patrón de método de la plantilla, pero como puede anular los métodos privados en C ++, tampoco necesito protected allí.

¿Cuáles son algunos de los escenarios del mundo real en los que me gustaría usar los métodos protected en el código C ++?

(Tenga en cuenta que no me gusta demasiado la herencia de implementación en general, eso podría explicar mucho ...)

    
pregunta fredoverflow 29.03.2011 - 19:08

6 respuestas

12

Aquí hay un ejemplo

class Base {
public:
  // other members ...

protected:
  ~Base() { }
};

Se utiliza como una clase base no polimórfica. Pero a los usuarios no se les permitirá llamar a delete baseptr; porque el destructor es inaccesible. Dado que no tiene un destructor virtual, permitir que las personas hagan eso sería un comportamiento indefinido. Consulte "Virtualidad" por Herb.

    
respondido por el Johannes Schaub - litb 29.03.2011 - 19:14
3

Un ejemplo que uso con frecuencia es que en la clase base de mi jerarquía de objetos tendré un registrador protegido. Todas mis clases básicas necesitarán acceso al registrador, pero no hay razón para hacerlo público.

Además, si está utilizando el patrón de Plantilla y tiene un método de ejecución previa o posterior en la clase base, es posible que desee llamar a la implementación base desde el método de anulación. Si la base es solo privada (y aún se puede sobrescribir en C ++), no podrá llamar a la implementación base desde el método de anulación.

    
respondido por el bryanatkinson 29.03.2011 - 19:17
1

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á.

    
respondido por el Moo-Juice 29.03.2011 - 20:00
0

Como muchas otras características, protected le permite romper la encapsulación en cierta medida. Romper los conceptos OO puros se hace generalmente por varias razones

  1. logrando un mejor rendimiento (piense inline ),
  2. hacer que el código sea más fácil de entender e, irónicamente,
  3. mejor encapsulación ( friend le permite restringir el acceso a los miembros de la clase a algunos amigos)

y protected es solo una de las herramientas en ese cuadro. Puede usarlo si desea dar a las clases derivadas acceso a algunas partes de una clase que deberían ocultarse al público en general.

Un caso en el que lo he usado es hacer que todos los constructores de una clase protected , básicamente hagan que esa clase sea abstracta (no se puede crear una instancia de ella, excepto como un subobjeto de un objeto de una clase derivada) .

    
respondido por el sbi 29.03.2011 - 19:15
0

Quizás fue un mal diseño, pero lo tenía para algo como esto:

// much simplified, of course
class input_device // base class
{
public:
    virtual ~input_device() {}

    // normally would be private with public caller, etc.
    virtual void update() = 0; 

    template <typename Func>
    void register_callback(Func func)
    {
        mButtonPressSignal.connect(func);
    }

protected:
    void trigger_signal(unsigned button)
    {
        mButtonPressSignal(button);
    }

private:
    boost::signals2::signal<void(unsigned)> mButtonPressSignal;
};

Las clases derivadas, en update() , podrían activar la señal llamando a trigger_signal() . Pero como eso es todo lo que deberían poder hacer con la señal, la señal se dejó en privado. La función de activación se hizo protegida porque solo la clase derivada debería poder activarla, no nada en absoluto.

    
respondido por el GManNickG 29.03.2011 - 19:23
0

"Métodos públicos": una clase puede hacer esto. "Métodos protegidos": Cómo una clase puede hacer esto. "Métodos privados": cómo una clase puede hacer esto, pero "soy paranoico y no quiero que nadie sepa cómo lo hago".

// burguers.hpp

class BurguerClass {
  private: void addSecretRecipeSauce();  

  protected: virtual void addBread();  
  protected: virtual void addSalad();  
  protected: virtual void addMeat();
  protected: virtual void addExtraIngredients();

  public: virtual void makeBurguer();  
}

class CheeseBurguerClass: public BurguerClass {
  protected: override void addBread();  
  protected: override void addSalad();  
  protected: override void addMeat();
  protected: override void addExtraIngredients();

  protected: virtual void addCheese();

  public: override void makeBurguer();
}

class RanchStyleBurguerClass: public BurguerClass {
  protected: override void addBread();  
  protected: override void addSalad();  
  protected: override void addMeat();
  protected: override void addExtraIngredients();

  public: override void makeBurguer();
}

class EastCoastVegetarianStyleBurguerClass: public BurguerClass {
  protected: override void addBread();  
  protected: override void addSalad();  
  protected: override void addMeat();
  protected: override void addExtraIngredients();

  public: override void makeBurguer();
}

Entonces, un nuevo cocinero (desarrollador) llega a su restaurante de comida rápida. Lo enseñas, vendes hamburguesas (métodos públicos), cómo preparar las hamburguesas (métodos protegidos), pero mantén la receta de receta secreta "patentada" para ti.

    
respondido por el umlcat 30.03.2011 - 21:30

Lea otras preguntas en las etiquetas