Как проверить входные параметры в конструкторе C ++? - PullRequest
0 голосов
/ 06 декабря 2018

Следующий пример показывает суть проблемы.Мне нужно инициализировать 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 голосов
/ 07 декабря 2018

Не так элегантно, как другие решения, но ... вы можете просто добавить 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 Тема: если Aclass, может быть, лучше, чтобы конструктор был public.

0 голосов
/ 07 декабря 2018

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 вместо встроенной проверки границ :

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;
};
0 голосов
/ 07 декабря 2018

Другой вариант дополнительного слоя через преобразование:

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;
};
0 голосов
/ 07 декабря 2018

Просто добавьте слой абстракции.Вы можете написать функцию, которая гарантирует, что вектор имеет правильный размер, и вы даже можете убедиться, что значения находятся в ожидаемом диапазоне, если он у вас есть.Это будет выглядеть как

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;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...