Как проверить инициализацию переменной-члена const перед ее назначением в C ++ - PullRequest
0 голосов
/ 27 ноября 2018

Допустим, у меня есть этот простой класс с переменной-членом const int:

class MyClass{
    public:
        Myclass(int x, int y);
    private:
        const int importantNumber;
        int anotherNumber;
};

MyClass::MyClass(int x, int y) :importantNumber{x}
{
    this->anotherNumber = y;
}

Поскольку int importantNumber является константой, я могу установить его только во время создания объекта конструктором (ссписок инициализации члена, как показано выше).

Теперь вопрос: как я мог бы добавить проверку для аргумента x, данного конструктору, перед тем, как фактически создать важный элемент с этим значением?Можно ли создать static int MyClass::validation(int a) и использовать его в списке инициализации члена конструктора, например importantNumber{validation(x)}?

Даже если это возможно, есть ли лучший способ сделать это?

Ответы [ 3 ]

0 голосов
/ 27 ноября 2018

Используйте функцию фабрики для создания класса вместо конструктора.

class MyClass
{
public:
  static MyClass* create (int x, int y);

private:
  MyClass(int x, int y);

private:
  const int importantNumber;
  int anotherNumber;
};

MyClass* MyClass::create (int x, int y)
{
  return x > 0 ? new MyClass(x, y) : NULL;
}

Когда вам требуется дополнительная проверка параметров, фабрики имеют следующие преимущества:

  • Они избегают созданияОбъект в памяти, если тесты не пройдены.is_valid () "функция-член для вашего класса.
0 голосов
/ 27 ноября 2018

Вы можете использовать троичный оператор condition ? true : false в конструкторе, если хотите проверить с помощью простого условия:

class MyClass{
    public:
        MyClass(int x, int y);
    private:
        const int importantNumber;
        int anotherNumber;
};

MyClass::MyClass(int x, int y) : importantNumber(x > 0 ? x : 0)
{
    this->anotherNumber = y;
}

Однако, имейте в виду, что вещи могут быстро стать трудными для чтения, если вы переборщитес этим оператором.

Для чего-то более сложного, вы можете сделать что-то вроде этого:

int validateIntegral(int x) const
{
    // Do validation on 'x'...

    return x;
}

class MyClass{
    public:
        MyClass(int x, int y);
    private:
        const int importantNumber;
        int anotherNumber;
};

MyClass::MyClass(int x, int y) : importantNumber(validateIntegral(x))
{
    this->anotherNumber = y;
}
0 голосов
/ 27 ноября 2018

Вы просто добавляете его.

MyClass::MyClass(int x, int y) : importantNumber{validate(x)}
{
    this->anotherNumber = y;
}

Функция int validate(int original) теперь может возвращать что-то отличное от x, либо выдавать исключение, либо assert, либо запрашивать подтверждение у пользователя, в зависимости от того, что вы считаете целесообразным.

Если это простая проверка и вы не хотите писать функцию validate, вы можете использовать лямбду:

MyClass::MyClass(int x, int y) :importantNumber{
    [](int number){
        assert(number > 0);
        return number;
    }(x)}
{
    this->anotherNumber = y;
}

Хотя это может быть немного запутанным, еслиты переусердствовал.

...