Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么人们编写私有字段获取程序返回非常量引用?_C++_Encapsulation_Getter Setter_Getter_Private Members - Fatal编程技术网

C++ 为什么人们编写私有字段获取程序返回非常量引用?

C++ 为什么人们编写私有字段获取程序返回非常量引用?,c++,encapsulation,getter-setter,getter,private-members,C++,Encapsulation,Getter Setter,Getter,Private Members,我们都同意公共变量不利于封装等等。但是,我注意到有很多代码可以实现这类功能: class foo { private: int integer_; string someString_; // other variables public: int& integer() { return integer_; } string& someString() { return someString_; } // other "functi

我们都同意公共变量不利于封装等等。但是,我注意到有很多代码可以实现这类功能:

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;
}
我在很多地方看到过这种方法,但我不明白为什么。基本上,它返回对数据的引用,从而将其直接公开给外部。因此,从任何角度来看,都没有真正实现封装


为什么经常使用这种方法?

我强烈建议不要返回对私有变量的非常量引用。不是因为它破坏了封装,而是因为它是不必要的:为什么不首先将变量
公开

是的,破坏封装是不好的,但这并不意味着每个变量都应该是私有的。有些变量是要从用户那里读取和修改的,因此将它们公开是有意义的。例如,假设它有两个公共成员变量,
first
second
。这不是坏习惯


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

有一个反复出现的咒语,即应该使用getter/setter函数来封装数据。因此,许多(无经验或咖啡过量)程序员认为他们应该使用以下内容:

int& integer() { return integer_; }
但这与简单的写作没有多大区别:

class foo {
public: // <<<
    int integer_;
    string someString_;
    // ...
};
相应的setter函数如下所示:

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

我不得不部分地不同意这两种观点ῥεῖ 以及@Rakete1111的答案,考虑到类的定义是如何随着时间的推移而演变的

虽然这些getter方法通常是由刚听过“禁止暴露成员”咒语的人编写的,但它们也可以有合法的用途:

  • getter方法稍后可能会被修改,以在返回引用之前包含某种有效性检查或资源分配代码——直接访问数据成员是不允许的。虽然这意味着更改类的代码,但不需要更改类用户代码。此外,如果getter的实现没有在类头中公开,那么它甚至可能不需要重新编译类用户代码。注意:这样做可能是其他一些糟糕的设计选择的标志
  • getter方法可能会被子类(在这种情况下,它通常是一个虚拟方法)以与上面类似的方式重写
  • getter方法稍后可能会将其返回类型替换为原始数据成员类型的引用,而不是对实际成员的引用,而实际成员可能不再存在。想想
    vector
    是如何工作的;当你调用它的
    操作符[]
    时,你不会得到一个
    布尔值&
    ,你会得到某种代理,当它被赋值或赋值时,会进行适当的位提取或设置
  • 非常量getter不能用于非常量实例。所以实际上,相对于直接暴露成员,它确实限制了访问。OP示例类的作者是否真的打算这样做是另一个问题 总之:虚拟的非常量引用getter可以是其他有意义代码的存根。


    也就是说,让getter返回常量引用或值通常是个好主意。或者只是在适当的情况下(也有一些情况)公开字段。

    此结构可用于调试目的

    如果你有一个公共变量,你就不能很容易地监控它的使用。 将其转换为一对私有变量和返回引用的方法将允许您放置断点和/或记录调用


    然而,单独的getter和setter可以更好地达到相同的目的,因此这只是相对于普通公共变量的一个优势。

    我写过一次。我计划稍后返回并用返回堆栈对象的对象替换字段getter,该对象可以转换为原始类型并由原始类型分配。这使我可以稍后返回并截取所有分配,以将验证放入


    这是一种强大的技术。项目中的其他编码人员都无法理解它。整个堆栈都被撕掉了。

    “为什么经常使用这个?”是因为常见的愚蠢行为。之所以经常使用它,是因为许多程序员并不真正知道自己在做什么。所以他们基本上认为自己在解决问题,而他们所做的只是在代码中添加冗长的内容?正如其他评论员所说的那样,这很糟糕。不幸的是,常见做法和最佳做法并不总是相同的。顺便说一句,我相信这是不常见的…是的,它只是增加了冗长的代码,这是不必要的。然而,许多人使用它。这简直让我大吃一惊:|是的,这就像
    std::vector
    中的
    size()
    为什么不写:
    int integer()const{return integer}
    ?@NeilButterworth差别很小,我的例子可以很好地推断出
    int
    以外的其他类型(除了紧跟OP的例子).@每个人都需要更多的打字、更多的代码阅读,而且效率可能更低。如果您查看标准库中的类似函数,它们返回整数值。std::pair没有任何行为-如果您的类有行为,则公共数据是fatal@NeilButterworth为什么?有什么区别吗?正如@NeilButterworth所说,
    pair
    没有行为。它只是数据的容器。所以这是最好的做事方式?有不同于演员的容器吗?除了需要
    friend
    的情况之外,如果您有一个具有行为的类,例如std::string,那么如果您可以轻松地更改实现该类的变量,会发生什么情况?如果直接更改指向存储的指针,std::string会发生什么情况
    void integer(const int& value) {
        integer_ = value;
    }