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 中,您可以使用委托构造函数功能:

借助委托构造函数功能,您可以将常见的初始化和后期初始化集中在一个名为目标构造函数的构造函数中。委托构造函数可以调用目标构造函数进行初始化。委托构造函数也可以用作一个或多个委托构造函数的目标构造函数。您可以使用此功能使程序更具可读性和可维护性。

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

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

参数少的构造器调用参数多的构造器,参数多的构造器做所有的检查。

请注意,您应该能够通过为param1and添加默认值来统一最后三个构造函数param2,如下所示:

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

对于 C++03,您需要一个特殊的函数来检查和设置参数。您可以使用多个函数,在此示例中,我放置了一个检查所有参数的函数。

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);

在这里,您将需要之前提出的解决方案之一。

于 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 回答