3

私はユーティリティ クラスのライブラリを作成していますが、その多くはシングルトンです。私は継承を使用してそれらを実装しました:

template <class T>
class Singleton {
    public:
        T& getInstance() {
            if(m_instance == 0) {
                 m_instance = new T;
            }

            return m_instance;
        }
    private:
        static T* m_instance;
};

class SomeClass : public Singleton<SomeClass> {
    public:
        SomeClass() {}
        virtual ~SomeClass() {}

        void doSomething() {;}
};

明らかにこれは単純な例であり、実際のクラスではありません。とにかく、次のようなコードを使用していることがわかります。

SomeClass::getInstance().doSomething();

SomeClass の複数のインスタンスを作成します。これは、ライブラリ (.a) ファイルの外部と内部で使用されていることが原因である可能性があると考えています。たとえば、自分で作成したものではない UI ライブラリを使用しており、これを個別にコンパイルして追加しています。これらの追加のいくつかは、私の .a ライブラリでも使用されているシングルトンを利用しています。

別のコンパイルがこれを引き起こしていますか?他の何か?

この問題を回避する唯一の方法は、必要なシングルトンで初期化する main.cpp ファイルにグローバル オブジェクトを作成することです。次に、すべてのコードが次のような呼び出しでこの共通グローバル オブジェクトにアクセスします。

GlobalObject::getSomeClass().doSomething()

別のシングルトンを作成するたびに、このオブジェクトにメソッドを追加しなければならないのは嫌です。さらに、最初のアクセス方法を使用すると、構文がより明確で親しみやすくなります。

SomeClass::getInstance().doSomething();

ご意見、ご感想等ありましたらお聞かせください。

ありがとう。

4

3 に答える 3

6

問題は、テンプレートが完全にインラインであるため、複数のコンパイル単位でインスタンス化されることです。したがって、テンプレートを使用するすべてのコンパイル ユニットで、(コンパイル ユニットごとに) 1 つのシングルトンを作成することになります。必要なのは、すべてのコンパイル ユニットが同じテンプレートのインスタンス化を参照するように、グローバル リンケージを強制することです。今後の C++ 標準は、extern templateを介してこれをサポートします。今できることは、プロジェクトで自動インスタンス化を無効にし、明示的に使用するテンプレートを手動でインスタンス化することです。このように、任意のコンパイル ユニットでテンプレートを使用すると、明示的なインスタンス化を行う (1 つの) コンパイル ユニットからリンカーによって満たされる実装への不明な参照が生成されます。

于 2009-04-10T23:02:58.217 に答える
1

複数のスレッドが同時に getInstance にアクセスしていますか? これにより、複数のインスタンスが作成される可能性があります。検討:

  1. スレッド 1 は " if (m_instance==0)" を実行し、true を検出します
  2. スレッド 2 は " if (m_instance==0)" を実行し、それが true であることを検出します
  3. スレッド 1 は新しい T を割り当てます
  4. スレッド 2 は新しい T を割り当てます

次に、一方が他方を上書きし、インスタンスのいずれかを返します (コンパイラの最適化などに応じて)。

于 2009-04-10T21:37:22.137 に答える
1

Singleton から作成するすべてのテンプレート クラスは、独自の静的m_instanceメンバーを持つことになります...テンプレートがインスタンス化されると、実際にはテンプレート パラメーターのセットごとに異なるクラスが生成されるため、それらは異なるクラス間で共有されません。継承のやり方から判断すると、これはおそらく、そこから派生するクラスごとに Singleton のインスタンスになることを意味します。おそらくこれがあなたの問題の原因ですか?

于 2009-04-10T21:43:53.697 に答える