8

あまり一般的ではない C++ のイディオムがありますが、これは私が過去に何度か使用してうまくいきました。それを説明するために一般的に使用されている名前があるかどうかを思い出せないようです。

mixinsCRTP、およびtype-erasureに多少関連していますが、特にこれらのいずれかではありません。

クラスに実装を追加したいが、それをクラスまたはその派生元のクラスに配置したくない場合に、問題が発生します。この理由の 1 つは、クラスが継承階層の一部であり、実装が 1 回だけ発生する可能性があるためです。

とりあえず、階層に具体的な非リーフ クラスを含める必要があるかどうか、場合によっては仮想継承がオプションになるかどうかなどの問題はさておき、次から派生するテンプレート クラスで実装を提供する 1 つのソリューションを知っています。そのテンプレート パラメータ。これにより、インスタンスを作成するときにテンプレートを使用できますが、そのオブジェクトのベースの 1 つへのポインターまたは参照によってのみオブジェクトを使用できます (大まかな意味での型消去の出番です)。

例として、侵入的な参照カウントがある場合があります。すべてのクラスは ref カウント インターフェイスから派生しますが、ref カウント自体と ref カウント メソッドの実装を 1 回だけ表示する必要があるため、それらを派生テンプレートに入れます。それを呼び出しましょうImplementsRC<T>。これで、次のようにインスタンスを作成できます。

ConcreteClass* concrete = new ImplementsRC<ConcreteClass>();

複数のテンプレート化されたオーバーロードなどで形成されたコンストラクターの転送などについて詳しく説明しています。

それで、イディオムが何であるかを明確にしたことを願っています。私の質問に戻ります - このイディオムに受け入れられている、または少なくとも一般的に使用されている名前はありますか?

4

9 に答える 9

3

面白いアイデアです。ただし、ここではすでに確立されているパターンの名前を示すつもりはありません。それどころか、まだパターンがないと思う理由を(ある程度)説明します。

それは何をするためのものか?

これは、恐ろしいダイヤモンドの継承を回避するための非常に優れた方法です。

この方法の目的については明らかに混乱があるので、なぜこれがその目的であると思うのかを詳しく説明します。

class RefCounted
{
  virtual void addReference() = 0;
  virtual void removeReference() = 0;
};

class B: public RefCounted {};
class C: public RefCounted {};

class Diamond: public B, public C {};

さて、ここで問題があります。このクラスにrightの実装を配置するRefCountedと、インターフェイスではなく基本クラスになるため、仮想継承を使用する必要があります。そうしないと、データメンバーが複製されます(BとCの両方に存在します)。

したがって、アイデアは実装を最後の瞬間まで延期することです。

利点:

  • BまたはCの使用を推測する必要はありません。仮想継承は不要です。
  • 実装を追加するのを忘れた場合、コンパイラは適切に通知するので、それについて心配する必要はありません。

不便:

  • クライアントに負担をかけます。特に、1つのオブジェクトがさまざまなインターフェイスを実装する可能性があるため、オブジェクトを作成するためのファクトリが必要です。これは、テンプレートメタプログラミング(多かれ少なかれ)で自動化される場合もあれば、クラスの作成者によって簡単に提供される場合もあることに注意してください。

提供例:

// d.h
class D: public B, public C
{
public:
  typedef ImplementRC<D> concrete_type;
  static concrete_type Build(int, int); // Named Constructor idiom

private:
  D(int,int);
}; // class D

// main.cpp
D::concrete_type myD = D::Build(1,2);

それで、名前は何ですか?

これにぴったり合うものは思いつかない。BridgeとDecoratorについては言及されていますが、これは非常に特殊であり、実際にはそれほどOO指向ではありません(たとえば、多重継承がないため、Javaでは発生しません)。したがって、この用語が見つかるとは思えません。 GoFの本で。

また、CRTP(ベースはその派生クラスを認識している)に一種のループがあり、ここでは発生しないため、実際にはCRTPではありません>実際には厳密に線形です!

そして、それは確かにPimplイディオムではありません。これは、実装用のテンプレートを使用している間、実装をクライアントから隠すことを提案します。(ただし、テンプレートはPimplを内部詳細として使用できます)

なんとかしてタイトルを模倣するJustInTime Implementationのjitiを謙虚に提案しますが、ここでの派生は目標ではなく単なるツールであると私は思います。

とにかく面白いアイデア。

于 2009-12-17T18:18:57.540 に答える
1

Decorator パターンをお探し ですか?

基本的に、デコレータは別のオブジェクトを囲み、特定のメソッドの機能を拡張するオブジェクトです。メソッドの呼び出しは、囲まれたメソッドに転送されます。

于 2009-12-17T13:49:28.177 に答える
1

これはミックスインです

于 2009-12-17T13:55:48.323 に答える
1

これに名前があるかどうかはわかりません.gfが提案したように、橋のパターンに少し似ています. これは、機能を基本クラスにフックするようなものです。

私はこれに新しい名前を提案します。ポン引きイディオムです。あなたがあなたの基本クラスをポン引きしているように;)

于 2009-12-17T12:49:09.223 に答える
1

Bruce Eckel ( http://www.artima.com/weblogs/viewpost.jsp?thread=132988 )のように、私は間違いなくこれを mixin と考えています。

私の意見では、これを mixin にしている理由の 1 つは、それがまだ単一の継承であることです。これは、MI を使用して同様のことを達成することとは異なります。

于 2009-12-17T20:45:46.623 に答える
1

参照カウントの例を見ると、IUnknown の実装を提供するために ATL に含まれる数少ないテンプレート クラスの 1 つである CComObject<> を調べると、喜びが得られるかもしれません。また、ポリシー クラスを使用して動作を変更します。当然のことながら、CComObjectの概念についてGoogle で調べようとする S/N 比は非常に低いです。この MSDN の記事では、検索に役立つ「キーワード」がいくつか提供される場合があります。

http://msdn.microsoft.com/en-us/library/c43h4867(VS.80).aspx

[注意: 明確にするために、彼がCComObjectを使用していると言っているのではありません。同じ概念の別の一般的な例であり、パターンの本や記事で参照されている可能性があることを示唆しています]

于 2009-12-18T13:54:15.333 に答える
0

よくわかりませんが、「空のメンバーのC ++最適化」ですか?

この種の動作は、クラス テンプレートプライベート継承を使用して実装されます。

Scott Meyer による「Counting Objects in C++」という雑誌記事で説明されています。

于 2009-12-17T13:01:43.820 に答える
0

にきびイディオムのように見えますか?意外な使い方もあるかもしれません。

于 2009-12-17T12:05:12.740 に答える
0

私自身の質問に答えます。狂気の最初の兆候?-いいえ、これより前にいくつかの兆候がありました;-)

とにかく、私が最初に投稿してからかなり時間が経ちましたが、とにかく私は多かれ少なかれ別人です.

mixoverという名前に落ち着いたことがわかりました。これは非常にうまく適合し、より一般的な概念に限定されるのではなく、ミックスインの改良版と見なすことができることがわかりました。

私は最近それらを頻繁に使用しているので、戻ってきてこのスレッドを更新すると思いました.

于 2011-06-10T08:23:36.570 に答える