Cenários do mundo real para métodos protegidos


14

Hoje notei que basicamente nunca uso protectedmétodos no código C ++, porque raramente sinto a necessidade de chamar métodos não públicos de um pai. Eu uso protegido em Java no padrão de método de modelo, mas como você pode substituir métodos privados em C ++, também não preciso protecteddisso.

Então, quais são alguns cenários do mundo real em que eu gostaria de usar protectedmétodos no código C ++?

(Observe que não gosto muito de herança de implementação em geral, isso pode explicar muito ...)

Respostas:


12

Aqui está um exemplo

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

protected:
  ~Base() { }
};

Utilizado como uma classe base não polimórfica. Mas os usuários não terão permissão para acessá delete baseptr;-lo porque o destruidor é inacessível. Como não possui destruidor virtual, permitir que as pessoas façam isso seria um comportamento indefinido. Veja "Virtualidade" de Herb.


1
O que há com vocês? Por que isso foi prejudicado? É perfeitamente razoável. Se você não entender, pergunte. Se você acha que está errado, por favor, explique. Estamos aqui para aprender com suas idéias.
SBI

Por que -1? Esta é a primeira coisa que pensei.
GManNickG 29/03

1
Construtores e destruidores são os únicos usos que eu já vi. Observe que o gcc ainda emite um aviso de que o destruidor não é virtual neste.
Matthieu M. 29/03

+1 Eu também uso o método protected para aplicar alguns conselhos de livros: ter uma interface pública com funções virtuais protegidas, em vez de funções virtuais públicas.
Klaim

3

Um exemplo que eu uso com freqüência é que, na Classe Base do meu objeto Hierarquia, terei um Agente de Log protegido. Todas as minhas classes básicas precisarão acessar o Logger, mas não há motivo para tornar isso acessível ao público.

Além disso, se você estiver usando o padrão Template e tiver um método de execução anterior ou posterior na classe base, convém chamar a implementação base a partir do método de substituição. Se a base for apenas privada (e ainda puder ser substituída em C ++), você não poderá chamar a implementação de base pelo método de substituição.


1
O padrão do modelo não é sobre não precisar chamar métodos de classe base ???
SBI

Ponto de vista, mas eu não diria que é 'tudo' não ter que chamar métodos de classe base. Em muitas situações, tenho hierarquias de objetos implementando o padrão de modelo que possui vários níveis, cada um dos quais adiciona um pouco mais de funcionalidade / verificações. Nesses casos, um método protegido seria necessário.
bryanatkinson

1

Apenas um exemplo que eu usei no passado. Os métodos protegidos são ótimos para fornecer funções específicas da implementação, além de permitir que a classe base rastreie corretamente as coisas. Considere uma classe base que fornece uma função de inicialização substituível, mas também deve ter estado para determinar se foi inicializada:

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

Tudo está bem aqui. Exceto quando uma classe derivada não se preocupa em chamar, setInitialized()pelo menos, o fato de que alguém pode chamá-la (poderíamos tornar isso protegido aqui, e outro motivo para usar métodos protegidos!). Eu prefiro uma classe que faz uso de membros virtuais protegidos:

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

Em nossa nova classe, toda inicialização ainda é delegada à classe derivada. Desde que seja lançada uma exceção, mantemos o contrato "esta classe é inicializada" que, segundo nosso método, acontecerá.


0

Como muitos outros recursos, protectedpermite que você quebre o encapsulamento até certo ponto. Quebrar os conceitos puros de OO geralmente é feito por várias razões

  1. alcançar melhor desempenho (pense inline),
  2. tornando o código mais fácil de entender e, ironicamente,
  3. melhor encapsulamento ( friendpermite restringir o acesso dos alunos a alguns amigos)

e protectedé apenas uma das ferramentas nessa caixa. Você pode usá-lo se desejar conceder às classes derivadas acesso a algumas partes de uma classe que devem estar ocultas do público em geral.

Um caso em que eu o usei é tornar todos os construtores de uma classe protected, basicamente tornando essa classe abstrata (você não pode instancia-la, exceto como um subobjeto de um objeto de uma classe derivada).


0

Talvez tenha sido um design ruim, mas eu o tinha para algo assim:

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

Classes derivadas, em update(), podem acionar o sinal chamando trigger_signal(). Mas como isso é tudo o que eles devem fazer com o sinal, o próprio sinal foi deixado em sigilo. A função acionadora foi protegida porque apenas a classe derivada deve ser capaz de acioná-la, e nada.


0

"Métodos públicos": uma classe pode fazer isso. "Métodos protegidos": como uma classe pode fazer isso. "Métodos particulares": como uma classe pode fazer isso, mas "sou paranóico e não quero que ninguém saiba como faço".

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

Assim, um novo cozinheiro (desenvolvedor) chega ao seu restaurante de fast food. Você ensina, vende burguers (métodos públicos), como preparar os burguers (métodos protegidos), mas guarde para si o molho secreto "patenteado" da receita.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.