以下据说比公共成员第一/第二更好。我相信这几乎一样糟糕。如果您正在提供一种方法来访问课外的私有变量,那么重点是什么?功能不应该是
T First(); void(or T) First(const T&)
样品:
// Example 17-3(b): Proper encapsulation, initially with inline accessors. Later
// in life, these might grow into nontrivial functions if needed; if not, then not.
//
template<class T, class U>
class Couple {
Couple() : deleted_(false) { }
T& First() { return first_; }
U& Second() { return second_; }
void MarkDeleted() { deleted_ = true; }
bool IsDeleted() { return deleted_; }
private:
T first_;
U second_;
bool deleted_;
};
答案 0 :(得分:50)
有几个原因导致返回类的内部的引用(或指针)是坏的。从(我认为是)最重要的开始:
封装被破坏:泄漏实施细节,这意味着您无法再按照自己的意愿改变类内部。例如,如果您决定不存储first_
,而是动态计算它,您将如何返回对它的引用?你不能,因此你被卡住了。
不变不再可持续(在非const引用的情况下):任何人都可以访问和修改随意引用的属性,因此您无法“监控”其更改。这意味着您无法维护此属性所属的不变量。从本质上讲,你的班级正在变成一个blob。
生命周期问题突然出现:在属性所在的原始对象不再存在之后,很容易保留属性的引用或指针。这当然是未定义的行为。例如,大多数编译器会尝试警告保持对堆栈上对象的引用,但我知道没有编译器能够为函数或方法返回的引用设置这样的警告:你是独立的。
< / LI> 醇>因此,通常最好不要放弃引用或指向属性的指针。 甚至不是常数!
对于较小的值,通常可以通过副本(in
和out
)传递它们,特别是现在使用移动语义(在路上)。
对于较大的值,它实际上取决于具体情况,有时代理可能会减轻您的麻烦。
最后,请注意,对于某些课程,拥有公共成员并不是那么糟糕。封装pair
成员的意义何在?当你发现自己编写的类只不过是一组属性(没有任何不变量)时,那么考虑将它们公之于众,而不是让我们所有的OO并为它们编写一个getter / setter对。/ p>
答案 1 :(得分:24)
如果template
类型T
和U
是大结构,那么按价值返回费用很高。但是,您是正确的,通过引用返回相当于授予对private
变量的访问权限。要解决这两个问题,请将它们设为 const
参考:
const T& First() const { return first_; }
const U& Second() const { return second_; }
P.S。此外,当没有setter方法时,在构造函数中保持变量未初始化是一种不好的做法。在原始代码中,First()
和Second()
似乎是first_
和second_
上的包装器,用于读/写两者。
答案 2 :(得分:7)
答案取决于人们想要做什么。返回引用是促进数据结构变异的便利方式。一个很好的例子是stl地图。它返回对元素的引用,即
std::map<int,std::string> a;
a[1] = 1;
没有什么可以阻止你做
auto & aref = a[1];
这一定是不好的做法吗?我不这么认为。我会说,如果没有它,你可以这样做。如果它让生活更方便和有效地使用它并且意识到你在做什么。