Soy bastante nuevo en C ++, así que tiendo a diseñar con muchos Java-isms mientras aprendo. De todos modos, en Java, si tuviera una clase con un método de 'búsqueda' que devolviera un objeto T
de un Collection< T >
parámetro que coincidiera con un parámetro específico, devolvería ese objeto y si el objeto no se encontrara en la colección, volvería null
. Luego, en mi función de llamada, solo verificaríaif(tResult != null) { ... }
En C ++, descubro que no puedo devolver un null
valor si el objeto no existe. Solo quiero devolver un 'indicador' de tipo T que notifica a la función de llamada que no se ha encontrado ningún objeto. No quiero lanzar una excepción porque no es realmente una circunstancia excepcional.
Así es como se ve mi código en este momento:
class Node {
Attr& getAttribute(const string& attribute_name) const {
//search collection
//if found at i
return attributes[i];
//if not found
return NULL; // what should this be?
}
private:
vector<Attr> attributes;
}
¿Cómo puedo cambiarlo para poder dar ese tipo de marcador?
fuente
std::find(first, last, value)
devuelvelast
si ningún elemento coincide.Respuestas:
En C ++, las referencias no pueden ser nulas. Si desea devolver opcionalmente null si no se encuentra nada, debe devolver un puntero, no una referencia:
De lo contrario, si insiste en regresar por referencia, debe lanzar una excepción si no se encuentra el atributo.
(Por cierto, me preocupa un poco que su método sea
const
y devuelva un noconst
atributo. Por razones filosóficas, sugeriría regresarconst Attr *
. Si también desea modificar este atributo, puede sobrecargar con un noconst
método devolviendo un noconst
atributo también.)fuente
nullptr
lugar deNULL
por c ++ 11 ahora?Aquí hay varias respuestas posibles. Quiere devolver algo que pueda existir. Aquí hay algunas opciones, que van desde la menos preferida a la más preferida:
Devuelve por referencia y la señal no se puede encontrar por excepción.
Es probable que no encontrar atributos sea una parte normal de la ejecución y, por lo tanto, no sea muy excepcional. El manejo de esto sería ruidoso. No se puede devolver un valor nulo porque es un comportamiento indefinido tener referencias nulas.
Regresar por puntero
Es fácil olvidarse de verificar si un resultado de getAttribute sería un puntero no NULL y es una fuente fácil de errores.
Utilice Boost.Optional
Un impulso :: opcional significa exactamente lo que está sucediendo aquí y tiene métodos fáciles para inspeccionar si se encontró tal atributo.
Nota al margen: std :: Optional se votó recientemente en C ++ 17, por lo que esto será algo "estándar" en un futuro próximo.
fuente
boost::optional
no implica mucha sobrecarga (sin asignación dinámica), por lo que es tan bueno. Usarlo con valores polimórficos requiere ajustar referencias o punteros.Puede crear fácilmente un objeto estático que represente un retorno NULO.
Y en algún lugar de un archivo fuente:
fuente
Si desea un
NULL
valor de retorno, debe usar punteros en lugar de referencias.Las referencias no pueden ser en sí mismas
NULL
.(Nota para los futuros carteles de comentarios: Sí, puede hacer que la dirección de una referencia sea NULL si realmente lo intenta).
Vea mi respuesta aquí para obtener una lista de diferencias entre referencias y punteros .
fuente
Como ha descubierto, no puede hacerlo de la forma en que lo ha hecho en Java (o C #). Aquí hay otra sugerencia, puede pasar la referencia del objeto como un argumento y devolver un valor bool. Si el resultado se encuentra en su colección, puede asignarlo a la referencia que se está pasando y devolver 'verdadero'; de lo contrario, devolver 'falso'. Considere este código.
La función anterior tiene que encontrar el Operador contra la clave 'token', si encuentra la que devuelve verdadero y asigna el valor al parámetro Operador & op.
El código de la persona que llama para esta rutina se ve así
fuente
La razón por la que no puede devolver NULL aquí es porque ha declarado su tipo de retorno como
Attr&
. El final&
hace que el valor de retorno sea una "referencia", que es básicamente un puntero garantizado de no ser nulo a un objeto existente. Si desea poder devolver un valor nulo, cambieAttr&
aAttr*
.fuente
No puede regresar
NULL
porque el tipo de retorno de la función es un objetoreference
y no unpointer
.fuente
Puedes probar esto:
fuente