是否返回了访问者惯用语的参考?

Lie*_*yan 12 c++ idioms reference accessor

在C++中,可以创建一个返回对私有字段的引用的访问器.

class Cls {
    private:
        int _attr;
    public:
        int& attr() { return _attr; }
};
Run Code Online (Sandbox Code Playgroud)

这样可以如下访问该属性:

// set
c.attr() = 4;

// get
cout << c.attr() << endl;
Run Code Online (Sandbox Code Playgroud)

这种风格的访问者惯用/良好实践吗?一个普通的C++程序员会看到这种访问者的风格会感到惊讶吗?(提示:我第一次看到这个时很惊讶,但有点喜欢这种风格)

Chr*_*utz 10

假设你需要保证:

template <int Base>
class Digit {
  private:
    int attr_; // leading underscore names are reserved!
  public:
    int attr() const { return attr_; }
    void attr(int i) { attr_ = i % Base; } // !
};
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您无法返回引用,因为无法保证用户不会以您不想要的方式修改它.这是使用setter的主要原因 - 您可以(现在或以后)过滤输入以确保它是可接受的.有了参考,您必须盲目地接受用户分配给您的会员的内容.那时,为什么不公开呢?

  • 实际上,领先的下划线名称并非全部保留.它们在全局命名空间中保留(不是这种情况),如果它们后面的字母是大写字母(也不是这种情况),则保留它们.对类成员使用`_ [a-z0-9].*`标识符很好.但答案是+1,如果你提供直接访问,你还是打破了封装. (3认同)

ild*_*arn 7

不,只要您还提供const过载,该代码就不足为奇了:

class Cls {
    int _attr;
public:
    int& attr() { return _attr; }
    int const& attr() const { return _attr; }
};
Run Code Online (Sandbox Code Playgroud)

但是,出于Chris Lutz和Mark B提到的原因,我会考虑以下惯用语:

class Cls {
    int _attr;
public:
    int const& attr() const { return _attr; }
    void attr(int i) { _attr = i; }
};
Run Code Online (Sandbox Code Playgroud)


Mar*_*k B 5

通常,对于非平凡的类(例如可以简单地定义为a的类struct),为特定属性提供访问器/增变器可能是代码气味.通常,类应该倾向于保持其内部状态:内部.如果你提供一个非const引用内部状态,那么突然间你根本无法控制类不变量.这不仅会使调试变得更加困难,因为可能的状态更改的范围是整个项目,它会阻止您更改类的内部,因为它们实际上是状态和用户API.

相反,你应该设计一些方法,在你的类上执行有意义的工作,同时保持类不变量.在某些情况下,提供对特定状态变量的只读访问权限是完全正常的,而在其他情况下,您只希望以另一种方式提供对最终状态的访问.


Mik*_*our 5

这样做完全违背了首先将其设为私有的目的.

访问器的目的是以这样的方式公开内部状态:当外部代码尝试修改状态时,类可以维护不变量(通过仅允许读访问,或者在修改状态之前验证写访问); 它们通常看起来像

int  attr() const {return _attr;}
void attr(int a)  {_attr = a;}
Run Code Online (Sandbox Code Playgroud)

如果将来需要约束属性可以采用的值,或者更改它在内部存储的方式,那么您可以在不更改类接口的情况下修改这些属性的实现.

如果没有必要(并且您已经决定永远不需要),那就公开一下吧; 将它作为参考公开只会获得几行不必要的代码和使用它时的古怪语法.