4

質問の短いバージョン

./*thisと->/thisのどちらを使用するか、つまりC ++(* this).chained()。methods()とthis-> chained()-> methods()のどちらを使用するかについてアドバイスを求めています。

ちなみに、現時点で私が見たほとんどのページは[[C ++(* this).chained()。methods()]]を推奨しています。

あなたができないので、私はただ疑問に思っていました

My_Class object.chained()。methods();

(ちなみに、私はこの最初のセクションの例をテストしていません。2番目のセクションでテストされた例を提供します。)

あなたがしなければならない

My_Classオブジェクト;
object.chained()。methods();

これは迷惑な余分な行です

またはあなたはすることができます

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

これには値のコピーが必要です-コンストラクターにオブジェクトインスタンスの登録などの副作用がある場合は受け入れられません-多くのKnobsライブラリのように

またはあなたはすることができます

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

これは機能しますが、面倒な*(ptr)が必要です

またはあなたはすることができます

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

これは少し良いです。

私はあなたができると思います

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

それについてどう思うかわかりません。

ちなみに、ここではデバッグのヘルプは必要ありません。
わかりやすくするためだけに例を示しますが、私は常にこのようなものをコーディングしています。

私はスタイルのアドバイスを求めています。なぜなら、それをコーディングする方法はいくつかあり、反対の方法でそれを行うさまざまなライブラリを使用したからです。

そしてそれらを混ぜることは醜いです:

  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()を使用して2つの異なるライブラリを使用するコードに遭遇したとき、後置アドレス演算子と逆参照演算子を使用できるようにしたい場合があります。

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

より完全な例

セッター機能

私はほとんどの場合、このイディオムをセッター関数で使用します

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);

}

テスト出力:

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)

一般的な例

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())
   ;

}

テスト出力

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

ちなみに、ここではデバッグのヘルプは必要ありません。わかりやすくするためにのみ例を示します。

スタイルのアドバイスを求めています。

4

2 に答える 2

6

誰もが独自のスタイルを持っています。あなたが言うように、あなたがそれらを混ぜ始めたときだけそれは本当に迷惑になります。

個人的には、関数が0の場合にのみ、関数からポインターを返します。thisは決して0ではないので、私は常に*this(つまり参照)を返し、したがって。でチェーンし.ます。

また、デフォルトのコンストラクターを安価にするために、私は本当に一生懸命努力しています。これは、最初にデフォルトのコンストラクターを作成してから割り当てると便利な場合が非常に多いためです。

于 2013-01-18T22:55:05.270 に答える
2

私ができる最善の答えは「一貫している」ことです。コードの残りの部分でを使用する場合は、それをthis->使用します。を使用する場合は、それを(*this).使用してください。

違いはシンタックスシュガーだけなので、最善のガイダンスは、使用する他のコードが行うことです。私が知っているほとんどの人は->構文を好むでしょうが、既存のライブラリに統合する場合は、それをスキップすることをお勧めします。

個人的には、初期化の余分な行の方法を使用します。それは私にとって最もクリーンなものを読み取り、1行はスタック上にオブジェクトを構築し、他の行は必要に応じてメソッドを呼び出します。メソッドのみが必要で、実際のオブジェクトに依存しない場合は、メソッドを静的にして、オブジェクトの作成をすべてスキップします。

于 2012-12-20T05:35:53.013 に答える