使用受保护成员有什么不好?有什么替代方案?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (35)

我最近被告知受保护的成员是坏的,在做了一些阅读后,似乎确实是共识(例如http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-protected)。那我该怎么做呢?

假设我正在研究一组Widget类,并且每个小部件应该具有许多共同属性(例如foo,bar和baz)。我可以按如下方式定义基类:

class Widget
{
public:
    virtual ~Widget() = default()

    Foo foo() const;
    Bar bar() const;
    Baz baz() const;

    virtual void someInterfaceMethod() = 0;

protected:
    Foo m_foo;
    Bar m_bar;
    Baz m_baz;
};

Widget::foo() { return m_foo; } // etc.

在这个特定场景中,实现它的更好方法是什么?

我是否应该将Widget设置为仅接口类,然后在每个派生的窗口小部件中定义这些成员?我应该将它们设为私有,并在派生类的构造函数中使用get()和set()方法吗?我应该将它们设为私有并更改Widget构造函数以将它们作为参数吗?如果在施工之后它们无法完全初始化,该怎么办?

提问于
用户回答回答于

“X很好”,“X很糟糕”可能是太黑白一种表征事物的方式; 一如既往,没有绝对的好或坏,只有相对水平的适合实现你的目的。

至于为什么有些人可能不喜欢直接将受保护的成员变量暴露给子类代码,这可能与他们不喜欢将公共成员变量暴露给其他代码的原因相同 - 因为这样做会使其难以改变您将来的实现,而不会破坏其他依赖于当前实现细节的代码。

通过强制子类代码通过方法调用而不是直接访问成员变量,您可以强制该代码通过您可以控制的途径,因此将来可以修改而无需修改调用代码。例如,有一天您可能会决定每次m_baz修改,您想要打印日志消息(或其他)。如果所有10,000个呼叫站点都在调用set_m_baz(newVal)您的类,那么这是一个文件中的单行更改要实现。如果OTOH允许他们全部m_baz = newVal;直接进行,那么你现在必须修改所有10,000个呼叫站点以获得你想要的结果,这个潜在客户可以从乏味到不可能,具体取决于你的情况,谁拥有主叫代码等等。

扫码关注云+社区

领取腾讯云代金券