2

クラス用のコンストラクターがいくつかあります。

MyClass();
MyClass( int param1 );
MyClass( int param1, int param2 );
MyClass( std::string otherParam );
MyClass( std::string otherParam, int param1 );
MyClass( std::string otherParam, int param1, int param2 );

ここで、コンストラクターで実行する引数チェックがいくつかあります。たとえば、-3 <param1 <3です。このチェックを実行するための好ましい方法は何ですか?各コンストラクターからcheckParam1()とcheckOtherParam()を呼び出す必要がありますか?

4

3 に答える 3

4

C ++ 11では、委任されたコンストラクター機能を使用できます。

コンストラクターの委任機能を使用すると、一般的な初期化と初期化の投稿を、ターゲットコンストラクターという名前の1つのコンストラクターに集中させることができます。委任コンストラクターは、ターゲットコンストラクターを呼び出して初期化を行うことができます。委任コンストラクターは、1つ以上の委任コンストラクターのターゲットコンストラクターとして使用することもできます。この機能を使用して、プログラムをより読みやすく、保守しやすくすることができます。

MyClass( std::string otherParam, int param1, int param2 );

MyClass( std::string otherParam, int param1)
:   MyClass(otherParam, param1, 456) {
}

パラメーターが少ないコンストラクターは、パラメーターが多いコンストラクターを呼び出し、パラメーターが最も多いコンストラクターがすべてのチェックを実行します。

param1次のように、とのデフォルト値を追加することで、最後の3つのコンストラクターを統合できるはずであることに注意してくださいparam2

MyClass( std::string otherParam, int param1 = 123, int param2 = 456);
于 2012-09-30T17:53:47.470 に答える
3

C ++ 03の場合、パラメータをチェックおよび設定するための特別な関数が必要になります。複数の関数を使用できます。この例では、すべてのパラメーターをチェックする1つの関数を配置します。

void checkSetParams(std::string p1, int p2, int otherP)
{
    // check params, and set object members...
}

そして、コンストラクターで:

MyClass(int p1)
{
    checkSetParams(default_string, p1, default_int);
}

MyClass(int p1, int p2, std::string str)
{
    checkSetParams(str, p1, p2);
}

等々。

C ++ 11の場合、委任コンストラクターを使用できます。

MyClass(std::string otherParam)
: MyClass(otherParam, 42, 3)
{
}

標準の両方のバージョンの場合:コンストラクターでデフォルトの引数を使用できます。それはあなたの問題の一部を解決するかもしれません、しかしあなたはまだ「便利な」コンストラクターを持つことができます:

MyClass( int param1 = 42, int param2 = 3);
MyClass( std::string otherParam, int param1 = 42, int param2 = 3);

ここでは、前に提案したソリューションの1つが必要になります。

于 2012-09-30T18:23:48.697 に答える
1

私の個人的な好み、そして私がいつも他の人にアドバイスすることは、メンバーにできるだけ多くの責任を渡すことです。これには範囲チェックが含まれます。

したがって、このエラー生成コードの代わりに:

   MyClass( int param1 ) : param1(param1), param2(0) 
   {
      if (param1 < 7 || param1 > 123) throw std::range_error("param1");
      if (param2 < 0 || param2 > 123) throw std::range_error("param2");

   }
   MyClass( int param1, int param2 ) : param1(param1), param2(param2) 
   {
      if (param1 <= 8 || param1 > 123) throw std::range_error("param1");
      if (param2 <= 0 || param2 > 123) throw std::range_error("param2");
   }

私はメンバーレベルでの範囲定義を好みます:

template <class T, T range_min, T range_max>
struct Range_Type : Wrapper_Type<T> { // Wrapper_Type<T> stores value and emulates T 
  Range_Type(T value, const char* name) : Wrapper_Type<T>(value) {
     if (value < range_min || value > range_max) throw std::range_error(name);
  }
};

そして使用法:

  class MyClass{
  public:
       MyClass( int param1 ) : param1(param1), param2(0) 
       {
       }
       MyClass( int param1, int param2 ) : param1(param1), param2(param2) 
       {
       }
  private:
       Range_Type<int, 7, 123> param1;
       Range_Type<int, 0, 123> param1;
  };
于 2012-09-30T21:12:53.757 に答える