首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用C++ () .chain().method() vers ->chained(0->method() )链接成员函数

使用C++ () .chain().method() vers ->chained(0->method() )链接成员函数
EN

Stack Overflow用户
提问于 2012-12-20 03:44:12
回答 2查看 3.9K关注 0票数 4

问题的简短版本

我寻求关于是否使用./*this与->/this,即C++ (*this).chained().methods()与this->chained()->methods()的建议。

顺便说一下,目前我看到的大多数页面都推荐[C++ (*this).chained().methods()]。

我只是在想,因为你做不到

My_Class object.chained().methods();

(顺便说一句,我还没有在第一节中测试过这些例子。我在第二节中提供了测试的例子)。

你必须做

My_Class对象; object.chained().methods();

这是一条烦人的额外线路

或者你可以

My_Class object = My_Class().object.chained().methods();

它需要一个值副本--如果构造函数具有副作用(比如注册对象实例),则不可接受--就像许多旋钮库所做的那样。

或者你可以

My_Class* object_ptr =*(新My_Class).object.chained().methods();

这是可行的,但需要这个恼人的*(ptr)

或者你可以

My_Class* object_ptr =(新My_Class)->object.chained()->methods();

这就更好了。

我想你能做到

My_Class& object_ref(My_Class().chained().methods());

我不知道我是怎么想的。

顺便说一下,我这里不需要调试帮助。

我一直在编写这样的代码,我只是为了清楚地提供示例。

我正在寻求样式建议,因为有几种方法可以对其进行编码,而且我使用了不同的库,它们以相反的方式完成。

把它们混在一起是很丑的:

代码语言:javascript
复制
  My_Object_with_Setters* object_ptr2 = &((new My_Object_with_Setters)->set_R1(1).set_P1(2)->set_R1(3))

 My_Object().method_returning_ptr()->method_returning_ref();

也许没那么糟..。但这肯定会让人困惑。

当我遇到使用混合.chained()->methods()的两个不同库的代码时,我有时希望有后缀地址和取消引用操作符。

My_Object* mptr = My_Object() .method_returning_ptr() -> method_returning_ref ->&

更完整的例子

Setter函数

我经常把这个成语和setter函数结合使用。

代码语言:javascript
复制
class My_Object_with_Setters {
public:
  static int count;
  int value;
public:
  My_Object_with_Setters() {
    ++count;
    value = 0;
  }
public:
  std::ostream& print_to_stream(std::ostream& ostr) const {
    ostr << "(" << this->count << "," << this->value << ")";
    return ostr;
  }
  friend std::ostream&
  operator<< (
    std::ostream& ostr,
    const My_Object_with_Setters& obj ) {
    return obj.print_to_stream(ostr);
  }

public:
  My_Object_with_Setters& set_R1(int val) {
    this->value = val;
    std::cout << "set_R1: " << *this << "\n";
    return *this;
  }
  My_Object_with_Setters& set_R2(int val) {
    this->value = val;
    std::cout << "set_R2: " << *this << "\n";
    return *this;
  }
public:
  My_Object_with_Setters* set_P1(int val) {
    this->value = val;
    std::cout << "set_P1: " << *this << "\n";
    return this;
  }
  My_Object_with_Setters* set_P2(int val) {
    this->value = val;
    std::cout << "set_P2: " << *this << "\n";
    return this;
  }
public:
  My_Object_with_Setters set_V1(int val) {
    this->value = val;
    std::cout << "set_V1: " << *this << "\n";
    My_Object_with_Setters retval;
    retval = *this;     // kluge to force new object
    return retval;
  }
  My_Object_with_Setters set_V2(int val) {
    this->value = val;
    std::cout << "set_V2: " << *this << "\n";
    My_Object_with_Setters retval;
    retval = *this;     // kluge to force new object
    return retval;
  }
};

int My_Object_with_Setters::count = 0;  // clas static, distinguishes instances

void test_My_Object_with_Setters()
{
  std::cout << "cascading ref, ref, copy, copy, ref, ref\n";
  My_Object_with_Setters object;
  object.set_R1(1).set_R2(2).set_V1(11).set_V2(12).set_R1(101).set_R2(102);

  std::cout << "cascading ptr, ptr, ptr, ptr\n";
  My_Object_with_Setters* object_ptr = (new My_Object_with_Setters)->set_P1(1)->set_P2(2)->set_P1(11)->set_P2(12);

  std::cout << "cascading &address-of, ptr, ptr\n";
  (&object)->set_P1(1)->set_P2(2);

  std::cout << "cascading new ptr ref ptr ref\n";
  My_Object_with_Setters* object_ptr2 = &(*(new My_Object_with_Setters)->set_R1(1).set_P1(2)).set_R1(3);

}

测试输出:

代码语言:javascript
复制
cascading ref, ref, copy, copy, ref, ref
set_R1: (1,1)
set_R2: (1,2)
set_V1: (1,11)
set_V2: (2,12)
set_R1: (3,101)
set_R2: (3,102)
cascading ptr, ptr, ptr, ptr
set_P1: (4,1)
set_P2: (4,2)
set_P1: (4,11)
set_P2: (4,12)
cascading &address-of, ptr, ptr
set_P1: (4,1)
set_P2: (4,2)
cascading new ptr ref ptr ref
set_R1: (5,1)
set_P1: (5,2)
set_R1: (5,3)

通用示例

代码语言:javascript
复制
class My_Object {
public:
  static int count;
public:
  My_Object() {
    ++count;
  }
public:
  My_Object& method1_returning_ref_to_current_object() {
    std::cout << count << ": method1_returning_ref_to_current_object\n";
    return *this;
  }
  My_Object& method2_returning_ref_to_current_object() {
    std::cout << count << ": method2_returning_ref_to_current_object\n";
    return *this;
  }
public:
  My_Object* method1_returning_ptr_to_current_object() {
    std::cout << count << ": method1_returning_ptr_to_current_object\n";
    return this;
  }
  My_Object* method2_returning_ptr_to_current_object() {
    std::cout << count << ": method2_returning_ptr_to_current_object\n";
    return this;
  }
public:
  My_Object method1_returning_value_copy_of_current_object() {
    std::cout << count << ": method1_returning_value_copy_of_current_object\n";
    My_Object retval;
    return retval;
  }
  My_Object method2_returning_value_copy_of_current_object() {
    std::cout << count << ": method2_returning_value_copy_of_current_object\n";
    My_Object retval;
    return *this;
  }
};

int My_Object::count = 0;   // clas static, distinguishes instances

void test_My_Object()
{
  std::cout << "cascading ref, ref, copy, copy, ref, ref\n";
  My_Object object;
  object
   .method1_returning_ref_to_current_object()
   .method2_returning_ref_to_current_object()
   .method1_returning_value_copy_of_current_object()
   .method2_returning_value_copy_of_current_object()
   .method1_returning_ref_to_current_object()
   .method2_returning_ref_to_current_object()
   ;

  std::cout << "cascading ptr, ptr, ptr, ptr\n";
  My_Object* object_ptr = new My_Object;
  object_ptr
   ->method1_returning_ptr_to_current_object()
   ->method2_returning_ptr_to_current_object()
   ->method1_returning_ptr_to_current_object()
   ->method2_returning_ptr_to_current_object()
   ;

  std::cout << "cascading &address-of, ptr, ptr\n";
  (&object)
   ->method1_returning_ptr_to_current_object()
   ->method2_returning_ptr_to_current_object()
   ;

  std::cout << "cascading new ptr ref ptr ref\n";
  My_Object* object_ptr2
   = (&(*(new My_Object)
    ->method1_returning_ptr_to_current_object())
    .method2_returning_ref_to_current_object())
   ;

}

测试输出

代码语言:javascript
复制
cascading ref, ref, copy, copy, ref, ref
1: method1_returning_ref_to_current_object
1: method2_returning_ref_to_current_object
1: method1_returning_value_copy_of_current_object
2: method2_returning_value_copy_of_current_object
3: method1_returning_ref_to_current_object
3: method2_returning_ref_to_current_object
cascading ptr, ptr, ptr, ptr
4: method1_returning_ptr_to_current_object
4: method2_returning_ptr_to_current_object
4: method1_returning_ptr_to_current_object
4: method2_returning_ptr_to_current_object
cascading &address-of, ptr, ptr
4: method1_returning_ptr_to_current_object
4: method2_returning_ptr_to_current_object
cascading new ptr ref ptr ref
5: method1_returning_ptr_to_current_object
5: method2_returning_ref_to_current_object

顺便说一下,我这里不需要调试帮助。我提供这些例子只是为了清楚。

我在寻求时尚的建议。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-01-18 22:55:05

每个人都有自己的风格,就像你说的,只有当你开始把它们混合起来时,它才会变得很烦人。

就我个人而言,我只从函数返回指针,如果它可能是0;this永远不是0,所以我总是返回*this (即引用),从而使用.链接。

至于它的价值,我也非常努力地使默认构造函数便宜一些,部分原因是在很多情况下,首先使用默认构造,然后再分配是很方便的。

票数 6
EN

Stack Overflow用户

发布于 2012-12-20 05:35:53

我能给出的最好的答案是“始终如一”。如果您的其余代码使用this->,请使用该代码。如果它使用(*this).,请使用它。

因为区别仅仅是语法上的糖,你最好的指导就是你使用的其他代码。我认识的大多数人更喜欢->语法,但是如果您要集成到现有的库中,您可能想跳过它。

就我个人而言,我会使用额外的初始化方法。它对我来说是最干净的,一行在堆栈上构造对象,其他行根据需要调用方法。如果您只需要这些方法,并且它们不依赖于实际的对象,那么我会让它们一起静态和跳过对象创建。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13964970

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档