2016-05-05 63 views
1

コンテキスト:最近のC++で集約を実装する正しい方法は何ですか?

私が集約を必要とする状況が発生するのが一般的である:オブジェクトは、それを所有することなく、別のオブジェクトを使用しています。つまり、いくつかのメインモジュールは、他の人のためにオブジェクトを作成して共有します。

しかし、これまで実装した正しい方法は見つかりませんでした。

前研究:

1)C-様ポインタ: 共有オブジェクトがポインタとして提供されます。問題は、作成、共有、および削除の順序を正しく管理することはプログラマが責任を持って行うことであり、手軽にポインタを運ぶことができます。

int main() 
{ 
    A a; 
    B b(&a); 
    return 0; 
} 

2)弱いポインタ: 共有/弱いポインタはダングリングポインタの問題を解決するための使用。主な問題は、スタックオブジェクトを使用しないようにすることです。また、最悪の場合には(カーネル/低レベルのコード)は不可能であるという例外的なケースでは、議論のトピックが最良のケースで中継されます。

int main() 
{ 
    std::shared_ptr<A> a(new A()); 
    std::weak_ptr<A> wa = a; // optional, but required to show the weak_ptr use 
    B b(wa); 
} 

3)共有のポインタ: のみ共有ポインタを使用するには、以下同じ問題を抱えている(2)が、さらにAの所有権が不明です:いくつかの設計ガイドラインを破ること。

4)オブジェクト参照: オブジェクトへの参照を共有すると、問題が解決され、おそらく最も簡単な解決策です。一方、それは集約されたオブジェクトをコンストラクタに渡すよう強制し、代入演算子を回避し、一般にデザインを制限します。

int main() 
{ 
    A a; 
    B(a); 
} 

5)集計しないで、引数として渡すだけです。 可能であれば、これによって一部の機能のパラメータ数が大幅に増加します。それは、私の意見では、あまりにも多くの複雑さです。

6)シングルトンパターン シングルトンを使用すると、複数のモジュールから1つのオブジェクトにアクセスできます。しかし、これは1つのインスタンスを共有することしか許さず、いくつかの設計ガイドラインに反する。

質問:

現代のC++での集約を実装するための正しい方法は何ですか?

理想の目標は次のようになります。

  • コードを維持し、エラーを回避するのは簡単ください。
  • さまざまな方法で使用する柔軟性(例:スタック/ヒープ)
  • 余計な複雑さやあいまいなコードではありません。
+3

質問に答えるのに十分な情報がないと思います。これは、共有しているよりも多くのアーキテクチャ上の考慮事項に依存します。これらは、他のものに応じて有効なオプションですが、 "現代的な" C++では、可能であれば生ポインタを使用したくない場合がほとんどです(ほとんどの場合、 'new'を使う必要はありません) – johnbakers

+2

ありません。回答。特定の問題を解決するための最良の設計を選んでください。 –

+0

BはなぜAを所有していないのですか?ヒープを再利用するためのカスタムガベージコレクタがありますか? BはAよりも寿命が長いですか? – vegi

答えて

2

多くのコメント者が指摘したように、あなたの問題を解決する方法はありません。しかし、このようなことについては、C++のデザインパターンを生きている人が長らく議論してきました。(コメント投稿者の1人の提案を含む、template <class T> using non_owning_ptr<T> = T*を含む)ぶら下がりのポインタのよりよい取り扱いに関する素晴らしい議論のために、私はBjarne StroustrupのtalkをC++のコアルールとガイドライン、特にリンクから始まるセグメントについて提案します。 Herb Sutterのフォローアップtalkもこの点で有用であり、これらの規則を実施するための静的解析ツールに関するアイデアを紹介しています。

私は、これはあなたが探している魔法の解決策ではないですけど、それは価値があるもののために、それは私が来た私より人が賢くおよびC++での方法より経験豊富なソリューションであると思われますと一緒に。私は正に、Bjarne Stroustrupがこれらのルールとガイドラインについ最近のほとんどの時間を費やした理由です。これらの種類のものに対する完璧なソリューションはC++自体には存在しませんが、いくつかの制約があるため、もっと近づくことができます。

1

私は集約が必要です:オブジェクトは、所有していない別のオブジェクトを使用します。

これは私がよく知っている「集約」の定義ではありません。しかし、この投稿の目的のために、私はそれを使用します。

C++型システムでオブジェクトを所有せずにオブジェクトにアクセスする能力を表現する方法はありません。このアイデアを表現するために、この関係を実装するにはあまりにも多くの方法があります。

インスタンスBにはアクセスできますが、Bを所有していないインスタンスAがあるとしましょう。この2つのインスタンスの関係をどのように定義しますか?この関係は、Aが最初に知らされずにBが破壊された場合、安全ではありません。それで、どうやってそれを保証するのですか?

文字通り数多くの方法があります。おそらくBはshared_ptrに保持されており、したがってAはweak_ptrにその参照を保持することができ、Bがなくなったときに通知される可能性があります。たぶん、AとBの両方を所有する特定のオブジェクトCがあり、これを保証します。多分、コードの一般的な構造は、BがAの前に破壊されることを不可能にするかもしれない。おそらく、B自身がAにリンクし、そのデストラクタでAに通知するかも知れないかもしれない。コードが壊れやすいかもしれませんが、コードを書く人はすべて、AがBを失うことがないように注意します。

「それを実装する正しい方法」はありません。もの。それは可能な限りの関係の無数です。これらの関係は必ずしも間違っているわけではありません。それらのほとんどは必ずしも悪いコードではありません。それらは単に型間の暗黙の関係です。

Library Fundamentals v1には、observer_ptr<T>が含まれています。これは単なるポインタラッパーです。それは所有権の意味を伝えません。ただし、コアC++ガイドラインでは、raw pointers be used for most of these use-without-ownership relationsを推奨しています。代わりに何かを所有するポインタにowner<T>という注釈を付けることを提案します。

+0

https://en.wikipedia.org/wiki/Object_composition#Aggregation 私の単一行の説明があまりにも単純すぎるかもしれません。 これはあなたが慣れ親しんだ定義でない場合、集約のコンセプトに私を紹介できますか? 質問に関連して、はい、何百もの集計状況があります。そのため、私は「正しい」方法を求めています。同じように、エラーは非常に複雑なトピックですが、私たちはそれらを管理するいくつかの点で合意しています(例外、エラーリターンなど) observer_ptr/ownerテンプレートを見ていきます。ありがとうございました –

+0

@AdrianMaire: "*何百もの集計状況がありますので、私は"正しい "方法を求めています* *"あなたは私のポイントを見逃したようです。このような状況は何百もあるので、「正しい方法」はありません。それはできません。 –

関連する問題