2

公共类成员有什么区别

class data
{
public:

    std::list<data> list_of_data;
};

以及返回私有成员作为参考的方法?

class data
{
public:

   std::list<data>& get_data()
   { return list_of_data; }

private:

    std::list<data> list_of_data;
};

哪一个更好?

4

5 回答 5

3

这种形式的问题没有多大意义。如果您公开广播在第二种情况下list_of_data确实是成员的事实data(即使它是私有的),那么实际上没有区别。

但这不是我们拥有私人成员的目的。在典型的 C++ 设计中,在您的第二个变体中,不允许外部代码使用任何关于data. 外部代码唯一知道的是公共get_data()成员。实际数据在哪里get_data()- 局外人不知道也不关心。

在这种情况下,差异变得非常明显。

  • list_of_data在第一种情况下,您暴露了作为 class 成员实际存在的事实data。例如,它立即意味着生命周期与相应实例list_of_data的生命周期相同。data这也意味着不同的data实例有不同的list_of_data成员。

  • 在第二种情况下,您不会暴露任何类似的东西。外部代码不知道实际std::list<data>对象的位置以及它的生命周期。外部代码不知道 的不同实例是否data会从其get_data()成员返回不同的引用。为了得到这些问题的答案,外部用户必须注意代码的预期设计,而不是通过阅读代码来得出结论。这是一件好事。

这就是我们经常使用访问器函数(甚至是返回引用的函数)而不是公开暴露数据成员的全部原因。

于 2012-07-04T17:30:44.673 回答
2

第二种方法几乎总是更可取。它增加了一点额外的抽象,足以让它非常有用。

例如,使用第二种方法,您可以将您的成员变量移动到您的类中的任何其他组合,并且仍然保持接口。您甚至可以将其移至 PIMPL 并放弃包含<list>. 或者,您可以将功能设为虚拟并将成员移动到其他位置。它基本上使所有使用你的类的代码更能抵抗改变,这总是好的。

在其最基本的形式中,该函数通常甚至是内联的,从而在运行时使抽象自由。

现在唯一不是真正免费的方面是程序员时间,如果您认为省去编写函数更具成本效益,那就这样吧。但是,您可能应该使用其中一种“哑”聚合类型,例如tuple<>pair<>

于 2012-07-04T17:29:59.347 回答
0

如果它不是结构(即只有没有任何逻辑的数据) - 成员必须是私有的。例如,阅读 Herb Sutter 进行解释。

于 2012-07-04T17:10:22.717 回答
0

这两种方法都是不好的封装,因为它们可以修改对象,甚至用新对象替换它。相反,使用get按值或const引用返回对象的方法:

const MyClass &getObj() { .... }

使返回的对象不能被修改。

编辑 如果您仍然想修改返回的对象,那么只需通过引用返回它。在我看来,这至少比public field.

于 2012-07-04T17:11:41.667 回答
0

让我给你推荐几篇文章:

gotw #70 - 封装处理关于数据成员是公共的、受保护的、私有的问题。

gotw #76:访问权限的使用和滥用

After reading Herb Sutter's Exceptional C++ style which contains several gotw articles (including the ones above), I definitely vote for your 2nd example: private members, public access methods.

于 2012-07-04T18:09:56.580 回答