7

一般的で単純なタスクは次のとおりです。構成ファイルから構成設定を読み取り、設定をオブジェクトに (たとえばハッシュとして) 保存し、構成パラメーターにアクセスする必要があるさまざまなオブジェクトからこのオブジェクトにアクセスします。

ConfigFile クラス実装のこの実装を見つけましたが、機能します。私の質問は、このクラスのインスタンスを他のクラスから利用可能にし、スレッドセーフにするための最良の方法は何ですか、静的初期化順序の大失敗などを回避することです.

私の現在のアプローチは、 main() を使用して構築することです

    // Read face detection related parameter values from the configuration file.
string configFileName = "detection_parameters.txt";
try {
    parameters = ConfigFile( configFileName );
}
catch(ConfigFile::file_not_found) {
    cerr << "configuration file not found: " << configFileName << endl;
    exit(-1);
}

次に、パラメーターをグローバル変数にします。しかし、グローバル変数の代わりにシングルトンを使用する必要があることも読みました。ファイル名を使用してシングルトンをインスタンス化するにはどうすればよいですか?

これは非常に一般的なタスクに違いないので、一般的に受け入れられている良い方法があるに違いないと思いますか? 誰かが私にそれを指摘していただければ幸いです。

ありがとう、C

4

6 に答える 6

6

自分でロールする場合は、構成クラスにシングルトンデザインパターンを使用することをお勧めします。クラス自体に独自の型の静的ポインターを格納させ、コンストラクターをプライベートにして、静的ゲッターを使用してクラスの1つのインスタンスを取得するように強制します。

したがって、モックアップ(コンパイルされない可能性があり、楽しいConfig機能が欠落していますが、要点を説明する必要があります)

class Config
{
public:
   static Config * getConfig();
   static void setConfigFileName(string filename);
private:
   Config();
   static string m_filename;
   static Config * m_configInstance;
};

はっきりしない場合は、getConfig()がm_configInstanceを調べます。有効なものでない場合は、作成して(プライベートコンストラクターにアクセスできます)、m_configInstanceに格納して、後続のすべての呼び出しが同じコンストラクターにアクセスするようにします。

したがって、main()はsetConfigFileName()を使用し、クラスはConfig :: getConfig()を呼び出してから、その操作を呼び出す必要があります。標準のグローバル変数よりもはるかにクリーンです。

ブラスト-私がこれを書いている間に、他の人々もシングルトンデザインパターンを提案しました。ああ、そうですね。追加の説明がお役に立てば幸いです。

于 2009-07-08T17:43:37.440 に答える
2

構成クラスに対して行ったことは、ハッシュテーブル キャッシュを使用してシングルトンの静的クラスを作成することです。私の構成ファイルは、アプリケーションの設定を変更するために読み書きできるように設計されています。

設定を取得するための呼び出しが行われるたびに、ハッシュテーブルでルックアップを実行し、そこにない場合は、ファイルから設定を読み取り、ハッシュテーブルをロックして、ハッシュテーブルに入れます。ルックアップのためのハッシュテーブルは非常に高速です。

于 2009-07-08T17:31:27.310 に答える
2

Boost の Program Optionsライブラリを見たことがありますか?

于 2009-07-08T17:17:29.740 に答える
2

「静的初期化順序の大失敗」に言及することで、いくつかの静的オブジェクトを初期化するために構成項目を使用できるようにする必要があると思います。シングルトンの ConfigFile クラスは機能しますが、main() を開始する前に情報が必要になるため、ファイル名を取得する方法を変更する必要があります。ファイル名を提供するか、ファイル名を構成クラス自体に組み込むには、別のシングルトンが必要です。

于 2009-07-08T18:02:36.967 に答える
0

私はクリスに同意し、シングルトンを使用します。シングルトン パターンの優れた点は、最初にアクセスしようとしたときに必要なデータのみを初期化/収集し、それ以降は関心のあるすべての人が利用できることです。構成の変更を許可する場合は、ライターをロックする必要があります。

于 2009-07-08T17:40:54.390 に答える
0

シングルトン デザイン パターンと同様の手法を使用して、このようなグローバル リソースを構成しました。

class Config
{
public:
   Config(const string & filename) {
      if (m_configInstance) {
         throw AlreadyInitException;
      }
      // do main init
      m_configInstance = this;
   }

   ~Config() {
      m_configInstance = 0;
   }

   static Config * getConfig() {
      if (!m_configInstance) {
         throw NoConfigException;
      }
      return m_configInstance;
   }

private:
   static Config * m_configInstance;
};

Config * Config * m_configInstance = 0;

コンストラクターは、設定されていないことをテストし、m_configInstance設定されている場合は例外をスローします。m_configInstanceその後、構築を終了し、 に設定して自身を登録しますthis

設定されていない場合、getConfigメソッドはインスタンスまたはスローと例外を返します。

デストラクタは、m_configInstance再び 0 に設定します。

クラスを使用するには、 の開始時に 1 回作成しmain()ます。次に、メソッドで必要なときにアクセスしますgetConfig()

Configシングルトンとは異なり、オブジェクトの有効期間が明確に制御されるようになりました。また、これには単体テストの追加の利点があり、各テストまたはテストのスイートは独自のConfigオブジェクトを作成でき、それらはすべてテスト間で適切にクリーンアップされます。

于 2009-07-09T17:47:56.247 に答える