在成员函数中返回*this

Joe*_*Joe 13 c++ class this

我最近使用了一个允许以下类型语法的库:

MyClass myObject;
myObject
    .setMember1("string value")
    .setMember2(4.0f)
    .setMember3(-1);
Run Code Online (Sandbox Code Playgroud)

显然,这是通过让setter返回MyClass&type来实现的; 类似return*this.我喜欢这段代码的样子,但我看不太多.当发生这种情况时,我通常会怀疑为什么.

那么,这是一种不好的做法吗?像这样做的一些含义是什么?

Sam*_*ler 6

这有时被称为命名参数成语或方法链.这不是坏习惯,它有助于提高可读性.考虑一下这个从C++ FAQ中解脱出来的例子

File f = OpenFile("foo.txt")
            .readonly()
            .createIfNotExist()
            .appendWhenWriting()
            .blockSize(1024)
            .unbuffered()
            .exclusiveAccess();
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用OpenFile方法的位置参数,要求程序员记住每个参数的位置.

  • 我或许应该扩展一下downvote评论.命名参数成语很好:它产生**单阶段构造**,在构造函数成功执行后,对象完全初始化为工作类不变量.OP的代码使用**两阶段构造**或**多阶段构造**,这是坏的,因为在C++构造函数成功完成后,您仍然没有现成的对象.Bjarne在TCPPPL的附录中写了这篇文章,从他的网站上以PDF格式提供.此外,OP的代码无情地暴露了属性.所以,NPI =好,OP的代码=坏. (5认同)
  • 或者使用Boost参数,它看起来更加光滑. (3认同)

Jer*_*fin 6

有些人称之为流畅的编程(或流畅的界面).其他人称之为混乱.

倾向于后一阵营.特别是,我的经验是,在许多情况下,以这种方式编写代码的人依赖于"流畅的界面"来进行相当多的初始化对象.换句话说,尽管有伪装,它仍然是两步初始化.同样地,尽管在许多情况下它可能是可以避免的,但它似乎经常导致相当多的应该完全私有的类通过操纵器可以公开修改.

我个人比较喜欢的对象是创建后不可变的.这显然并非总是可行,在某些情况下,你甚至不能非常接近.尽管如此,你对外部操纵开放的对象的内部结构越多,你对该对象保持连贯状态的肯定程度就越低(通常,你需要做的工作就越多,以维持一致的状态).