人们为什么写私人场getters返回非const参考

Why do people write private-field getters returning a non-const reference?

本文关键字:返回 const 参考 getters 为什么      更新时间:2023-10-16

我们都可以就公共变量对封装和所有这些不利。但是,我注意到很多执行此类内容的代码:

class foo {
private:
    int integer_;
    string someString_;
    // other variables
public:
    int& integer() { return integer_; }
    string& someString() { return someString_; }
    // other "functions"
}
int main() {
    foo f;
    f.integer() = 10;
    f.someString() = "something";
    return 0;
}

我已经看到它在许多地方被使用,但我不明白为什么。基本上,它返回对数据的引用,从而将其直接暴露于外部。因此,从任何角度来看,都没有真正实现封装。

为什么通常使用?

有一个反复出现的咒语,应使用 getter/setter 函数来封装您的数据。因此

int& integer() { return integer_; }

,但这与简单写作没有太大不同:

class foo {
public: // <<<
    int integer_;
    string someString_;
    // ...
};

好吧,它添加了一个函数调用,但是您无法控制客户端对参考的操作。


如果您真的想提供 getter 函数写作:

const int& integer() const { return integer_; }

相应的 setter 函数看起来像:

void integer(const int& value) {
    integer_ = value;
}

我必须部分与 @πάνταῥεῖ和 @rakete1111的答案部分不同意,考虑到班级的定义是如何随着时间而变化的。

的确,这些方法通常是由刚刚听到"无暴露成员"咒语的人写的,但它们也可以具有合法的用途:

  1. getter方法可以修改 在返回参考之前,要在返回参考之前包含某种有效性检查或资源分配代码 - 直接访问数据成员不允许。虽然这意味着更改 class 的代码,但它不需要更改类用户代码。另外,如果在类标题中未公开Getter的实现,则可能不需要重新编译类用户代码。注意:这样做可能是其他一些不良设计选择的迹象。
  2. getter方法可能被子类(在这种情况下通常是虚拟方法)所覆盖的。
  3. Getter方法稍后可能会用原始数据成员类型的代理替换其返回类型,而不是对实际成员的引用 - 甚至可能不再存在。想想vector<bool>的工作原理;当您调用其operator[]时,您将无法获得boolean&,您将获得某种代理,当分配或分配到to时,会进行适当的位提取或设置。
  4. 非const getter不能用于非const实例。因此,实际上它确实限制了访问相对于直接暴露成员的访问。OP的示例类的作者是否实际上是一个不同的问题...

总结:"虚拟"非const-Reference getter可以是其他有意义的,代码的 stub

话虽如此,只要让Getter返回const引用或值,通常是一个好主意。或者只是在适当的情况下暴露该领域(也有一些)。

我会强烈劝阻返回 non-const 引用对私人变量的参考。不是因为它破坏了封装,而是因为它是不必要的:为什么不首先制作变量public

破坏封装不好,是的,但这并不意味着每个变量应为 private。某些变量应从用户中读取和修改,因此使其成为public是有意义的。例如,以std::pair为例,它具有2个公共成员变量firstsecond。那不是不好的做法。

唯一没有意义的时间是当变量不应该写入时。那将是不好的,因为它实际上会打破封装并使整个程序难以调试。

该结构可用于调试目的。

如果您有公共变量,则无法轻松监视其用法。将其转换为一对私有变量和方法返回参考,将允许您放置断点和/或记录呼叫。

但是,单独的getter和setter可以更好地实现相同的目的,因此这只是与普通公共变量相比的优势。

我写了一次。我稍后计划返回并用将堆栈对象返回到可以施放到原始类型并通过原始类型分配给的东西的东西。这使我稍后返回并拦截所有作业以进行验证。

有些压倒性的Techinque。项目上的其他编码人员都无法理解。整个堆栈被撕掉了。