如何在C ++构造函数中验证输入参数?

时间:2018-12-06 20:58:33

标签: c++ validation c++11 constructor

下面的示例显示了问题的症结所在。我需要初始化一个类的const成员。这只能在初始化列表中完成,而不能在构造函数主体中完成。如果向构造函数的输入无效,即向量大小小于3,我想断言或引发错误。

class A {
 // In following constructor, how do we make sure if params.size()
 // is at least 3.
 A(const std::vector<int>& params):
  x(params[0]), y(params[1]), z(params[2]) {}
private:
  const int x;
  const int y;
  const int z;
};

请告知如何在Modern C ++(11及更高版本)中实现此目标

4 个答案:

答案 0 :(得分:7)

只需添加一个抽象层。您可以编写一个函数来确保向量的大小正确,甚至可以确保值在预期范围内(如果有的话)。看起来像

class A {
 A(const std::vector<int>& params):
  x(verify(params, 0)), y(verify(params, 1)), z(verify(params, 3)) {}
private:
  static int verify(const std::vector<int>& params, int index) 
  { 
    if (params.size() < 4) // or use if (params.size() <= index) if you only care if the index will work
      throw something; 
    return params[index]; 
  }
  const int x;
  const int y;
  const int z;
};

答案 1 :(得分:4)

const成员只能在构造函数的成员初始化列表中进行初始化。要验证调用者的输入,您必须调用帮助器函数以验证每个输入值,然后再将其传递给相应的成员,例如:

int check(const std::vector<int> &params, int index) {
  if (params.size() <= index) throw std::length_error("");
  return params[index];
}

class A {
 A(const std::vector<int>& params):
  x(check(params, 0)), y(check(params, 1)), z(check(params, 3)) {}
private:
  const int x;
  const int y;
  const int z;
};

或者,只需使用vector's own built-in bounds checking代替:

class A {
 A(const std::vector<int>& params):
  x(params.at(0)), y(params.at(1)), z(params.at(3)) {}
private:
  const int x;
  const int y;
  const int z;
};

答案 2 :(得分:1)

不如其他解决方案那么优雅,但是...您可以在第一个常量的初始化内的三元运算符中简单地添加一个throw

class A
 {
   private:
      const int x;
      const int y;
      const int z;

   public:    
      A (const std::vector<int>& params)
         : x{ params.size() < 4u ? throw std::runtime_error{"!"}
                                 : params[0] },
           y{params[1]}, z{params[3]}
      { }
 };

非主题建议:如果Aclass,则构造函数最好是public

答案 3 :(得分:0)

通过转换的其他选项额外层:

class A_params{
   friend class A;
   int x;
   int y;
   int z;
   void validate();
   public:
   A_params(std::initializer_list<int>);
   A_params(const std::vector<int>&);
   A_params(int(&)[3]);
   //...
   };


class A {
 // In following constructor, how do we make sure if params.size()
 // is at least 3.
public:
 A(A_params params):
  x(params.x), y(params.y), z(params.z) {}
private:
  const int x;
  const int y;
  const int z;
};