web-dev-qa-db-ja.com

親オブジェクトに到達する方法は?

フィールドとして他のいくつかのオブジェクトを持つ親オブジェクトがあります。親オブジェクトはこれらのフィールドを完全に所有します。これらは親オブジェクトのフィールドとして宣言できます(MyPart part)、直接ではなく、参照として。

私はこれらのフィールドをコンストラクターで初期化したいのですが、場合によっては、親オブジェクトのインスタンスに到達し、そのオブジェクトのメソッドを呼び出す必要があります。生のポインターを使用すると、thisをコンストラクターまたはセッターに渡すだけで済みます。ただし、thisからスマートポインターを作成することは、親オブジェクトがスコープから外れると(コンストラクターがどこに戻るかはわかりません)知らないため、ほとんど不可能であることを発見しました。しかし、私は親オブジェクトのフィールドであることを知っていて、これらの子供たちは確実にそれを超えることはできません。

これまでに想像できる唯一の「クリーン」なアイデアは、構築された親への参照がスマートポインターであるファクトリメソッドでオブジェクトを構築し、次に子を個別に構築し、セッターを使用して親を構成することです。これは本当に最善の方法ですか?

現在、生のポインタをすべてのコストで回避するポリシーがあるので、他にどのようなオプションがありますか?または、そのような場合にそのままのポインタを使用するのが適切ですか?

4
h22

親への参照を使用できます。スケッチとして

class Parent;

class Child {
private: 
    Parent & parent;
public:
    Child(Parent & p) : parent(p) {}
    // other members
};

class Parent
private:
    Child child;
public:
    Parent() : child(*this) {}
    // other members
};

おまけとして、コンパイラはChildなしでParentを構築することを拒否します。さらに進んで、Childを非公開でのみ構築可能にし、フレンドParentにすることができます。

7
Caleth

生のポインタを使用するだけです。これは、ライフサイクルに影響を与えない非所有ポインタです。

そして、あなたが彼らが非ポインター/参照メンバーであると言うので、親ポインターを持っている子は親よりも長く生きることはないので、親はそれらをクリーンアップします。

9
r_ahlskog

フィールドクラスを親クラスに結合しないようにしてください。親にあるがフィールドに必要なデータは、フィールドの関数を呼び出すときに渡すことができます。フィールドの関数によって呼び出される必要がある親の関数は、コールバック関数として渡すことができます(例:std::function)。

クラス間の相互依存関係は、多くの場合、コードの構造が不適切であることを示しています。プログラムの流れはすぐに扱いにくくなり、コードの保守が困難になります。

フィールドが本当に親への参照を必要とする場合、フィールドのコンストラクターが渡されたポインターにアクセスせず、それを格納するだけであれば、thisポインターをフィールドのコンストラクターに(親の初期化リストでも)安全に渡すことができます。

5
D Drmmr