公共类成员有什么区别
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;
};
哪一个更好?
公共类成员有什么区别
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;
};
哪一个更好?
这种形式的问题没有多大意义。如果您公开广播在第二种情况下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()
成员返回不同的引用。为了得到这些问题的答案,外部用户必须注意代码的预期设计,而不是通过阅读代码来得出结论。这是一件好事。
这就是我们经常使用访问器函数(甚至是返回引用的函数)而不是公开暴露数据成员的全部原因。
第二种方法几乎总是更可取。它增加了一点额外的抽象,足以让它非常有用。
例如,使用第二种方法,您可以将您的成员变量移动到您的类中的任何其他组合,并且仍然保持接口。您甚至可以将其移至 PIMPL 并放弃包含<list>
. 或者,您可以将功能设为虚拟并将成员移动到其他位置。它基本上使所有使用你的类的代码更能抵抗改变,这总是好的。
在其最基本的形式中,该函数通常甚至是内联的,从而在运行时使抽象自由。
现在唯一不是真正免费的方面是程序员时间,如果您认为省去编写函数更具成本效益,那就这样吧。但是,您可能应该使用其中一种“哑”聚合类型,例如tuple<>
或pair<>
如果它不是结构(即只有没有任何逻辑的数据) - 成员必须是私有的。例如,阅读 Herb Sutter 进行解释。
这两种方法都是不好的封装,因为它们可以修改对象,甚至用新对象替换它。相反,使用get
按值或const
引用返回对象的方法:
const MyClass &getObj() { .... }
使返回的对象不能被修改。
编辑
如果您仍然想修改返回的对象,那么只需通过引用返回它。在我看来,这至少比public field
.
让我给你推荐几篇文章:
gotw #70 - 封装处理关于数据成员是公共的、受保护的、私有的问题。
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.