2011-07-15 2 views
1

多くの循環依存トピックを読みましたが、そのすべてが宣言に関係しているようです。私は相互に依存するオブジェクトを構築する方法と、私のアプローチで潜在的な落とし穴があるかどうかについて興味を持っています。この単純な例を考えてみましょう:C++循環依存性:コンストラクタはどのように見えるでしょうか?

#include <iostream> 
#include <vector> 
using namespace std; 

class A; //Forward declaration 

class B{ 
    public: 
     B(string name, A* a):myA(a), name(name){ 
      cout << "Works with pointer" << endl; 
     }; 
    private: 
     A* myA; 
     string name; 

}; 

class A{ 
    public: 
     A(){ 
      cout << "Constructing A" << endl; 
      if(bs.empty()) cout << "Vector is empty" << endl; 
      bs.push_back(B("First", this)); 
      cout << "Array has " << bs.size() << " elements." << endl; 
     }; 
    private: 
     std::vector<B> bs; 
}; 


int main() { 
    cout << "Start" << endl; 
    A a; 
    cout << "Ok." << endl; 
    return 0; 
} 

は、私がBA*ポインタを避けるために何ができるものはありますか?

理想的には私は参照を持っていると思いますが、私はB(string name, A& a)Bのコンストラクタを変更してbs.bush_back(B("First", *this));に一backを変更した場合、私はエラーを取得:non-static reference member 'A& B::myA', can't use default assignment operatorを。 See the modified example

私がコンパイラによって合成されたはここには当てはまりません。どのように適切なoperator=のようになりますか?あるいは、間違った方向を一緒にしていますか?あなたが標準コンテナタイプを使用する場合

+0

あなたは円形持ちの場合それを削除して、より多くの回避策を探すべきではありません。 –

+0

ええと、私の(言語にとらわれない)ドメインモデルには循環依存があります。クラス設計レベルで問題を回避する方法はありますか? – sebastiangeiger

答えて

5

は、vectorのようなタイプはコピーコンストラクトアサイナブルする必要があります。あなたの型がポインタメンバーを持っている場合、これらは暗黙的に定義されたコピー代入演算子でうまく動作しますが、参照がリバウンドできないため、参照メンバではそうではありません。

型をコンテナで使用する場合は、ポインタメンバーを使用する方がはるかに簡単です。特定のケースで意味を持つコピー代入演算子を定義できるかどうかは明らかではありませんが、一般的にはそうではありません。

0

ユーザー定義の代入演算子でも参照を使用することはできません。参照が初期化されるとリバウンドできないためです。ここでポインタを使用するのが最も簡単な方法です。

0
この場合

(およびのみこの場合は)、あなたはBテンプレートを作る検討することもでき..

template <typename SomeA> 
class B{ 
    public: 
     B(string name, SomeA& a):myA(a), name(name){ 
      cout << "Works with reference" << endl; 
     }; 
    private: 
     boost::optional<SomeA&> myA; 
     string name; 
}; 

class A{ 
    public: 
     A(){ 
      cout << "Constructing A" << endl; 
      if(bs.empty()) cout << "Vector is empty" << endl; 
      bs.push_back(B<A>("First", *this)); 
      cout << "Array has " << bs.size() << " elements." << endl; 
     }; 
    private: 
     std::vector<B<A> > bs; 
}; 

この提案は、任意のコンテキストなしで、純粋である...

関連する問題