Domanda

Sto riprogettando un costruttore di classi in C++ e ne ho bisogno per rilevare un bool non specificato.Ho utilizzato i valori predefiniti per tutti gli altri parametri, ma da quanto ho capito bool può essere inizializzato solo su true o false.Poiché entrambi i casi hanno un significato nella classe, come dovrei gestire il controllo della modifica rispetto a un valore predefinito?

È stato utile?

Soluzione

La realtà è che non puoi farlo. Un valore booleano ha valore, sia vero che falso, e se non lo hai inizializzato, esso è casualmente vero o falso, probabilmente diverso ad ogni esecuzione del programma o allocazione di quella classe.

Se devi avere un tipo con più opzioni, definisci un enum.

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

Altri suggerimenti

Il bool di Tristate è il percorso verso il lato oscuro. Il bool di Tristate porta alla rabbia. La rabbia porta all'odio. L'odio porta alla sofferenza.


Preferisco non usare un bool tristato.

Invece, usa un booleano aggiuntivo per stabilire se il primo booleano è " inizializzato " (o meglio, " noto ") o no.

class Prisoner : public Person
{


  ...

  bool is_veredict_known;
  bool is_guilty;
}

Se il Veredict non è ancora noto, non puoi dire se il Prigioniero è veramente colpevole, ma il tuo codice può distinguere tra le diverse situazioni. Naturalmente la Costituzione assicura che il valore predefinito di is_guilty dovrebbe essere falso, ma, comunque ... :)

A proposito, l'invariante di classe dovrebbe includere:

assert(is_veredict_known || !is_guilty);

Se è ciò di cui hai bisogno, crea un valore che rappresenti il ​​concetto di valore che potrebbe non essere stato inizializzato.

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

Ora puoi rappresentare tutti e 3 gli stati di cui hai bisogno.

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

In C ++ un bool è solo un bit di informazione, uno 0 o uno 1. Dato che si desidera rappresentare tre stati possibili, è necessario un altro bit di informazione. Esistono due tecniche generali:

  1. Utilizzare un altro <=> valore per indicare se il valore è " default " o no, oppure
  2. Utilizzare un tipo di enumerazione con tre valori per indicare (predefinito, vero, falso).

Probabilmente sceglierei l'opzione 1.

struct Bool { //guaranteed initialized bool
    bool v;

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

Usa la grande spinta :: opzionale. E non solo per i bool ma per tutti gli altri posti che hai usato alcuni sporchi valori non inizializzati in. Viene usato in questo modo:

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

Ed ecco un esempio di funzione che restituisce un facoltativo:

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

Potresti avere un membro privato separato che indica se il valore bool è stato effettivamente inizializzato o meno.

Non capisco bene, ma ci proverò ...

I valori predefiniti vengono applicati quando si dispone di un inizializzatore aggregato che lascia alcuni valori non specificati. In tal caso, il valore predefinito di bool sarebbe falso. In una classe, il & Quot; default & Quot; il valore sarebbe non inizializzato, il che significa che potrebbe essere qualsiasi valore e potrebbe cambiare da una corsa all'altra.

Se sei interessato a sapere se un bool è cambiato o meno, la tua migliore opzione è di tenerne traccia con un secondo bool predefinito su false, oppure usare un enum che rappresenta 3 stati possibili. Se vuoi veramente 3 stati, davvero non vuoi un bool.

Non puoi davvero. Potresti fornire un secondo costruttore, ad esempio:

class MyClass {
  public:
    MyClass(bool bFlag); // <-- not default
    MyClass(void);       // <-- default
};

Invece di un valore booleano, utilizzare un'enumerazione. Ad esempio, per controllare il livello di magia:

enum {
    MY_ENUM_NO_MAGIC,
    MY_ENUM_SOME_MAGIC,
    MY_ENUM_MORE_MAGIC
} MagicLevel;

Quindi chiedi al tuo costruttore di accettare un parametro 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;
    }

}

Bene, se usi funzioni e classi, semplicemente sovraccaricalle.

vale a dire:

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

// e il gioco è fatto. Inoltre, non è necessario avere una classe, è possibile utilizzare solo funzioni sovraccaricate.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top