2009-05-05 10 views
12

Je suis en train de reconcevoir un constructeur de classe en C++ et j'en ai besoin pour attraper un bool non spécifié. J'ai utilisé les valeurs par défaut pour tous les autres paramètres, mais selon moi, bool peut seulement être initialisé à true ou false. Puisque ces deux cas ont un sens dans la classe, comment dois-je gérer la vérification d'une valeur par défaut?Valeur par défaut pour bool en C++

+7

Est-il important de savoir si vous utilisez le "faux" par défaut d'un "faux" initialisé? – RobS

Répondre

39

La réalité est que vous ne pouvez pas faire cela. Un booléen a une valeur, vrai ou faux, et si vous ne l'avez pas initialisé, il est aléatoire ou vrai, peut-être différent à chaque exécution du programme ou allocation de cette classe.

Si vous avez besoin d'un type avec plus d'options, définissez une énumération.

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

volé à thedailywtf.com? :) – JaredPar

+4

Drôle pour la référence DailyWTF. –

+0

J'aime la réponse mais je voudrais tweek un peu pour inclure un défaut au lieu de FILENOTFOUND, donc j'ai posté une autre version de la réponse – Azder

5

Si c'est ce dont vous avez besoin, créez une valeur qui représente le concept d'une valeur qui n'a peut-être pas été initialisée.

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

Vous pouvez maintenant représenter les 3 états dont vous avez besoin.

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

+1: Ce serait mieux si C++ avait des fermetures. Je suppose que vous pourriez les simuler avec des pointeurs de fonction. (PS: Je n'aime pas le nom de la classe). –

1

Je ne comprends pas tout à fait, mais je vais essayer ...

Les valeurs par défaut sont appliquées lorsque vous avez un initialiseur total qui laisse certaines valeurs non précisées. Dans ce cas, la valeur par défaut de bool est false. Dans une classe, la valeur "default" ne serait pas initialisée, ce qui signifie qu'elle pourrait être n'importe quelle valeur et pourrait changer d'une exécution à l'autre. Si vous souhaitez savoir si un booléen a changé ou non, la meilleure option est de le garder avec un second bool par défaut à false ou d'utiliser une énumération représentant 3 états possibles. Si vous voulez vraiment 3 états, vous ne voulez vraiment pas un bool.

2

Vous pouvez avoir un membre privé distinct qui indique si la valeur booléenne a été initialisée ou non.

4

En C++ un bool est seulement un bit d'information, soit un 0 ou un 1. Puisque vous voulez représenter trois états possibles, vous avez besoin d'un peu plus d'informations. Il existe deux techniques générales:

  1. Utilisez une autre valeur bool pour indiquer si la valeur est « par défaut » ou non, ou
  2. Utilisez un type d'énumération avec trois valeurs pour indiquer (par défaut, true, false).

je choisirais probablement l'option 1.

18

On dirait que vous voulez boost::tribool ou boost::optional<bool> peut-être.

+6

Vous pouvez même configurer boost :: tribool pour vos besoins DailyWTF: BOOST_TRIBOOL_THIRD_STATE (FILENOTFOUND). –

0

Au lieu d'un booléen, utilisez une énumération. Par exemple, pour contrôler le niveau de magie:

enum { 
    MY_ENUM_NO_MAGIC, 
    MY_ENUM_SOME_MAGIC, 
    MY_ENUM_MORE_MAGIC 
} MagicLevel; 

Testez ensuite votre constructeur accepte un paramètre MagicLevel magic = MY_ENUM_NO_MAGIC. Tristate bool est le chemin vers le côté obscur.

35

Tristate bool conduit à la colère. La colère mène à la haine. La haine mène à la souffrance.


Je préfère ne pas utiliser un bool trois états.

A la place, utilisez un booléen supplémentaire pour savoir si le premier booléen est "initialisé" (ou mieux, "connu") ou non.

class Prisoner : public Person 
{ 


    ... 

    bool is_veredict_known; 
    bool is_guilty; 
} 

Si le veredict ne connaît pas encore, vous ne pouvez pas dire si le prisonnier est vraiment coupable, mais votre code peut différencier entre les différentes situations. Bien sûr, la Constitution garantit que la valeur par défaut de is_guilty doit être faux, mais quand même ... :)

Par ailleurs, la classe invariant doit comprendre:

assert(is_veredict_known || !is_guilty); 
1

Vous ne pouvez vraiment pas. Pourriez-vous fournir un second constructeur, par exemple:

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

Ceci est similaire à ce qui existait déjà que l'on m'a dit de nettoyer :) – voteblake

+0

Avez-vous même besoin d'exposer le constructeur par défaut? – wreckgar23

+0

Je ne peux pas parler pour l'affiche originale, mais, en général, non vous ne le faites pas. –

3

Utilisez le super boost :: optionnel. Et non seulement pour bools mais pour tous les autres endroits que vous utilisé quelques pas initialisées valeurs sales Il est utilisé comme ceci:.

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

Et voici un exemple de fonction renvoyant une option:

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; 
    } 
} 
0
class aclass 
{ 
    <stuff> lots of other things 
    bool mybool 
    bool ismyboolinit 

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

} 
3
struct Bool { //guaranteed initialized bool 
    bool v; 

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

Eh bien, si vous utilisez des fonctions et des classes, il suffit de les surcharger.

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

// et là vous allez. De plus, vous n'avez pas besoin d'avoir une classe, vous pouvez simplement utiliser des fonctions surchargées.

Questions connexes