2012-05-13 26 views
29

Qual è la migliore prassi (in questo caso):confronto l'overloading degli operatori

bool Foo::operator==(const Foo& other) { 
    return bar == other.bar; 
} 

// Implementation 1 
bool Foo::operator!=(const Foo& other) { 
    return bar != other.bar 
} 

// Implementation 2 
bool Foo::operator!=(const Foo& other) { 
    return !(*this == other); 
} 

Per operatori come>, <, < =,> = vorrei andare con implementazione 2, quando possibile. Tuttavia, per! = Penso che l'implementazione 1 sia migliore poiché non viene effettuata un'altra chiamata al metodo, è corretto?

+0

Lo scriverei nel modo più naturale per esprimerlo correttamente. Probabilmente il compilatore farà un ottimo lavoro di compilazione in qualunque modo tu scelga. – Flexo

+0

Ok, grazie. Come nota a margine, so che se il == è troppo complesso, allora l'implementazione 2 sarebbe migliore, ma questo è un altro caso. – blaze

+0

È necessario aggiungere un 'const' a ciascuna delle funzioni. Considera anche l'uso di funzioni libere piuttosto che funzioni membro, poiché le prime sono simmetriche rispetto a tipi e conversioni in cui queste ultime non lo sono. Questo è più importante se il tuo tipo può essere convertito implicitamente da altri tipi. –

risposta

29

La seconda implementazione ha il notevole vincolo che == sarà sempre il contrario booleano di !=. Questo è probabilmente ciò che desideri e rende il tuo codice più facile da mantenere perché devi solo cambiare un'implementazione per mantenere i due sincronizzati.

+7

E ogni compilatore C++ sul pianeta effettuerà la chiamata in linea! = '==. – jthill

+1

@jthill Fai attenzione: non lo farà se l'operatore non è ancora definito (ad esempio file sorgente). – Tim

+3

@Tim, potrebbe se il tuo compilatore ha LTO. – zneak

11

È necessario utilizzare sempre ciò che si ha quando si sovraccaricano gli operatori di confronto. Gli unici due che dovresti definire sono operator== e operator<. Il resto puoi scrivere in termini di questi due. È meno soggetto a errori, come se si avesse un errore, è solo in un posto.

Una delle caratteristiche principali di OOP è la riusabilità del codice. Se hai già scritto il codice, perché scrivere di nuovo? Rimani fedele a ciò che hai e avrai solo una cosa da testare.

È piuttosto come dichiarare una costante e quindi utilizzarla in diversi punti del file.

+0

In realtà, è necessario solo l'operatore <''. Perché x == y è logicamente equivalente a! (X mdenton8

+0

@ mdenton8, certo, ma è idiomatico definire sia l'operatore <'che l'operatore ==' da zero se si vogliono tutti gli operatori di confronto. Alcuni algoritmi e contenitori di C++ STL useranno 'operator ==' per l'uguaglianza e alcuni useranno l'operatore <'nel modo in cui lo descrivete. È vero che se fanno cose diverse, potresti avere dei risultati sorprendenti quando usi determinati algoritmi. – chris

+0

È vero, spesso può essere più efficiente e più chiaro. Ma meno gestibili per le stesse ragioni che hai menzionato sopra. – mdenton8

4

L'implementazione 2 è migliore perché utilizza l'operatore già definito ==. Anche quelle funzioni dell'operatore dovrebbero essere const perché non modificano l'oggetto.

+0

Grazie per il suggerimento – blaze

+0

Non posso essere sicuro di quale sia esattamente il mio setup causato da questo (boost.optional, forse) ma ho ricevuto un carico di errori come 'stl_algobase.h: 808: 22: errore: nessuna corrispondenza per ' operatore == ''fino a quando ho dichiarato le funzioni' const' Grazie per averlo indicato. – MatrixManAtYrService

1

In generale, l'implementazione 2 è migliore per molte ragioni. Prima di tutto, non scrivi (quasi) codice duplicato. Se hai bisogno di cambiarlo (perché la classe è cresciuta o c'è stato un bug), di nuovo con l'implementazione 2 cambi solo 1 posto. In altre parole, l'implementazione 2 rende il codice più coerente e meno soggetto a errori.

3

Nessuno dei precedenti.

Vorrei poter trovare la carta che supera davvero questo dettaglio ma non riesco a ricordare il nome.

Le operazioni di confronto devono essere esterne. La tua interfaccia dovrebbe essere sufficiente per trovare lo stato di un oggetto e lo stato dell'oggetto dovrebbe essere il dettare il confronto. Dovrebbe essere possibile scrivere "uguali" al di fuori della vostra classe, e quindi qualsiasi confronto in realtà, e che sia possibile ... lo si desidera.

+2

Questo non è sempre vero. Ci possono essere progetti in cui non si desidera garantire l'accesso a tutto lo stato. Inoltre, puoi sempre concedere l'accesso a una funzione gratuita attraverso l'amicizia. –

Problemi correlati