2011-11-04 17 views
13

Ad esempio: in un file di intestazione C++, se ho definito un struct Record e vorrei usarlo per l'eventuale ordinamento in modo che voglio sovraccaricare il . Ecco tre modi che ho notato in vari codici. Ho notato approssimativamente che: se ho intenzione di mettere Record in un std::set, map, priority_queue, ... contenitori, la versione 2 funziona (probabilmente anche la versione 3); se ho intenzione di salvare Record in un vector<Record> v e quindi chiamare make_heap(v.begin(), v.end()) ecc .. allora funziona solo la versione 1.C++ in meno di sovraccarico dell'operatore, quale modo di usare?

struct Record 
    { 
     char c; 
     int num; 

     //version 1 
     bool operator <(const Record& rhs) 
     { 
     return this->num>rhs.num; 
     } 

     //version 2 
     friend bool operator <(const Record& lhs, const Record& rhs) //friend claim has to be here 
     { 
     return lhs->num>rhs->num; 
     } 
    }; 

nello stesso file di intestazione, ad esempio:

 //version 3 
     inline bool operator <(const Record& lhs, const Record& rhs) 
     { 
     return lhs->num>rhs->num; 
     } 

In sostanza, vorrei gettare le domande qui per vedere se qualcuno potrebbe venire con qualche sintesi ciò che è le differenze tra questi tre metodi e quali sono i posti giusti per ogni versione?

+3

migliorare il rating di accettare. –

+0

potresti pubblicare completi programmi di esempio per ogni caso che non funziona –

+2

Non vedo nessuna versione3 –

risposta

5

Sono essenzialmente gli stessi, a parte il primo che non è const e consente di modificarsi.

preferisco la seconda per 2 motivi:

  1. Non deve essere un friend.
  2. lhs non deve essere un Record
+0

Penso che la seconda versione, se rivendichi l'operatore user268451

+0

@ user268451 Non deve essere un amico. In realtà è meglio se * non * è uno, in quanto porta a un migliore incapsulamento. – Pubby

+0

@ Pubby8 Se si desidera definire una funzione libera all'interno di una classe, è necessario aggiungere 'amico'. Questo non ha nulla a che fare con l'accesso ai membri privati. – Sjoerd

-4

Favorire in classe a meno che non possa essere in classe perché il primo argomento è il tipo sbagliato.

+2

In realtà si dovrebbe sempre favorire la classe, in modo tale che si applichino le conversioni su entrambi i tipi sinistro e destro (e non solo su quello giusto). Se possibile renderlo un non-amico, allora ancora meglio, poiché disaccoppia l'operatore dalla classe che lo implementa solo in termini di interfaccia pubblica. –

+2

Non vuoi le conversioni sugli operatori di confronto a meno che tu non sia una specie di numero! – Joshua

+1

@Joshua che non è sempre vero, se un contenitore (mappa, set di ordinamento, ...) ha bisogno di essere implementato per classi "non numeriche". – Kashyap

5

Il modo migliore per definire il meno dell'operatore è:

struct Record{ 
    (...) 
    const bool operator < (const Record &r) const{ 
     return (num < r.num); 
    } 
}; 
+2

Ciò non consente conversioni sul lato sinistro, quindi sicuramente non è il * modo migliore *. – Sjoerd

+2

Il percorso delle conversioni ipmlicit è pericoloso e il tuo non deve camminare – g24l