如何在多个构造函数中复制检查

时间:2012-09-30 17:52:03

标签: c++ constructor c++11

我的课程中有几个构造函数:

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()吗?

3 个答案:

答案 0 :(得分:4)

在C ++ 11中,您可以使用委托的构造函数:

  

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

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

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

具有较少参数的构造函数使用更多参数调用构造函数,具有最多参数的构造函数执行所有检查。

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

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

答案 1 :(得分: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);

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

答案 2 :(得分: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;
  };