Кроме наличия значения для не назначенного (как в @ 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 Заключение
Теперь у вас есть класс, где пользователь никогда не сможетпопасть в ситуацию, когда это недействительно.Я полагаю, что это намного лучше, чем пытаться определить, не затерялся ли пользователь при создании класса.