2010-02-28 10 views
8

considerare il seguente codice:Come restituire un riferimento const QString in caso di errore?

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

Come posso evitare di avere un vuoto QString senza cambiare il tipo di ritorno del metodo? (Sembra che restituire una QString vuota allocata nello stack sia una cattiva idea)

Grazie.

+4

Mentre è opportuno restituire il riferimento const in genere, penso che si possa ottenere più che restituire una QString in base al valore se necessario. È una copia scritta, molto economica da copiare. –

risposta

8

Non è possibile. O non restituire un riferimento const o utilizzare una variabile statica locale come questo:

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

Il vantaggio di questo metodo rispetto agli altri metodi proposti è che questa soluzione non richiede una modifica all'interfaccia di MyClass. Inoltre, l'utilizzo di un parametro predefinito potrebbe confondere gli utenti della tua classe e portare a un uso errato della classe. Questa soluzione è trasparente per l'utente.

A proposito, stai davvero usando un array in stile C nella tua classe?

+0

No, non lo sono, era per la concisione. – moala

3

Poiché si prevede che restituisca un valore const, non vedo alcun problema con un QString globale (o statico) vuoto che viene utilizzato da tutte queste funzioni per restituire una stringa vuota.

Non sono affatto arrabbiato per il nome. Mi aspetto che il QString "vuoto" sia un membro const const della classe QString. quindi il tuo codice sarebbe simile a questo.

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

In effetti, questo era il punto, esiste internamente a Qt per quello (non l'ho trovato) o esiste un altro modo per farlo senza questo QString statico vuoto? – moala

+2

Sono sicuro che esistono altri modi. Ma un QString statico e vuoto è un buon modo per risolvere questo problema. Non dovresti cercare di evitarlo. –

0

Come sull'utilizzo di un valore di default pre-inizializzato:

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

Non si risolve nel seguente problema? http://stackoverflow.com/questions/667396/parameter-passed-by-const-reference-returned-by-const-reference – moala

+0

Dipende da come lo si utilizza, se si assegna questa chiamata di funzione a 'const QString &' è pericoloso, ma se lo assegni ad un 'QString' non lo fa. Funziona bene nel mio esempio. –

+0

Quindi, quando si utilizza il valore di ritorno predefinito, nel punto del chiamante, diventa const QString e theId = getId (i, QString()); ma la QString temporanea verrà distrutta, quindi il riferimento rotto, non è vero? – moala

0

se ti ostini a restituire un riferimento, è necessario disporre di un oggetto per riferirsi a; quindi devi avere l'oggetto QString da qualche parte nel tuo esempio, non c'è modo di aggirarlo.

Tuttavia una tecnica che sembra adatto per il vostro caso è quello di modificare il metodo di accettare un ID predefinito per tornare nel caso in cui l'indice è fuori portata:

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

Si potrebbe anche un'eccezione se l'indice è fuori portata, quindi non è necessario tornare in caso di errore, ma probabilmente non è ciò che si desidera.

+3

predefinito è una cattiva idea poiché è una parola chiave C++ –

+1

Anche se sembra attraente, http://stackoverflow.com/questions/667396/parameter-passed-by-const-reference-returned-by-const-reference mostra che potrebbe essere un male ... – moala

2

Non è possibile evitarlo senza modificare il tipo di ritorno.

Se si sceglie di restituire un riferimento, è necessario che disponga di una variabile del tipo restituito che sopravvive all'ambito della funzione. Se non riesci a modificare l'API (ad esempio a causa di promesse di compatibilità binaria), sei bloccato a questo per sempre. Dovrai sprecare memoria memorizzando un valore del tipo pertinente, anche se modifichi il resto dell'implementazione di classe ad es. generare i valori al volo o recuperarli da una fonte esterna.

Ecco perché le guide di progettazione API C++ che sono a conoscenza dei problemi di compatibilità binaria raccomandano di non restituire un const& senza un'attenta considerazione.

0

QString: null è sufficiente?

+0

Qt 4.6.2 manca un membro statico del 'QString', per qualche motivo. Ma 'QString :: QString()' "costruisce" la stringa nulla e immagino che il costruttore sia qualcosa come 'QString :: PrivateData * private = QString :: someStaticNullData' – ony

+1

QString :: null esiste nella mia istanza di Qt 4.6. 2 (e, mi aspetto, anche il tuo). È deprezzato, ma è ancora lì. Se stai usando una piattaforma che usa file ELF, Mach-O o PE (Linux, * BSD, MacOS, Windows) dovresti essere in grado di usare QString :: null bene. Le piattaforme integrate probabilmente hanno più restrizioni. http://lists.trolltech.com/qt-interest/2005-11/msg01002.html – blarf

0

Non è possibile evitare la necessità di una QString vuota senza modificare il modo in cui funziona getId(). Ma ci sono due approcci che mi vengono in mente:

  • invece di restituire una stringa vuota, lanciare un'eccezione; oppure
  • non preoccupatevi di restituire un riferimento e restituite semplicemente un QString, facendo affidamento su return value optimization per eliminare il costo della copia dell'oggetto.
Problemi correlati