Scenari reali per metodi protetti

14

Oggi ho notato che praticamente non utilizzo mai metodi protected nel codice C ++, perché raramente sento il bisogno di chiamare metodi non pubblici di un genitore. Io uso protetto in Java nel modello di metodo del modello, ma dato che puoi sovrascrivere i metodi privati in C ++, non ho nemmeno bisogno di protected .

Quindi quali sono alcuni scenari del mondo reale in cui vorrei utilizzare i metodi protected nel codice C ++?

(Nota che non mi piace molto l'ereditarietà dell'implementazione in generale, che potrebbe spiegare molto ...)

    
posta fredoverflow 29.03.2011 - 19:08
fonte

6 risposte

12

Ecco un esempio

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

protected:
  ~Base() { }
};

Utilizzato come classe base non polimorfica. Ma gli utenti non potranno chiamare delete baseptr; su di esso perché il distruttore è inaccessibile. Dal momento che non ha un distruttore virtuale, permettere alle persone di farlo sarebbe un comportamento indefinito. Vedi "Virtuality" di Herb.

    
risposta data 29.03.2011 - 19:14
fonte
3

Un esempio che uso frequentemente è che nella classe base del mio oggetto gerarchia avrò un logger protetto. Tutte le mie classi base avranno bisogno di accedere al Logger, ma non c'è motivo di renderlo pubblicamente accessibile.

Inoltre, se si utilizza il modello Modello e si dispone di un metodo pre o post esecuzione sulla classe base, è possibile chiamare l'implementazione di base dal metodo di sovrascrittura. Se la base è solo privata (e può ancora essere sovrascritta in C ++), non sarà possibile chiamare l'implementazione di base dal metodo di sovrascrittura.

    
risposta data 29.03.2011 - 19:17
fonte
1

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

    
risposta data 29.03.2011 - 20:00
fonte
0

Come molte altre funzioni, protected ti consente di interrompere l'incapsulamento in qualche modo. Rompere i concetti di OO puro viene in genere fatto per diversi motivi

  1. raggiungere prestazioni migliori (pensa inline ),
  2. semplificare la comprensione del codice e, ironia della sorte,
  3. migliore incapsulamento ( friend ti consente di limitare l'accesso ai membri della classe a pochi amici)

e protected è solo uno degli strumenti in quella scatola. Puoi usarlo se vuoi dare alle classi derivate l'accesso ad alcune parti di una classe che dovrebbero essere nascoste al pubblico in generale.

Un caso in cui l'ho usato è di rendere tutti i costruttori di una classe protected , fondamentalmente facendo di quella classe astratta (non puoi istanziarla eccetto che come sotto-oggetto di un oggetto di una classe derivata) .

    
risposta data 29.03.2011 - 19:15
fonte
0

Forse era un cattivo design, ma ce l'avevo per qualcosa di simile:

// 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;
};

Le classi derivate, in update() , potrebbero attivare il segnale chiamando trigger_signal() . Ma perché è tutto ciò che dovrebbero essere in grado di fare con il segnale, il segnale stesso è stato lasciato privato. La funzione di innesco è stata resa protetta perché solo la classe derivata dovrebbe essere in grado di attivarla, non di nulla.

    
risposta data 29.03.2011 - 19:23
fonte
0

"Metodi pubblici": una classe può farlo. "Metodi protetti": come una classe può farlo. "Metodi privati": come una classe può farlo, ma "Sono paranoico e non voglio che nessuno sappia come lo faccio".

// 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();
}

Quindi, un nuovo cuoco (sviluppatore) arriva al tuo fast food. Lo insegni, vendi burger (metodi pubblici), come preparare gli hamburger (metodi protetti), ma tieni la salsa segreta "brevettata" per te.

    
risposta data 30.03.2011 - 21:30
fonte

Leggi altre domande sui tag