2012-06-07 7 views
10

Disculpas por mi terminología incorrecta.¿Cuál es el equivalente no puntero de NULL?

que tienen una porción de código que devuelve un puntero NULL si una entrada no existe:

ObjectType * MyClass::FindObjectType(const char * objectTypeName) 
{ 
    if (objectTypeMap.find(objectTypeName) == objectTypeMap.end()) 
    { 
     Msg("\n[C++ ERROR] No object type: %s", objectTypeName); 
     return NULL; 
    } 
    else 
     return &objectTypeMap[ objectTypeName ]; 
} 

quiero hacer lo mismo pero esta vez de devolver un objeto en lugar de simplemente un puntero. El siguiente código no me da ningún error de compilación (que me sorprende):

ObjectType MyClass::FindObjectType(const char * objectTypeName) 
{ 
    if (objectTypeMap.find(objectTypeName) == objectTypeMap.end()) 
    { 
     Msg("\n[C++ ERROR] No object type: %s", objectTypeName); 
    } 
    else 
     return objectTypeMap[ objectTypeName ]; 
} 

Con el puntero puedo comprobar si la entrada no se ha encontrado de esta manera:

if (FindObjectType(objectType) == NULL) 
    //Do something 

¿Cómo puedo realizar la comprobación equivalente con el objeto que se devuelve?

+3

'impulso :: opcional' o una excepción. – GManNickG

Respuesta

12

No existe un nivel de idioma equivalente para los objetos.

Una opción es crear un objeto "centinela" que está garantizado para comparar desigual a cualquier objeto "real", y volver que:

class ObjectType { 
public: 
    static const ObjectType null; 

    bool operator==(const ObjectType &rhs) const { /* need an appropriate comparison test */ } 

    ... 
}; 

ObjectType ObjectType::null(/* something unique */); 


... 

ObjectType foo(const char *objectTypeName) { 
    if (cond) { 
     return objectTypeMap[objectTypeName]; 
    } else { 
     return ObjectType::null; 
    } 
} 


... 

if (foo(objectType) == ObjectType::null) { 
    std::cout << "Returned the null object\n"; 
} 
+0

Gracias por su respuesta. ¿Podrías demostrar cómo se hace esto? –

+0

@PhloxMidas: ¿Es suficiente el pseudocódigo en mi respuesta? –

4

El siguiente código no está dando un error debido a que el estándar es muy conservador.

Algunas estructuras de código son extremadamente intrincadas y el compilador no puede saber si se puede alcanzar o no el final de la función. Por lo tanto, la norma dice que el compilador no tiene que probar que la función devuelve un valor correctamente ...

Sin embargo la Norma Qué dice que en caso de una función finaliza normalmente (sin excepción) sin haber devuelto un valor, entonces Comportamiento indefinido se invoca (es decir, cualquier cosa puede suceder, probablemente un bloqueo). La mayoría de los compiladores tienen una advertencia para tal situación, para gcc y Clang puede usar -Wreturn.


Ahora bien, el principio de nulidad o centinela valores no es nueva, y un puntero nulo es sólo uno encarnación (entre muchos).

Si no tiene sentido para su objeto sea anulable (rara vez lo hace, pero puede ser un recurso) entonces tienes 2 alternativas:

  • throw una excepción para señalar el error
  • cambio una clase de contenedor (como boost::optional<ObjectType>) que puede ser nula

en esta condición, ya que se espera que Find puede no encontrar nada, se lo recomiendo a este último en general.

uso es simple:

boost::optional<ObjectType> MyClass::FindObjectType(char const* objectTypeName) 
{ 
    if (objectTypeMap.find(objectTypeName) == objectTypeMap.end()) { 
     // do not print anything, it is up to the caller to decide what to do 
     return boost::none; 
    } 

    return objectTypeMap[ objectTypeName ]; 
} 

Y entonces la persona que llama, escribe:

int main(int argc, char* argv[]) { 
    if (boost::optional<ObjectType> o = MyClass::FindObject(argv[1])) { 
     o->foo(); 

     return 0; 
    } 

    Msg("\n[C++ ERROR] No object type: %s", argv[1]); 
    return 1; 
} 
+0

¿'boost :: none' se puede convertir a' false'? – Nawaz

+0

@Nawaz: No lo creo ... y no entiendo por qué lo preguntas en realidad. –

+0

@Nawaz: 'impulsar :: opcional ' puede usarse en expresiones booleanas, basándose en una variante de la [modismo bool seguro] (http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Safe_bool) . Entonces puede escribir 'if (myOptional)' para probar la presencia del valor (o 'if (! MyOptional)' para probar su ausencia). –

Cuestiones relacionadas