2010-07-29 21 views
19

Con todos los tipos fundamentales de C++, uno puede simplemente consulta:C++ convertir clase a booleano

if(varname) 

y el tipo se convierte en un valor booleano para la evaluación. ¿Hay alguna forma de replicar esta funcionalidad en una clase definida por el usuario? Una de mis clases se identifica por un número entero, aunque tiene varios otros miembros, y me gustaría poder verificar si el entero se establece en NULL de esa manera.

Gracias.

+0

Google para "booleano seguro" y verá diferentes soluciones que permiten la evaluación booleana sin conversión explícita a bool, evitando las trampas comunes de conversión. –

Respuesta

18

Puede definir un operador de conversión definido por el usuario. Debe ser una función miembro, p. Ej .:

class MyClass { 
    operator int() const 
    { return your_number; } 
    // other fields 
}; 

También puede implementar el operador bool. Sin embargo, quisiera FUERTEMENTE, sugiero no hacerlo porque su clase será utilizable en expresiones aritméticas que pueden llevar rápidamente a un desastre. IOStreams define, por ejemplo, la conversión a void*. Puede probar void* de la misma manera que puede probar un bool, pero no hay conversiones implícitas definidas en el lenguaje desde void*. Otra alternativa es definir operator! con la semántica deseada.

En resumen: la definición del operador de conversión de tipos enteros (incluidos los booleanos) es realmente una mala idea.

+0

Usted declara que la conversión a tipos enteros es una mala idea ... pero esto es exactamente lo que hace su fragmento de código. Acordé que 'operator bool()' tiene consecuencias imprevistas y hay mejores soluciones. Pero la conversión a vacío * tampoco es perfecta: 'Foo x; delete x; 'ahora se compilará. 'bool operator!()' es mejor, pero igual tiene que hacer 'if (!! x)' para probar el caso positivo. Como se sugiere en otro comentario, la expresión de Safe Bool es la mejor solución. –

+3

1) El OP claramente no conocía la sintaxis para definir operadores de conversión, de lo contrario, habría sido capaz de codificar la solución más trivial. Entonces aprendió algo nuevo. 2) Le advertí que esta era una mala idea. 3) Safe bool es mejor, pero parece una sobreingeniería. Si la conversión a void * es buena para la biblioteca estándar, también es bueno para mí. – zvrba

+5

En C++ 11 existe el operador explícito bool() '(mencionado en @plats answer y @UncleBens comment) que logra lo que el OP quiere. Creo que sería bueno si esta información se incluyera en la respuesta aceptada. – fhahn

9

Simplemente implemente operator bool() para su clase.

p. Ej.

class Foo 
{ 
public: 
    Foo(int x) : m_x(x) { } 
    operator bool() const { return (0 != m_x); } 
private: 
    int m_x; 
} 

Foo a(1); 
if (a) { // evaluates true 
    // ... 
} 

Foo b(-1); 
if (b) { // evaluates true 
    // ... 
} 

Foo c(0); 
if (c) { // evaluates false 
    // ... 
} 
+3

-1, esto se rompe fácilmente de manera no evidente. Busque la frase idiomática "Safe Bool". – greyfade

+3

C++ 0x tiene 'operador explícito bool()' para evitar la rotura implícita del tipo? – UncleBens

+0

@grayfade: de acuerdo: esta solución no es ideal y la expresión de Safe Bool es más robusta. –

-1

C++ comprueba si el resultado de las declaraciones es igual a cero o no. Entonces creo que puede definir el operador de igualdad para su clase y definir cómo su clase será diferente de cero en qué condiciones.

+0

No realmente ... el valor se convierte en booleano. Es solo que, en general, la conversión se realiza de '0' a' false' y de cualquier otra cosa a 'true'. La diferencia importante es que si defines 'bool operator == (type const &, int);' y 'bool operator == (int, type const &);' puedes comparar tu objeto a '0' pero no puedes usar el objeto como una condición. –

3

Como han dicho otros, utilizar operator int() o operator bool() es una mala idea debido a las conversiones que permite. Usar un puntero es una mejor idea. La mejor solución a este problema conocimientos hasta ahora es devolver un miembro (función) del puntero:

class MyClass { 
    void some_function() {} 

    typedef void (MyClass:: * safe_bool_type)(); 
    operator safe_bool_type() const 
    { return cond ? &MyClass::some_function : 0; } 
}; 
14

El enfoque C++ 11 es:

struct Testable 
    { 
    explicit operator bool() const 
     { return false; } 
    }; 

int main() 
    { 
    Testable a, b; 
    if (a)  { /* do something */ } // this is correct 
    if (a == b) { /* do something */ } // compiler error 
    } 

Nota explicit la palabra clave que impide que el compilador convirtiendo implícitamente.

+2

Esta debería ser la respuesta más aceptada y máxima. –