Scenari del mondo reale per metodi protetti


14

Oggi ho notato che praticamente non uso mai protectedmetodi nel codice C ++, perché raramente sento la necessità di chiamare metodi non pubblici di un genitore. Uso il metodo protetto in Java nel modello di modello, ma poiché è possibile ignorare i metodi privati ​​in C ++, non ho nemmeno bisogno di protectedlì.

Quindi quali sono alcuni scenari del mondo reale in cui vorrei usare protectedmetodi nel codice C ++?

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

Risposte:


12

Ecco un esempio

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

protected:
  ~Base() { }
};

Utilizzato come classe di base non polimorfica. Ma agli utenti non sarà permesso di chiamarlo delete baseptr;perché il distruttore è inaccessibile. Dal momento che non ha un distruttore virtuale, consentire alle persone di farlo sarebbe un comportamento indefinito. Vedi "Virtuality" di Herb.


1
Come va ragazzi? Perché questo è stato downvoted? È perfettamente ragionevole. Se non lo capisci, ti preghiamo di chiedere. Se ritieni che sia sbagliato, ti preghiamo di spiegare. Siamo qui per imparare dalle tue intuizioni.
sabato

Perché -1? Questa è la prima cosa a cui ho pensato.
GManNickG

1
Costruttori e distruttori sono gli unici usi che ho visto. Nota che gcc emette ancora un avviso che il distruttore non è virtuale su questo.
Matthieu M.

+1 Uso anche il metodo protetto per applicare alcuni consigli sui libri: avere un'interfaccia pubblica con funzioni virtuali protette, anziché funzioni virtuali pubbliche.
Klaim

3

Un esempio che uso frequentemente è che nella Classe Base del mio oggetto Gerarchia avrò un Logger protetto. Tutte le mie classi di base avranno bisogno dell'accesso al Logger, ma non c'è motivo di renderlo accessibile al pubblico.

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 sostituzione. Se la base è solo privata (e può ancora essere sovrascritta in C ++), non sarà possibile chiamare l'implementazione di base dal metodo di sostituzione.


1
Il modello di modello non consiste nel non dover chiamare metodi di classe base ???
sabato

Punto preso, ma non direi che è "tutto" non dover chiamare metodi di classe base. In molte situazioni ho gerarchie di oggetti che implementano il modello di modello con più livelli, ognuno dei quali aggiunge leggermente più funzionalità / controlli. In questi casi, sarebbe necessario un metodo protetto.
Bryanatkinson,

1

Solo un esempio che ho usato in passato. I metodi protetti sono ottimi per fornire funzioni specifiche dell'implementazione, consentendo allo stesso tempo alla classe base di tracciare correttamente le cose. Prendi in considerazione una classe di base che fornisce una funzione di inizializzazione sostituibile, ma deve anche avere uno 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

Qui va tutto bene. Tranne quando una classe derivata non si preoccupa di chiamare, setInitialized()non da ultimo il fatto che chiunque può chiamarla (potremmo renderlo protetto qui, e un altro motivo per usare metodi protetti!). Preferisco di gran lunga una classe che utilizza membri protetti virtuali:

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, tutta l'inizializzazione è ancora delegata alla classe derivata. A condizione che venga generata un'eccezione, manteniamo il contratto "questa classe è inizializzata" che il nostro metodo dice che accadrà.


0

Come molte altre funzionalità, protectedti consente di interrompere l'incapsulamento in una certa misura. La rottura dei concetti di OO puro viene generalmente eseguita per diversi motivi

  1. ottenere prestazioni migliori (pensa inline ),
  2. rendere il codice più facile da capire e, ironicamente,
  3. migliore incapsulamento ( friendconsente di limitare l'accesso ai membri della classe ad alcuni amici)

ed 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 grande pubblico.

Un caso in cui l'ho usato è quello di rendere tutti i costruttori di una classe protected, fondamentalmente rendendo tale classe astratta (non è possibile crearne un'istanza se non come oggetto secondario di un oggetto di una classe derivata).


0

Forse era un cattivo design, ma l'ho avuto per qualcosa del genere:

// 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 poiché è tutto ciò che dovrebbero essere in grado di fare con il segnale, il segnale stesso è stato lasciato privato. La funzione trigger è stata resa protetta perché solo la classe derivata dovrebbe essere in grado di attivarla, per nulla.


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 ristorante fast food. Lo insegni, vendi hamburger (metodi pubblici), come preparare gli hamburger (metodi protetti), ma tieni la salsa segreta "brevettata" per te.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.