2010-02-28 16 views
8

Consideremos el siguiente código:Cómo devolver una referencia QString const en caso de error?

const QString& MyClass::getID(int index) const 
{ 
    if (i < myArraySize && myArray[i]) { 
     return myArray[i]->id; // id is a QString 
    } else { 
     return my_global_empty_qstring; // is a global empty QString 
    } 
} 

¿Cómo puedo evitar tener un QString vacío sin cambiar el tipo de retorno del método? (Parece que devolver una QString vacía asignada en la pila es una mala idea)

Gracias.

+4

Si bien es bueno devolver la referencia de referencia en general, creo que puede más que salirse con la suya devolviendo un QString por valor si es necesario. Es copia en escritura, muy barato de copiar. –

Respuesta

8

No puede. O bien no devolver una referencia const o utilizar una variable estática local como esto:

const QString& MyClass::getID(int index) const { 
    static const QString emptyString; 

    if (i < myArraySize && (myArray[i] != 0)) { 
     return myArray[i]->id; // id is a QString 
    } else { 
     return emptyString; 
    } 
} 

La ventaja de este método sobre los otros métodos propuestos es que esta solución no requiere un cambio a la interfaz de MyClass. Además, usar un parámetro predeterminado puede confundir a los usuarios de su clase y provocar un uso incorrecto de la clase. Esta solución es transparente para el usuario.

Por cierto, ¿realmente está usando una matriz de estilo C en su clase?

+0

No, no lo soy, fue por concisión. – moala

3

Dado que se espera que esto devuelva un valor de const no veo ningún problema con tener un QString vacío global (o estático const) que todas estas funciones utilicen para devolver una cadena vacía.

Aunque no me gusta el nombre. Esperaría que el QString "vacío" fuera un miembro estático de la clase QString. para que tu código se vea así en su lugar.

const QString& MyClass::getID(int index) const 
{ 
    if (i < myArraySize && myArray[i]) { 
     return myArray[i]->id; // id is a QString 
    } else { 
     return QString::EmptyString; // is a global empty QString 
    } 
} 
+0

De hecho, ese era el punto, ¿existe internamente para Qt (no lo encontré), o existe otra forma de hacerlo sin este QString vacío estático? – moala

+2

Estoy seguro de que existen otras formas. Pero una QString vacía estática es una buena manera de resolver este problema. No deberías tratar de evitarlo. –

0

¿Cómo sobre el uso de un valor por defecto pre-inicializado:

const QString& MyClass::getID(int index, const QString& def = QString()) const 
{ 
    if (i < myArraySize && myArray[index]) { 
     return myArray[index]->id; // id is a QString 
    } else { 
     return def; 
    } 
} 
+1

¿No se resuelve en el siguiente problema? http://stackoverflow.com/questions/667396/parameter-passed-by-const-reference-returned-by-const-reference – moala

+0

Depende de cómo lo use, si asigna esta función llame a 'const QString &' es peligroso, pero si lo asigna a un 'QString' no lo hace. Funciona bien en mi ejemplo. –

+0

Luego, al usar el valor de retorno predeterminado, en el punto de la persona que llama, se convierte en const QString y theId = getId (i, QString()); pero el QString temporal será destruido, entonces la referencia rota, ¿no es así? – moala

0

si insiste en devolver una referencia, debe tener un objeto para referirse a; así que debes tener el objeto QString en algún lugar de tu ejemplo, no hay forma de evitarlo.

Sin embargo, una técnica que parece adecuado para su caso es cambiar su método para aceptar un ID por defecto para volver por si el índice está fuera del rango:

const QString& MyClass::getID(int i, const QString& default) const 
{ 
    if(i < myArraySize && myArray[i]) 
    return myArray[i]->id; 
    else 
    return default; 
} 

También podría lanzar una excepción si el índice está fuera de rango, entonces no necesitaría regresar al fallo, pero probablemente eso no sea lo que desea.

+3

predeterminado es una mala idea ya que es una palabra clave C++ –

+1

Incluso si se ve atractivo, http://stackoverflow.com/questions/667396/parameter-passed-by-const-reference-returned-by-const-reference muestra que puede ser malo ... – moala

2

No puede evitarlo sin cambiar el tipo de devolución.

Si elige devolver una referencia, entonces tiene tiene alguna variable del tipo de devolución que supera el alcance de la función. Si no puede cambiar la API (por ejemplo, debido a las promesas de compatibilidad binaria), entonces está bloqueado en esto para siempre. Deberá perder memoria almacenando algún valor del tipo relevante, incluso si cambia el resto de la implementación de su clase a, p. genere los valores sobre la marcha o recupérelos de alguna fuente externa.

Es por eso que las guías de diseño de la API C++ que conocen los problemas de compatibilidad binaria recomiendan no devolver const& sin una consideración cuidadosa.

0

¿Sería suficiente QString :: null?

+0

Qt 4.6.2 falta dicho miembro estático de la 'QString', por algún motivo. Pero 'QString :: QString()' "construye" la cadena nula y supongo que ese constructor es algo así como 'QString :: PrivateData * private = QString :: someStaticNullData' – ony

+1

QString :: null existe en mi instancia de Qt 4.6. 2 (y, espero, el tuyo también). Está depreciado, pero sigue ahí. Si está utilizando una plataforma que usa archivos ELF, Mach-O o PE (Linux, * BSD, MacOS, Windows), debería poder usar QString :: null muy bien. Las plataformas integradas probablemente tengan más restricciones. http://lists.trolltech.com/qt-interest/2005-11/msg01002.html – blarf

0

No puede evitar la necesidad de un QString vacío sin cambiar la forma en que getId() funciona. Pero hay dos enfoques que nos vienen a la mente:

  • en lugar de devolver silenciosamente una cadena vacía, lanzar una excepción; o
  • no te molestes en devolver una referencia, y simplemente devuelve un QString, dependiendo de return value optimization para eliminar el costo de copiar el objeto.
Cuestiones relacionadas