14

我正在用 C++ 重新设计一个类构造函数,并需要它来捕获一个未指定的布尔值。我对所有其他参数都使用了默认值,但据我了解,布尔只能初始化为真或假。由于这两种情况在课堂上都有意义,我应该如何处理检查默认值的变化?

4

13 回答 13

41

现实是你不能这样做。布尔值具有真或假的值,如果您没有初始化它,那么它是随机的真或假,在程序的每次运行或该类的分配中可能不同。

如果您需要具有更多选项的类型,请定义一个枚举。

typedef enum MyBool {
    TRUE,
    FALSE,
    FILENOTFOUND
} MyBool;
于 2009-05-05T23:40:59.010 回答
37

三态布尔是通往黑暗面的道路。三态布尔会导致愤怒。愤怒导致仇恨。仇恨导致痛苦。


最好不要使用三态布尔值。

相反,使用一个额外的布尔值来判断第一个布尔值是否“已初始化”(或者更好的是,“已知”)。

class Prisoner : public Person
{


  ...

  bool is_veredict_known;
  bool is_guilty;
}

如果判决还不知道,您无法判断 Prisoner 是否真的有罪,但您的代码可以区分不同的情况。当然,宪法保证 is_guilty 的默认值应该是假的,但是,仍然...... :)

顺便说一句,类不变量应该包括:

assert(is_veredict_known || !is_guilty);
于 2009-05-06T08:33:50.723 回答
18

听起来你想要boost::tribool或者boost::optional<bool>

于 2009-05-05T23:39:03.320 回答
5

如果这就是您所需要的,请创建一个表示可能尚未初始化的值的概念的值。

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;
}
于 2009-05-05T23:36:30.657 回答
4

在 C++ 中,abool只是一位信息,要么是 0,要么是 1。由于要表示三种可能的状态,因此还需要一位信息。有两种通用技术:

  1. 使用另一个bool值来指示该值是否为“默认”,或者
  2. 使用具有三个值的枚举类型来指示(默认、真、假)。

我可能会选择选项1。

于 2009-05-05T23:38:11.933 回答
3

使用巨大的 boost::optional。不仅对于布尔值,而且对于您使用了一些脏的未初始化值的所有其他地方。它的使用如下:

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;
   }
}
于 2009-11-22T15:21:14.343 回答
3
struct Bool { //guaranteed initialized bool
    bool v;

    Bool() : v(false) {}
    operator bool() const { return v; }
    bool& operator=(const bool val){ return v = val; }
};
于 2010-09-02T22:29:50.737 回答
2

您可以有一个单独的私有成员来指示 bool 值是否已实际初始化。

于 2009-05-05T23:37:51.230 回答
1

我不是很明白,但我会尝试...

当您有一个未指定某些值的聚合初始值设定项时,将应用默认值。在这种情况下,bool 的默认值为 false。在一个类中,“默认”值将是未初始化的,这意味着它可以是任何值,并且可以从运行到运行更改。

如果您对 bool 是否已更改感兴趣,最好的选择是使用默认为 false 的第二个 bool 来跟踪它,或者使用表示 3 种可能状态的枚举。如果你真的想要 3 个状态,你真的不想要一个布尔值。

于 2009-05-05T23:37:05.103 回答
1

你真的不能。您能否提供第二个构造函数,例如:

class MyClass {
  public:
    MyClass(bool bFlag); // <-- not default
    MyClass(void);       // <-- default
};
于 2009-05-06T13:42:14.370 回答
0

使用枚举代替布尔值。例如,控制魔法等级:

enum {
    MY_ENUM_NO_MAGIC,
    MY_ENUM_SOME_MAGIC,
    MY_ENUM_MORE_MAGIC
} MagicLevel;

然后让你的构造函数接受一个参数MagicLevel magic = MY_ENUM_NO_MAGIC

于 2009-05-05T23:42:51.767 回答
0
class aclass
{
    <stuff> lots of other things
    bool mybool
    bool ismyboolinit

    void setmybool(bool b)
    {
        mybool = b;
        ismyboolinit = true;
    }

}
于 2009-11-22T15:28:56.873 回答
0

好吧,如果您使用函数和类,只需重载它们。

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.
} 

// 你去吧。此外,您不需要有一个可以只使用重载函数的类。

于 2011-10-07T18:03:15.297 回答