简体   繁体   中英

Default value for bool in C++

I'm redesigning a class constructor in C++ and need it to catch an unspecified bool. I have used default values for all of the other parameters, but from my understanding bool can only be initialized to true or false. Since both of those cases have meaning in the class, how should I handle checking for change from a default value?

The reality is that you can't do this. A bool has value, either true or false, and if you haven't initialized it then it is randomly true or false, possibly different at each run of the program or allocation of that class.

If you need to have a type with more options, define an enum.

typedef enum MyBool {
    TRUE,
    FALSE,
    FILENOTFOUND
} MyBool;

Tristate bool is the path to the dark side. Tristate bool leads to anger. Anger leads to hate. Hate leads to suffering.


Prefer not to use a tristate bool.

Instead, use one additional boolean for whether the first boolean is "initialized" (or better, "known") or not.

class Prisoner : public Person
{


  ...

  bool is_veredict_known;
  bool is_guilty;
}

If the veredict is not known yet, you can't tell if the Prisoner is really guilty, but your code can differentiate between the different situations. Of course the Constitution assures that the default value of is_guilty should be false, but, still... :)

By the way, the class invariant should include:

assert(is_veredict_known || !is_guilty);

听起来您想要boost :: tribool或也许boost :: optional <bool>

If that's what you need, create a value which represents the concept of a value that may not have been initialized.

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

Now you can represent all 3 states you need.

class SomeType { 
  ...
  Maybe<bool> m_myBool;
}

In C++ a bool is only one bit of information, either a 0 or a 1. Since you want to represent three possible states, you need one more bit of information. There are two general techniques:

  1. Use another bool value to indicate whether the value is "default" or not, or
  2. Use an enumeration type with three values to indicate (default, true, false).

I would probably choose option 1.

Use the great boost::optional. And not only for bools but for all other places you used some dirty not-initialized-values in. It is used like this:

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

And here's a function example returning an optional:

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;
   }
}
struct Bool { //guaranteed initialized bool
    bool v;

    Bool() : v(false) {}
    operator bool() const { return v; }
    bool& operator=(const bool val){ return v = val; }
};

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

I don't quite understand, but I'll try...

Default values are applied when you have an aggregate initializer that leaves some values unspecified. In that case, bool's default would be false. In a class, the "default" value would be uninitialized, meaning it could be any value and could change from run to run.

If you're interested in whether or not a bool has changed, your best option is to keep track of it with a second bool defaulting to false, or use an enum representing 3 possible states. If you truly want 3 states, you really don't want a bool.

You really can't. Could you provide a second constructor, for example:

class MyClass {
  public:
    MyClass(bool bFlag); // <-- not default
    MyClass(void);       // <-- default
};
class aclass
{
    <stuff> lots of other things
    bool mybool
    bool ismyboolinit

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

}

Well if your using functions and classes, just overload them.

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

// and there you go. Also you don't need to have a class you could just use overloaded functions.

Instead of a boolean, use an enumeration. For example, to control the level of magic:

enum {
    MY_ENUM_NO_MAGIC,
    MY_ENUM_SOME_MAGIC,
    MY_ENUM_MORE_MAGIC
} MagicLevel;

Then have your constructor accept a parameter MagicLevel magic = MY_ENUM_NO_MAGIC .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM