为什么人们写私有字段getter返回非const引用?

Eve*_*one 14 c++ getter encapsulation private-members getter-setter

我们都同意公共变量不利于封装以及所有这些.但是,我注意到有很多代码可以执行此类操作:

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;
}
Run Code Online (Sandbox Code Playgroud)

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

为什么这个常用?

πάν*_*ῥεῖ 16

有一个反复出现的口头禅,应该使用getter/setter函数来封装你的数据.因此,许多(没有经验或咖啡超载)程序员得到他们应该使用的东西:

int& integer() { return integer_; }
Run Code Online (Sandbox Code Playgroud)

但这与简单写作没有太大区别:

class foo {
public: // <<<
    int integer_;
    string someString_;
    // ...
};
Run Code Online (Sandbox Code Playgroud)

好吧,它添加了一个函数调用,但是你无法控制客户端对引用的作用.


如果你真的想提供一个getter函数写:

const int& integer() const { return integer_; }
Run Code Online (Sandbox Code Playgroud)

相应的setter函数如下所示:

void integer(const int& value) {
    integer_ = value;
}
Run Code Online (Sandbox Code Playgroud)

  • 你为什么不写:`int integer()const {return integer_; }`? (2认同)
  • @NeilButterworth差别很小,我的例子推断除了`int`以外的其他类型(除了紧跟OP的例子). (2认同)

ein*_*ica 9

我必须部分地同意@πάνταῥεῖ和@Rakete1111的答案,考虑一个类的定义是如何随着时间的推移而演变的.

虽然这些getter方法通常是由刚刚听过"没有暴露成员"口头禅的人写的,但它们也可以合法使用:

  1. 稍后可以修改getter方法以在返回引用之前包括某种有效性检查或资源分配代码 - 对数据成员的直接访问不允许.虽然这意味着更改的代码,但它不需要更改类用户代码.此外,如果getter的实现没有在类头中公开,它甚至可能不需要重新编译类用户代码.注意:这样做可能是其他一些不良设计选择的标志.
  2. getter方法可以通过子类(在这种情况下通常使其成为虚方法)以与上述类似的方式覆盖.
  3. getter方法稍后可以用原始数据成员类型的代理替换其返回类型,而不是对实际成员的引用 - 这可能不再存在.想想如何vector<bool>运作; 当你打电话给它时,operator[]你没有得到它boolean&,你得到某种代理,当分配或分配时,它会进行适当的位提取或设置.
  4. 非const getter不适用于非const实例.实际上它确实限制了相对于公开成员的访问权限.OP的示例类的作者是否真的打算这是一个不同的问题......

总结:"虚拟"非const-reference getter可以是其他有意义的代码的存根.

话虽这么说,让getter返回const引用或值通常是一个好主意.或者只是在适当的情况下暴露场地(也有一些场景).

  • @NeilButterworth:(1)是的,但是 - 强制[link](https://en.wikipedia.org/wiki/You_aren't_gonna_need_it)给那些没有的人.(2)_I_可能不需要它,但谁知道该代码的作者需要什么? (2认同)

Rak*_*111 5

我会极力劝阻返回非const引用到一个私有变量。不是因为它破坏了封装,而是因为它是不必要的:为什么不首先创建变量public

是的,破坏封装是不好的,但这并不意味着每个变量都应该是private。某些变量是要从用户读取和修改的,因此使它们有意义public。例如,take std::pair,它有2个公共成员变量,firstsecond。这不是一个坏习惯。

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