Значение по умолчанию для bool в C++
Я перепроектирую конструктор класса В C++ и нуждаюсь в нем, чтобы поймать неуказанный bool. Я использовал значения по умолчанию для всех других параметров, но из моего понимания bool может быть инициализирован только true или false. Поскольку оба этих случая имеют значение в классе, как я должен обрабатывать проверку изменения от значения по умолчанию?
13 ответов
реальность такова, что вы не можете сделать это. Bool имеет значение true или false, и если вы его не инициализировали, то он является случайным true или false, возможно, различным при каждом запуске программы или выделении этого класса.
Если вам нужен тип с большим количеством опций, определите перечисление.
typedef enum MyBool {
TRUE,
FALSE,
FILENOTFOUND
} MyBool;
Tristate bool-это путь к темной стороне. Tristate bool приводит к гневу. Гнев ведет к ненависти. Ненависть ведет к страданию.
предпочитают не использовать tristate bool.
вместо этого используйте одно дополнительное логическое значение для того, является ли первое логическое значение "инициализированным "(или лучше" известным") или нет.
class Prisoner : public Person
{
...
bool is_veredict_known;
bool is_guilty;
}
Если veredict еще не известен, вы не можете сказать, действительно ли заключенный виновен, но ваш код может различать между разными ситуациями. Конечно, Конституция гарантирует, что значение по умолчанию is_guilty должно быть ложным, но все же... :)
кстати, инвариант класса должен включать:
assert(is_veredict_known || !is_guilty);
похоже, вы хотите boost:: tribool или, может быть,boost:: необязательно
Если это то, что вам нужно, создайте значение, которое представляет концепцию значения, которое, возможно, не было инициализировано.
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;
}
В C++ a bool
- Это только один бит информации, либо 0, либо 1. Поскольку вы хотите представить три возможных состояния, вам нужен еще один бит информации. Есть две общие техники:--3-->
- использовать другой
bool
значение, указывающее, является ли значение "по умолчанию" или нет, или - используйте тип перечисления с тремя значениями для указания (по умолчанию, true, false).
Я бы, вероятно, выбрал вариант 1.
struct Bool { //guaranteed initialized bool
bool v;
Bool() : v(false) {}
operator bool() const { return v; }
bool& operator=(const bool val){ return v = val; }
};
используйте большой импульс:: необязательно. И не только значений, но и для всех других местах, где вы некоторые грязные неинициализированные значения. Он используется следующим образом:
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;
}
}
У вас может быть отдельный частный член, который указывает, было ли фактически инициализировано значение bool или нет.
Я не совсем понимаю, но попробую...
значения по умолчанию применяются, если у вас есть агрегатный инициализатор, который оставляет некоторые значения неуказанными. В этом случае значение по умолчанию bool будет false. В классе значение "по умолчанию" будет неинициализированным, что означает, что это может быть любое значение и может изменяться от запуска к запуску.
Если вас интересует, изменился ли bool, ваш лучший вариант-отслеживать его со вторым bool по умолчанию false, или используйте перечисление, представляющее 3 возможных состояния. Если вы действительно хотите 3 состояния, вы действительно не хотите bool.
вы действительно не можете. Не могли бы вы предоставить второй конструктор, например:
class MyClass {
public:
MyClass(bool bFlag); // <-- not default
MyClass(void); // <-- default
};
вместо логического используйте перечисление. Например, для управления уровнем магии:
enum {
MY_ENUM_NO_MAGIC,
MY_ENUM_SOME_MAGIC,
MY_ENUM_MORE_MAGIC
} MagicLevel;
тогда пусть ваш конструктор примет параметр MagicLevel magic = MY_ENUM_NO_MAGIC
.
class aclass
{
<stuff> lots of other things
bool mybool
bool ismyboolinit
void setmybool(bool b)
{
mybool = b;
ismyboolinit = true;
}
}
Ну, если вы используете функции и классы, просто перегрузите их.
ie:
class thing
{
public:
void f1(bool); // bool input
void f1(int = 3); // default with out bool being known
private:
// stuff
};
void thing::f1 (bool hasAFace)
{
if(hasAFace)
f1(0);
if(!hasAFace)
f1(1);
}
void thing::f1 (int tri)
{
bool actionTime;
if(tri == 1)
actionTime = true;
else if(tri == 0)
actionTime = false;
else
//input defualt action here.
}
// и вот вы идете. Также вам не нужно иметь класс, который вы могли бы просто использовать перегруженные функции.