2

一般的な設定マネージャーを作成しようとしています。設定は INI ファイルから取得され、整数または文字列にすることができます。これらの設定のベクトルを保存できるようにしたいので、それらを繰り返し処理して目的の設定を見つけ、その値を抽出できます。

私はこのようなものを書くことができるようにしたい:

// Desired usage:
Settings settings;      // A container class, defined below
settings.add(new Setting<string>("shipName", "HAL"));
settings.add(new Setting<int>   ("shipYear", 2001));

// Different return types:
string shipName = settings.getSetting("shipName")->getValue(); 
int shipYear    = settings.getSetting("shipYear")->getValue();

私は3つのクラスを持っています:

  1. すべての設定クラスの母である AbstractSetting。これが必要なのは、一貫した型をベクトルに格納できるようにするためです。

  2. 設定、AbstractSetting から継承するテンプレート化されたクラス。ここでは、設定データを文字列または整数として保存できます。

  3. 設定、保存と取得を処理する設定を保持するためのコンテナー クラス。

メソッドは主にゲッター/セッターです。実装は明らかなので、簡潔にするために省略しました。

私の質問は、getValue() のさまざまな実装 (さまざまな戻り値の型) を使用できるようにするために、AbstractSetting に何を入れればよいかということです。

class AbstractSetting
{
private:
   string mName;

public:
   AbstractSetting(const string &name);     // Constructor

   // What does here?  Need to declare getValue somehow
};

////////////////////////////////////////

// Sublcasses of AbstractSetting, one for each T
template <class T>
class Setting : public AbstractSetting
{
private:
   T mValue;

public:
   Setting<T>(const string &name, const T &value);

   void setValue(const T &value);
   T getValue();
};

////////////////////////////////////////

// Container for all our settings
class Settings 
{
private:
   Vector<AbstractSetting *> mSettings;

public: 
   const AbstractSetting *getSetting(const string &name) const;
   void add(AbstractSetting *setting);    // Store new setting
};
4

3 に答える 3

2

期待する型をコンパイラに伝える必要があると思います。これは、次のようにして行うことができます。

class AbstractSetting
{
  private:
   string mName;

  public:
   AbstractSetting(const string &name);     // Constructor

   template <typename T>
   T&  getTheValue()
   {
      Settings<T>* upcast = dynamic_cast<Settings<T>*>(this);
      if (!upcast)
         ; //throw your exception
      return upcast->getValue();
   }

   template <typename T>
   T const&  getTheValue() const
   {
      Settings<T>* upcast = dynamic_cast<Settings<T>*>(this);
      if (!upcast)
         ; //throw your exception
      return upcast->getValue();
   }
};

そしてそれを呼び出す:

 string & value = settings.getSettings("strName").getTheValue<string>();
 int otherValue = settings.getSettings("intName").getTheValue<int>();

戻り値の型を指定したくない場合は、次のようにして参照によって変数を渡すことができます。

class AbstractSetting
{
  private:
   string mName;

  public:
   AbstractSetting(const string &name);     // Constructor

   template <typename T>
   void  getTheValue(T& ret)
   {
      Settings<T>* upcast = dynamic_cast<Settings<T>*>(this);
      if (!upcast)
         ; //throw your exception
      ret = upcast->getValue();
   }
};

そして、次のように使用します。

 string value;
 int otherValue;
 settings.getSettings("stringName").getTheValue(value); // will do a copy, so this is kind of bad, avoid this by using pointer.
 settings.getSettings("intName").getTheValue(otherValue);
于 2013-08-01T13:22:29.103 に答える
1

私が見つけたもう1つの解決策を提供しますが、それが好きかどうかはまだわかりません .

これを AbstractSettings クラスに追加すると、次のようになります。

template<class T>
operator T()
{
   return getValue<T>();
}

C++ の暗黙的なキャストをオーバーライドして、この構文を機能させることができます。

int shipYear = *settings.getSetting("shipYear");
于 2013-08-01T22:18:41.240 に答える