1

これはスタック オーバーフローに関する私の最初の質問なので、優しくしてください。

最初に、私が見たい正確な動作を説明しましょう。C# に精通している場合は、変数を「読み取り専用」として宣言すると、プログラマーがその変数に値を 1 回だけ割り当てることができることをご存知でしょう。変数をさらに変更しようとすると、エラーが発生します。

私が求めていること: 私が定義するすべてのシングルトン クラスを、プログラム内で 1 回だけ予測どおりにインスタンス化できるようにしたいと考えています (詳細は下部にあります)。

私の目標を実現するための私のアプローチは、 extern を使用してシングルトンへのグローバル参照を宣言することです (これは後で選択した時点でインスタンス化します。私が持っているものは、次のようになります。

namespace Global
{
    extern Singleton& mainInstance; // not defined yet, but it will be later!
}

int main()
{
    // now that the program has started, go ahead and create the singleton object
    Singleton& Global::mainInstance = Singleton::GetInstance(); // invalid use of qualified name
    Global::mainInstance = Singleton::GetInstance(); // doesn't work either :( 
}

class Singleton
{
    /* Some details ommited */

    public:
        Singleton& GetInstance()
        {
            static Singleton instance; // exists once for the whole program
            return instance;
        }
}

ただし、これは実際には機能せず、ここからどこに行くべきかわかりません。

私が反対していることについての詳細:

いくつかのサードパーティ プロセスや作成する他のプロセスと通信しながら、ゲーム ロジックを処理するコードに取り組んでいるため、スレッド化について懸念しています。最終的には、何らかの同期を実装して、複数のスレッドが安心して Singleton クラスの情報にアクセスできるようにする必要があります。どのような種類の最適化を行いたいのか、またはスレッド化が正確に何を伴うのかわからないため (それを使用して実際のプロジェクトを実行したことはありません)、シングルトンがインスタンス化されるタイミングを予測可能に制御できることは良いことだと考えていました。

プロセス A がプロセス B を作成し、B には複数のファイルやライブラリに対して分散された複数のシングルトンが含まれているとします。これらのシングルトン オブジェクトがインスタンス化される順序を確実に保証できない場合、それは本当の悪夢になる可能性があります (それらは相互に依存する可能性があり、NULL オブジェクトでメソッドを呼び出すことは一般的に悪いことです)。

C# を使用している場合は readonly キーワードを使用するだけですが、この (コンパイラがサポートする) 動作を C++ で実装する方法はありますか? これも良い考えですか?フィードバックをお寄せいただきありがとうございます。


編集

上記のコード例に従うことに縛られていた場合、選択した回答は、必要なことを行う最も簡単な方法です。私はこれらの EntryPoint オブジェクトの 1 つだけを作成する予定ですが、シングルトンから離れたパターンに変更することにしました。

class EntryPoint
{

    /* Intentionally defined this way to discourage creation */
    EntryPoint(const EntryPoint &); // undefined & private
    EntryPoint& operator=(const EntryPoint &); // undefined & private

    // public
    EntryPoint()
    {
        /* All of the action is performed here! */
    }

    /* Other supporting functions */
}

// The easier to understand main function!
int main()
{
    EntryPoint * ep = new EntryPoint(); // transfer control to the entrypoint
    delete ep;
}

これらすべてのシングルトンが必要になると考えていた理由の 1 つは、モジュラー プラグイン タイプのアプリケーションをサポートするより大きなアーキテクチャを作成する計画があるためです。また、メモリ リークを最小限に抑えるために、より多くのエラー チェックとメモリ保護が必要でした。クロスプラットフォームの Qt ( http://qt.nokia.com/ ) が保護されたポインターやその他のクールな機能を提供していることを知り、うれしく思いました。

4

2 に答える 2

1

Singleton::GetInstance直接使用しないのはなぜですか?(読み取り専用) グローバルに保存する必要があるのはなぜですか? これにより、依存関係の問題も解決されます。

于 2010-06-05T11:57:54.067 に答える
1

次の呼び出しによるアクセスのみを許可します。

Singleton::GetInstance 

コピーおよび割り当てコンストラクターを非公開にすることで、これを強制します

private:
   Singleton(){}
   Singleton(Singleton const&){}; //copy ctor private
   Singleton& operator=(Singleton const&){}; 
于 2010-06-05T13:40:27.797 に答える