26

これは、依存性注入を扱っていたMiško Hevery のGoogle トークの 1 つのコメントで私が尋ねた質問でもありますが、コメントに埋もれてしまいました。

依存関係を一緒に配線するファクトリー/ビルダーのステップがC++でどのように機能するのだろうか。

つまり、B に依存するクラス A があります。ビルダーは B をヒープに割り当て、A のコンストラクターで B にポインターを渡し、同時にヒープに割り当て、A へのポインターを返します。

後片付けは誰がするの?完成後はビルダーに片付けてもらってもいいですか?話の中で、ビルダーは同じ寿命を持つことが期待されるオブジェクトをセットアップするか、少なくとも依存関係の寿命が長くなる必要があると述べているため、これは正しい方法のようです (私もそれについて質問があります)。コードでの意味:

class builder {
public:
    builder() :
        m_ClassA(NULL),m_ClassB(NULL) {
    }
    ~builder() {
        if (m_ClassB) {
            delete m_ClassB;
        }
        if (m_ClassA) {
            delete m_ClassA;
        }
    }
    ClassA *build() {
        m_ClassB = new class B;
        m_ClassA = new class A(m_ClassB);
        return m_ClassA;
    }
};

ここで、注入先のオブジェクトの有効期間よりも長く続くことが予想される依存関係がある場合 (ClassC がその依存関係であるとします)、ビルド メソッドを次のように変更する必要があることを理解しています。

ClassA *builder::build(ClassC *classC) {
    m_ClassB = new class B;
    m_ClassA = new class A(m_ClassB, classC);
    return m_ClassA;
}

あなたの好みのアプローチは何ですか?

4

8 に答える 8

13

この講演は、Javaと依存性注入についてです。

C ++では、RAWポインタを渡さないようにしています。これは、RAWポインタに所有権のセマンティクスが関連付けられていないためです。あなたが所有権を持っていない場合、私たちは誰がオブジェクトをクリーンアップする責任があるのか​​わかりません。

ほとんどの場合、依存性注入はC++の参照を介して行われることがわかりました。
ポインタを使用する必要があるまれなケースでは、所有権の管理方法に応じて、ポインタをstd ::unique_ptr<>またはstd::shared_ptr<>でラップします。
C ++ 11機能を使用できない場合は、std ::auto_ptr<>またはboost::shared_ptr<>を使用してください。

また、C ++とJavaのプログラミングスタイルは非常に多様化しており、一方の言語のスタイルをもう一方の言語に適用すると、必然的に災害につながることも指摘しておきます。

于 2008-12-09T14:47:20.957 に答える
9

テンプレートを使用した C++ での DI は興味深いものです。

http://adam.younglogic.com/?p=146

Java DI を文字通り C++ に翻訳しすぎないように、作者は正しい動きをしていると思います。読む価値があります。

于 2009-12-23T01:08:02.290 に答える
6

最近、DI バグに悩まされています。多くの複雑な問題、特に自動化された部分が解決されると思います。かなりの C++ の方法で DI を使用できるようにするプロトタイプを作成しました。または、少なくともそう思います。ここでコード例を見ることができます: http://codepad.org/GpOujZ79

明らかに欠けているもの: スコーピングなし、実装へのインターフェースのバインディングなし。後者は簡単に解決できますが、前者はわかりません。

ここに誰かがコードについて意見を持っていれば、私は感謝しています。

于 2010-05-10T16:39:21.867 に答える
3

RAII を使用します。

生のポインターを誰かに渡すことは、所有権を渡すことと同じです。それがやりたくない場合は、問題のオブジェクトをクリーンアップする方法も知っているある種のファサードをそれらに与える必要があります。

shared_ptr<> はこれを行うことができます。そのコンストラクターの 2 番目の引数は、オブジェクトを削除する方法を知っている関数オブジェクトにすることができます。

于 2008-12-09T16:40:16.877 に答える
2

私自身の経験に基づくと、明確な所有権のルールを設定するのが最善です。小さな具体的なオブジェクトの場合、相互依存を避けるために直接コピーを使用するのが最善です。

相互依存が避けられず、明確な所有権がない場合があります。たとえば、(m) A インスタンスは (n) B インスタンスを所有し、特定の B インスタンスは複数の As によって所有される場合があります。この場合、最善の方法は、COM 参照カウントと同様に、B に参照カウントを適用することです。B* を取得する関数は、最初に参照カウントを増やし、所有を解放するときにそれを減らす必要があります。

また、boost::shared_ptr は新しい型を作成するため、使用も避けています (shared_ptr と B* は 2 つの異なる型になります)。メソッドを追加すると、頭痛の種が増えることがわかりました。

于 2009-12-23T16:04:06.073 に答える
2

通常、C++ では、適切に処理を行った場合、ほとんどの場合、デストラクタを記述する必要はまったくありません。物事を自動的に削除するには、スマート ポインターを使用する必要があります。ビルダーは、ClassA および ClassB インスタンスの所有者のようには見えません。スマート ポインターを使用したくない場合は、オブジェクトの有効期間とその所有者について考える必要があります。

于 2008-12-09T15:14:02.387 に答える
2

所有権の問題を完全に解決しないと、事態は複雑になります。依存関係が注入されたオブジェクトよりも長く存続する可能性があるかどうかを実装で決定する必要があります。

個人的にはノーと言います。依存関係が注入されたオブジェクトは後でクリーンアップされます。ビルダーを介して実行しようとすると、依存関係とそれが注入されるオブジェクトの両方よりもビルダーが長く存続する必要があります。私の意見では、これは解決するよりも多くの問題を引き起こします。依存性注入による構築が完了した後、ビルダーはそれ以上有用な目的を果たさないからです。

于 2008-12-09T14:33:02.983 に答える
1

FFEAD Dependency Injectionも確認できます。これは、Spring for JAVA のラインで DI を提供し、邪魔にならない方法で物事を処理します。また、組み込みのAJAX サポート、リフレクション、シリアル化、C++ インタープリター、C++ 用のビジネス コンポーネント、ORM、メッセージング、Web サービス、スレッド プール、およびこれらすべての機能をサポートするアプリケーション サーバーなど、他にも多くの重要な機能があります。

于 2010-08-10T07:31:42.020 に答える