简体   繁体   English

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

[英]How to validate input parameters in C++ constructor?

Following example shows the crux of the problem. 以下示例显示了问题的关键。 I need to initialize const members of a class. 我需要初始化类的const成员。 This can only be done in the initializer-list and not in constructor body. 这只能在初始化列表中完成,而不能在构造函数体中完成。 I want to assert or throw an error if input to the constructor is invalid, that is, if the vector size is less than 3. 如果构造函数的输入无效,也就是说,如果向量大小小于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;
};

Please advise how to achieve this in Modern C++ (11 and later) 请告知如何在Modern C ++(11及更高版本)中实现这一目标

Just add a layer of abstraction. 只需添加一个抽象层。 You can write a function that makes sure the vector is of the correct size and you can even make sure the values are in an expected range, if you have one. 您可以编写一个函数来确保向量的大小正确,甚至可以确保值在预期的范围内(如果有的话)。 That would look like 那看起来像

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

const members can only be initialized in the constructors's member initialization list. const成员只能在构造函数的成员初始化列表中初始化。 To validate the caller's input, you would have to call a helper function to validate each input value before passing it to the corresponding member, eg: 要验证调用者的输入,您必须调用辅助函数来验证每个输入值,然后再将其传递给相应的成员,例如:

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

Or, simply utilize the vector 's own built-in bounds checking instead: 或者,只需使用vector自己的内置边界检查

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

Not as elegant as other solutions but... you can simply add a throw in a ternary operator inside the initialization of the first constant 还不如优雅的其他解决方案,但......你可以简单地添加一个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]}
      { }
 };

Off Topic suggestion: if A is a class , maybe it's better that the constructor is public . 关闭主题建议:如果A是一个class ,那么构造函数是public可能更好。

Other option extra layer through conversion: 通过转换的其他选项额外层:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM