C++ では、シングルトンのすべてのメンバーを静的にできますか、それとも可能な限り多くできますか? 私の考えでは、とにかくグローバルに 1 つのインスタンスしかありません。
検索中に、C# の静的クラスに関する多くの議論を見つけましたが、それについてはよく知りません。それについても学びたいと思います。
どんなことでも構いませんのでコメントお願いします。
静的シングルトンでは、シングルがいつ割り当てられて構築されるかを制御できません。これにより、静的変数の構築規則の c++ 順序に翻弄されるため、別の静的変数の構築中にこのシングルを呼び出すと、シングルがまだ存在しない可能性があります。
別の静的変数のコンストラクターからシングルトンを呼び出すつもりがなく、何らかの理由で構築を遅らせたくない場合は、シングルトンに静的変数を使用しても問題ありません。
詳細については、静的変数の初期化順序を参照してください。
あなたの質問に答えるために:あなたが提案しているケースは、C#の「静的クラス」のようなものであり、C++には「静的クラス」の概念がありません。
通常、C ++シングルトンクラスでは、静的データメンバーはシングルトンインスタンス自体のみです。これは、シングルトンクラスへのポインタまたは単なるインスタンスのいずれかです。
シングルトンインスタンスをポインタにせずにシングルトンクラスを作成するには、2つの方法があります。
1)
class MySingletonClass
{
public:
static MySingletonClass& getInstance()
{
static MySingletonClass instance;
return instance;
}
// non-static functions
private:
// non-static data-members
};
2)
class MySingletonClass
{
public:
static MySingletonClass& getInstance()
{
return sInstance;
}
// non-static functions
private:
static MySingletonClass sInstance;
// non-static data-members
};
// In CPP file
MySingletonClass MySingletonClass::sInstance;
この実装はスレッドセーフではなく、いつ構築されるか、いつ破棄されるかという観点からは予測できません。このインスタンスがそれ自体を破棄するために別のシングルトンに依存している場合、アプリケーションを終了するときに識別できないエラーが発生する可能性があります。
ポインタのあるものは次のようになります。
class MySingletonClass
{
public:
static MySingletonClass& getInstance()
{
return *sInstance;
}
static MySingletonClass* getInstancePointer()
{
return sInstance;
}
MySingletonClass()
{
if (sInstance) {
throw std::runtime_error("An instance of this class already exists");
}
sInstance = this;
}
// non-static functions
private:
static MySingletonClass* sInstance;
// non-static data-members
};
このようなシングルトンクラスの初期化は、通常、アプリケーションの初期化中に発生します。
void MyApp::init()
{
// Some stuff to be initalized before MySingletonClass gets initialized.
MySingletonClass* mySingleton = new MySingletonClass(); // Initalization is determined.
// Rest of initialization
}
void MyApp::update()
{
// Stuff to update before MySingletonClass
MySingletonClass::getInstance().update(); // <-- that's how you access non-static functions.
// Stuff to update after MySingletonClass has been updated.
}
void MyApp::destroy()
{
// Destroy stuff created after singleton creation
delete MySingletonClass::getInstancePointer();
// Destroy stuff created before singleton creation
}
このシナリオでは、シングルトンの初期化と破棄が制御されていますが、マルチスレッドアプリケーションではシングルトンはうまく機能しません。これであなたの疑問が解消されることを願っています。
おそらくご存知のように、シングルトン パターンには、インスタンスが存在する場合にのみインスタンスを作成し、そのインスタンスを返す静的メソッド Instance が含まれています。シングルトンの他のメソッドまたはすべてのメソッドを静的にできない理由はありません。ただし、クラスのインスタンスが 1 つしかないことを考えると、他のすべてを静的にする意味があるかどうかはわかりません。それは理にかなっていますか?
シングルトンのポイントの多くは、それがいつ作成されるかをある程度制御できるようにすることです。
静的データ メンバーを使用すると、それらのメンバーに対するそのコントロールが失われます。
したがって、それを行うのは賢明ではありません。
とはいえ、シングルトンは一般に、純粋なグローバル変数と同じ問題の多くを伴う Evil™ です。これには、さまざまな予測不可能な効果を、予測不可能な場所から他の予測不可能でほとんど知られていない場所に意地悪に伝播する、制御不能な通信ハブとして機能する傾向が含まれます。予測不可能な時代。
シングルトンは本当に答えなのか、それとも、この場合、解決しようとしていた問題を複雑にする方法にすぎないのでしょうか?
短い答え:はい! 承知しました!C++ は柔軟性があり、ほとんどすべてのことが可能です (特に、このような単純なもの)。
詳細な答えは、ユースケースによって異なります。