Setter / getters和分层数据结构

时间:2013-03-28 18:39:40

标签: c++

我知道在你的课堂上设置公共字段被认为是一个坏主意。但是,当您的类包含众多分层数据结构和字段时,最好的方法是什么?例如:

class A {B d1; C d2; D d3;}
class B {E d4; F d5;}
class E {G d6; int d7;}

在C中,很容易访问这样的数据结构,例如ptr_to_A-> d1.d4.d7等等......但是当我们使用setter / getters时的方法是什么?

在C ++中使用setter和getter时,像A.get_d1()。get_d4()。get_d7()这样的表达式似乎不方便,它们会强制返回引用。由于某些结构非常大,按价值返回似乎是一个糟糕的主意。

在这些情况下,您使用哪种方法或编码方式?也许摆脱setter / getters并将这些领域公之于众?

3 个答案:

答案 0 :(得分:2)

在我的编码风格中,一个类不应该暴露公共的“原始”数据成员,而应该只暴露getter和setter(即使它们是简单的单行方法)。

这是因为代码可以在将来升级,并且单行方法可以扩展到更复杂的东西(或者可以添加一些仅调试构建功能来检查一些不变量等),所以它是更好地保持客户端的接口一致(如果您公开“原始”数据成员,这是不可能的。)

您可以避免使用get_()前缀,只需将数据成员视为具有简单(不含get_...)名称的“属性”,例如

class Shape
{
public:
  ....

  COLORREF Color() const // Just Color() i.e. the property name, without get_...
  {
     return m_color;
  }

private:
  COLORREF m_color;
};

编写客户端代码,如:

Shape s;
COLORREF someColor = s.Color();

对我来说很好看。

对于setter,您可以使用如下语法:

Shape& Color(COLORREF color)
{
    m_color = color;
    return *this;
}

并编写客户端代码,如:

Shape s;
s.Color(...).Draw(); // set color and draw shape

如果属性的类型比COLORREF(32位DWORD)更复杂,则可以使用如下模式:

std::wstring Name() const // getter
{
    return m_name;
}

Shape& Name(std::wstring name) // setter
{
    // Pass by value and move from the value (C++11 move semantics)
    m_name = std::move(name);

    return *this;
}

答案 1 :(得分:2)

  

我知道在你的课堂上设置公共字段是一个坏主意。

这是来自上一个十年Java开发的全面声明。您应该考虑成员应该是逐个成员公开还是私有。有时公共数据成员是正确的想法。请考虑以下问题:

  1. 我是否需要对此会员保持不变?
  2. 此会员可以使用无效值吗?
  3. 我是否希望界面提供此成员的替代表示?
  4. 如果上述任何问题的答案都是肯定的,那么您可能想要使用吸气剂。

    还要考虑单独设置成员是否真的有意义。也许您应该使用构造函数设置成员,并且您希望提供一些修改这些成员的其他接口。

      

    在C ++中使用setter和getter时,像A.get_d1()。get_d4()。get_d7()这样的表达式似乎不方便

    虽然对数据结构进行相当深的嵌套并不常见,但通常一段特定的代码不应该深入研究它。如果确实如此,我想它可能做得比它应该做的更多,超出了它的单一责任。但是,如果从d7对象获取A是一项常见任务,则A可能应在其界面中公开它:

    int A::get_d7 {
      return get_d1().get_d4().get_d7();
    }
    
      

    由于某些结构非常大,按价值返回似乎是一个糟糕的主意。

    实际上,使用现代C ++,这根本不是问题。传递值应该被视为对象传递的默认模式。这是因为现在可以移动临时对象,这实际上是一种非常有效的复制形式。

答案 2 :(得分:1)

如果您只是将一个类用作纯数据结构,并且没有与要封装的数据相关的行为,那么请改用struct并访问直接领域。 Bjarne Stroustrup recommends this approach。这相当于使用class并将所有成员声明为public,但将其称为struct则更清楚地表明它只不过是简单的数据集合。

如果您所做的不仅仅是存储数据,那么请使用getter和setter。

  

在C ++中使用setter和getter时,表达式如   A.get_d1()。get_d4()。get_d7()似乎不方便,而且他们强迫   返回参考。由于一些结构非常大,所以返回   按价值似乎是一个可怕的想法。

不,您可以选择是按引用还是按值返回。