4

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

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/getter 时,方法是什么?

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

在这些情况下,您使用哪种方法或编码风格?也许摆脱 setter/getter 并将这些字段公开?

4

3 回答 3

5

我知道在课堂上设置公共字段被认为是个坏主意。

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

  1. 我需要维护这个成员的不变量吗?
  2. 这个成员可以有一个无效的值吗?
  3. 我是否希望界面提供此成员的替代表示?

如果上述任何问题的答案都是肯定的,那么您可能想要使用 getter。

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

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

虽然具有相当深的数据结构嵌套并不少见,但通常不应该深入研究特定的一段代码。如果是这样,我想它可能做得比它应该做的更多,超出了它的单一职责。但是,如果d7A对象获取是一项常见任务,也许A应该在其接口中公开它:

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

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

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

于 2013-03-28T18:52:44.103 回答
3

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

这是因为以后代码可以升级,单行方法可以扩展成更复杂的东西(或者可以添加一些debug-only build的特性来检查一些不变量等),所以最好保留与客户端一致的接口(如果您公开“原始”数据成员,这是不可能的)。

您可以避免使用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如果属性的类型比 a (它是 32-bit )更复杂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;
}
于 2013-03-28T18:51:22.327 回答
1

如果您只是将类用作纯数据结构,并且没有与您要封装的数据相关的行为struct,那么请改用 a并直接访问字段。Bjarne Stroustrup 推荐这种方法。这相当于使用 aclass并将所有成员声明为public,但将其称为 astruct可以更清楚地表明它只不过是简单的数据集合。

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

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

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

于 2013-03-28T18:51:14.053 回答