Как проверить, была ли определенная переменная типа enum в классе назначена или нет? - PullRequest
0 голосов
/ 30 мая 2018

Я хочу проверить, установлена ​​ли переменная в классе или нет?Как я могу это сделать?

enum Color {
   red,
   blue
};
class example {
   Color c;
   void set_color(Color c) { this->c = c; }
   Color get_color() { return c; }
   bool check_color_is_set() {
       if (c == Color) {} // compile error
       if (c == NULL) {} // compile error
       return true;
   }

Я хочу знать, была ли назначена переменная Color c или нет?

Ответы [ 3 ]

0 голосов
/ 30 мая 2018

Кроме наличия значения для не назначенного (как в @ code707's answer ), вы можете сделать несколько вещей.

Тот же подход, пользователь может использовать класс неинициализированный - смягчение

Все основано на хранении bool, если пользователь вызывает правильно установленные.

Используйте инкапсуляцию get / set дляпроверьте, установлено ли оно:

class example {
private:
    Color color;
    bool isColourSet = false;

public:
    Color get_color() const;

    void set_color(Color newCol) {
       color = newCol;
       isColourSet = true;
    }
...

Затем вы можете использовать этот bool различными способами в зависимости от вашего желания:


Бросить исключение

    Color get_color() const {
       if (!isColourSet) throw some_exception; // It wasnt Set!! Throw
       return color;
    }

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


Возвращение кода ошибки

Если вы не хотите выдавать исключение, вы можете передать аргумент возврата и вернуть ошибку:

ErrInt get_colour(Colour &out) const {
    if (!isColourSet) return STANDARD_ERROR_VAL;
    out = color;
    return STANDARD_SUCCESS_VALUE;
}

Это очень похоже на концепцию Bad Value в перечислении.


Использование std::optional

Так как c++17 у вас также есть новый способ std::optional, где вы можете при желании вернуть (вместо того, чтобы выдавать исключение или возвращать значение ошибки).

class example {
public:
    std::optional<Color> get_colour() {
        return color;
    }
    void set_color(Color newColor) {
        color = newColor;
    }
private:
    std::optional<Color> color;
}

Тогда пользователь может использовать его кактакие:

auto myColor = myExample.get_colour();
if (myColour) { // Here you can check the optional
    myColour.get() // Do something with colour.
...

Новый подход, пользователь не может установить класс в плохом состоянии - перепроектировать

В отличие от установки значения и необходимости проверить, было ли оно установлено правильно, возможно, выможет спроектировать класс так, чтобы он никогда не находился в недопустимом состоянии.Давайте рассмотрим, как мы можем это сделать:

1 Тип безопасности

Мы не хотим, чтобы пользователь мог установить случайное значение для цвета, который мы не делаемзнать о.В текущей реализации enum будет типом, который может быть установлен с вероятностью любого значения int!Что это значит, когда кто-то делает set_color(538)?Мы можем исправить это с помощью c ++ 11 enum class:

enum class Color {
    RED,
    BLUE
}

// This now causes a compiler error:
set_color(523);
// You can only use it like this:
set_color(Color::Red);

2 Аргументы конструктора

Мы можем заставить пользователя выбрать исходный цвет, предоставив толькоконструктор, которому требуется цвет:

class example {
public:
    example(Color startColor) : color(startColor) {}        
...
private:
    Color c;
}

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

void change_color(Color newColor) {
    color = newColor;
}

3 Заключение

Теперь у вас есть класс, где пользователь никогда не сможетпопасть в ситуацию, когда это недействительно.Я полагаю, что это намного лучше, чем пытаться определить, не затерялся ли пользователь при создании класса.

0 голосов
/ 30 мая 2018

Если вы без колебаний используете библиотеку наддува , то, возможно, вы сможете сделать это, используя boost::optional.

#include <boost/optional.hpp>

enum Color {
   red,
   blue
};

class example 
{
   boost::optional<Color> c;
   void set_color(Color c) { this->c = c; }
   Color get_color() { return c; }
   bool check_color_is_set()
   {
     if( c ){
       // color is set
       return true;
     }
     else
     {
       // color is not set.
       return false;
     }
   }
}

Значение по умолчанию boost::optional<Color> c будет boost::none по умолчанию.Вы можете выполнить обычные проверки if на нем и посмотреть, было ли что-то установлено или нет.

Вот справочная документация по для Boost Optional для справки.

ПРИМЕЧАНИЕ: Я не использовал опциональную версию STL, но если вы не заинтересованы в использовании Boost, вы всегда можете также использовать std::optional.

0 голосов
/ 30 мая 2018

А как насчет специального значения для "не назначено"?

enum Color {
   nocolor,
   red,
   blue
};
class example {
   Color c = nocolor;
   void set_color(Color c) { this->c = c; }
   Color get_color() { return c; }
   bool check_color_is_set() {
       if (c == nocolor) {} 

       return true;
   }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...