2

私はそれを見るまで、これが C++ で可能であることを知りませんでした。AddAttribute()、AddTraceSource() などは、クラス TypeId のメンバー関数です。

TypeId
Sender::GetTypeId (void)
{
static TypeId tid = TypeId ("Sender")
.SetParent<Application> () /*Member function of TypeId*/
.AddConstructor<Sender> () 
.AddAttribute ("PacketSize") 
.AddAttribute ("Destination") 
.AddTraceSource ("Tx")
;
return tid;
}

これが C++ でできるとは知りませんでした。誰かがこのトピック (オブジェクト作成中に複数のメンバー関数を呼び出す) にもっと光を当てることができますか? スクリプトでこれを実行できることはわかっています。しかし、C ++では?ファイルの拡張子は *.cc です。私の質問が素朴で申し訳ありませんが、C ++のいくつかの章を読み逃したことが判明しました?!

4

5 に答える 5

3

このトリックの鍵は、これらすべてのメンバー関数が呼び出し元のオブジェクトへの参照を返すことです。そう:

TypeId("Sender")

これはコンストラクターを呼び出し、一時オブジェクトを返します。それで:

.SetParent<Application>()

SetParent<>これにより、一時TypeIdオブジェクトのメンバー関数が呼び出されます。おそらく次のような署名があります。

template<typename T>
TypeId & SetParent();

そのため、呼び出されたオブジェクト ( *this) への参照を返します。これにより、 への次の呼び出しがAddConstructor<Sender>()可能になります。その関数は、チェーン内の他の関数と同様に、同様のシグネチャを持っている可能性があります。

于 2013-11-15T02:07:30.763 に答える
1

これは、ビルダー パターンとして知られています。

これはある種の特別な言語機能ではありません。代わりに、関数は呼び出されたオブジェクトへの参照を返しています。

これらの関数はそれぞれ の戻り値の型を持ち、 を返すTypeId&だけ*thisなので、呼び出し元は 1 つのステートメントで多くの関数を連鎖させることができます。

于 2013-11-15T02:07:09.027 に答える
1

表示されているのは、ビルダー パターンと呼ばれるデザイン パターンです。

何かを設定する各メソッドは、内部状態を変更してから への参照を返すため*this、同じオブジェクトに対してさらに呼び出しを行うことができます。

最後に、概念的には、最後の呼び出しで返されたオブジェクトを に格納しAddTraceSourceますtid。前述の関数はすべて同じインスタンスへの参照を返したため、コンストラクターが最初に作成した同じインスタンスを格納します。

したがって、SetParentおそらく次の行に沿って実装されます

template <typename T>
TypeId& TypeId::SetParent()
{
    this->parent = T();
    return *this;
}

他の場所でもこのパターンに遭遇したことがあるでしょう。Iostream は、<<and>>演算子を使用してこれを行います。

std::cout << "Here's one call to the overloaded operator."
          << " Here's another."
          << " Take a look at the signature of operator<< when you get chance."
          << std::endl;
于 2013-11-15T02:14:31.080 に答える
1

関数がオブジェクトへの参照を返すまで、必要なときにいつでも関数を任意の長いチェーンにチェーンできます。operator <<これは、ストリームでオーバーロードされた を呼び出すときに発生することstd::coutであり、同じ方法でクラスでもコーディングできます。

基本的な考え方は、クラスの設計にあります。すべての関数で returninvoidする代わりに、関数を呼び出したオブジェクトへの参照を返します。

class sample{
   sample& fun1(){cout << "fun1" << endl; return *this;};
   sample& fun2(int number){cout << "fun2("<<number<")\n"; return *this;};
   sample& fun3(){cout << "fun3" << endl; return *this;};
};

これで、次のような関数を呼び出すことができます:

sample yourObject;
yourObject.fun1().fun2(5).fun3().fun1().fun2(12);
于 2013-11-15T02:05:08.953 に答える
0

関数をチェーンすることは完全に可能です:

//foo() returns string
auto size = foo().length();

&TypeIdこれらの関数は、それぞれが( *this) 型を返す場合に連鎖できます。

于 2013-11-15T02:07:55.830 に答える