受保护方法的真实场景


14

今天,我注意到我基本上从不使用protectedC ++代码中的方法,因为我很少感到需要调用父级的非公共方法。我确实在模板方法模式中使用了Java中的protected,但是由于您可以在C ++中覆盖私有方法,因此我也不需要protected

那么,在哪些实际场景中我想protected在C ++代码中使用方法?

(请注意,我一般不太喜欢实现继承,这可能会解释很多...)

Answers:


12

这是一个例子

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

protected:
  ~Base() { }
};

用作非多态基类。但是delete baseptr;由于析构函数不可访问,因此不允许用户调用它。由于它没有虚拟析构函数,因此允许人们这样做将是不确定的行为。请参阅Herb的“虚拟性”


1
你们怎么了?为什么这被否决?这是完全合理的。如果您不明白,请询问。如果您觉得错了,请解释。我们在这里从您的见解中学习。
2011年

为什么是-1?这是我想到的第一件事。
GManNickG 2011年

1
构造函数和析构函数是我所见过的唯一用途。请注意,gcc仍会发出警告,指出该析构函数不是虚拟的。
Matthieu M.

+1我还使用受保护的方法来应用一些书的建议:具有带有受保护的虚拟功能的公共接口,而不是公共虚拟功能。
克拉姆

3

我经常使用的一个示例是,在对象层次结构的基类中,我将有一个受保护的Logger。我所有的基类都需要访问Logger,但是没有理由使其可以公开访问。

另外,如果您使用的是Template模式,并且在基类上具有执行前或执行后的方法,则可能需要从重写方法中调用基本实现。如果基础仅是私有的(并且仍然可以用C ++覆盖),则将无法从覆盖方法调用基础实现。


1
是不是所有的模板模式并不不必调用基类方法???
2011年

要点了,但我不会说不必调用基类方法就是“全部”。在许多情况下,我有对象层次结构来实现具有多个级别的模板模式,每个级别都添加了更多的功能/检查。在这些情况下,将需要一种Protected方法。
bryanatkinson 2011年

1

只是我过去使用的一个示例。受保护的方法非常适合提供特定于实现的功能,同时还允许基类正确跟踪事物。考虑一个提供可重写的初始化函数的基类,但还必须具有确定是否初始化的状态:

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

这里一切都很好。除非派生类不必费心调用setInitialized()任何人都可以调用它的事实(我们可以在此将其设置为受保护的对象,以及使用受保护方法的另一个理由!)。我更喜欢使用虚拟受保护成员的类:

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

在我们的新类中,所有初始化仍然委托给派生类。提供一个抛出的异常,我们维护我们的方法将要发生的“此类已初始化”协定。


0

与许多其他功能一样,protected您可以在某种程度上打破封装。打破纯OO概念通常是出于以下几个原因

  1. 实现更好的性能(认为inline),
  2. 使代码更易于理解,具有讽刺意味的是,
  3. 更好的封装(friend允许您将对类成员的访问权限限制为几个朋友)

并且protected是在该对话框的工具只有一个。如果您想让派生类访问应该向公众隐藏的类的某些部分,则可以使用它。

我用过的一种情况是使一个类的所有构造函数成为该类的protected基本组成部分(除了作为派生类对象的子对象之外,您不能实例化它)。


0

也许这是不好的设计,但是我有这样的想法:

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

in中的派生类update()可以通过调用触发信号trigger_signal()。但是因为这就是他们应该能够处理的信号,所以信号本身就被保密了。由于只有派生类才应该能够触发它,所以根本就什么都不能触发它,从而使触发函数受到保护。


0

“公共方法”:一个类可以做到这一点。“受保护的方法”:类如何做到这一点。“私有方法”:类如何做到这一点,但是“我很偏执,不想让任何人知道我如何做到这一点”。

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

因此,一名新厨师(开发人员)到达了您的快餐店。您教书,卖汉堡包(公共方法),如何制作汉堡包(受保护的方法),但将“专利”秘密配方酱留给自己。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.