Значение по умолчанию для bool в C ++ - PullRequest
13 голосов
/ 06 мая 2009

Я перепроектирую конструктор класса в C ++, и мне нужно, чтобы он перехватывал неопределенный тип bool. Я использовал значения по умолчанию для всех других параметров, но из моего понимания bool может быть только инициализирован как true или false. Поскольку оба этих случая имеют значение в классе, как мне обрабатывать проверку на изменение значения по умолчанию?

Ответы [ 13 ]

40 голосов
/ 06 мая 2009

Реальность такова, что вы не можете сделать это. Значение bool имеет значение true или false, и если вы его не инициализировали, то оно случайным образом равно true или false, возможно, различается при каждом запуске программы или распределении этого класса.

Если вам нужен тип с большим количеством опций, определите перечисление.

typedef enum MyBool {
    TRUE,
    FALSE,
    FILENOTFOUND
} MyBool;
36 голосов
/ 06 мая 2009

Tristate bool - это путь к темной стороне. Tristate Bool приводит к гневу. Гнев ведет к ненависти. Ненависть ведет к страданию.


Предпочитают не использовать тристатный бул.

Вместо этого используйте один дополнительный логический параметр для определения того, является ли первый логический параметр "инициализированным" (или лучше "известным") или нет.

class Prisoner : public Person
{


  ...

  bool is_veredict_known;
  bool is_guilty;
}

Если veredict еще не известен, вы не можете сказать, действительно ли Prisoner виновен, но ваш код может различать различные ситуации. Конечно, Конституция гарантирует, что значение по умолчанию is_guilty должно быть ложным, но все же ... :)

Кстати, инвариант класса должен включать в себя:

assert(is_veredict_known || !is_guilty);
18 голосов
/ 06 мая 2009

Звучит так, как вы хотите boost :: tribool или, может быть, boost :: необязательно .

5 голосов
/ 06 мая 2009

Если это то, что вам нужно, создайте значение, которое представляет концепцию значения, которое, возможно, не было инициализировано.

template <typename T>
struct Maybe {
  Maybe() : m_hasValue(false) {}
  bool HasValue() const { return m_hasValue; }
  T& Value() { ThrowIfFalse(m_hasValue); return m_value; }
  const T& Value() const { ThrowIfFalse(m_hasValue); return m_value; }
  void SetValue( _In_ const T& value) { m_value = value; m_hasValue = true; }
private:
  bool m_hasValue;
  T m_value;
};

Теперь вы можете представлять все 3 состояния, которые вам нужны.

class SomeType { 
  ...
  Maybe<bool> m_myBool;
}
4 голосов
/ 06 мая 2009

В C ++ bool - это только один бит информации, либо 0, либо 1. Поскольку вы хотите представить три возможных состояния, вам нужен еще один бит информации. Существует два основных метода:

  1. Используйте другое значение bool, чтобы указать, является ли значение "по умолчанию" или нет, или
  2. Используйте тип перечисления с тремя значениями для указания (по умолчанию, true, false).

Я бы, наверное, выбрал вариант 1.

3 голосов
/ 03 сентября 2010
struct Bool { //guaranteed initialized bool
    bool v;

    Bool() : v(false) {}
    operator bool() const { return v; }
    bool& operator=(const bool val){ return v = val; }
};
3 голосов
/ 22 ноября 2009

Используйте отличный импульс :: необязательно. И не только для bools, но и для всех других мест, которые вы использовали некоторые грязные неинициализированные значения в. Он используется так:

void function(optional<int> value) {
   if (value)
      std::cout << "value is defined: " << value.get() << "\n";
   else
      std::cout << "value is not defined\n";
}

А вот пример функции, возвращающей необязательное значение:

struct MapClass {
   map<string,int> m_map;

   optional<int> getValue(string key) {
      optional<int> result = none;
      if (m_map.find(key) != m_map.end())
         result = m_map[key];
      return result;
   }
}
2 голосов
/ 06 мая 2009

У вас может быть отдельный закрытый элемент, который указывает, было ли значение bool на самом деле инициализировано или нет.

1 голос
/ 06 мая 2009

Вы действительно не можете. Не могли бы вы предоставить второй конструктор, например:

class MyClass {
  public:
    MyClass(bool bFlag); // <-- not default
    MyClass(void);       // <-- default
};
1 голос
/ 06 мая 2009

Я не совсем понимаю, но я попробую ...

Значения по умолчанию применяются, когда у вас есть агрегатный инициализатор, который оставляет некоторые значения неуказанными. В этом случае по умолчанию bool будет ложным. В классе значение «по умолчанию» будет неинициализированным, то есть оно может быть любым значением и может меняться от запуска к запуску.

Если вас интересует, изменился ли bool или нет, ваш лучший вариант - отслеживать его со вторым bool по умолчанию, равным false, или использовать enum, представляющий 3 возможных состояния. Если вы действительно хотите 3 состояния, вы действительно не хотите bool.

...