2011-11-04 23 views
13

Na przykład: w pliku nagłówkowym C++, jeśli zdefiniowałem struct Record i chciałbym go użyć do ewentualnego sortowania, tak że chcę przeciążać less operator. Oto trzy sposoby, które zauważyłem w różnych kodach. Z grubsza zauważyłem, że: jeśli mam zamiar wstawić Record do kontenerów std::set, map, priority_queue, ..., wersja 2 działa (prawdopodobnie także wersja 3); jeśli zamierzam zapisać Record w vector<Record> v, a następnie zadzwonić pod numer make_heap(v.begin(), v.end()) ... wtedy działa tylko wersja 1.C++ mniej przeciążenia operatora, jaki sposób użyć?

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

w tym samym pliku nagłówka na przykład:

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

Zasadniczo chciałbym rzucać pytania tutaj, aby zobaczyć, czy ktoś mógłby wymyślić jakiegoś podsumowania, co się różnice między tymi trzema metodami i jakie są właściwe miejsca dla każdej wersji?

+3

Poprawa zaakceptować ocenę. –

+0

Czy możesz przesłać kompletne przykładowe programy dla każdego przypadku, który nie działa –

+2

Nie widzę wersji3 –

Odpowiedz

5

Są one w zasadzie takie same, z wyjątkiem pierwszego, który nie jest stały i pozwala na modyfikację samego siebie.

wolę drugi dla 2 powodów:

  1. To nie musi być friend.
  2. lhs nie musi być Record
+0

Wydaje mi się, że druga wersja, jeśli zgłosisz się do operatora user268451

+0

@ user268451 To nie musi być przyjaciel. Najlepiej, jeśli to * nie jest * jedna, ponieważ prowadzi do lepszej enkapsulacji. – Pubby

+0

@ Pubby8 Jeśli chcesz zdefiniować bezpłatną funkcję z klasy, musisz dodać 'friend'. Nie ma to nic wspólnego z dostępem do prywatnych członków. – Sjoerd

-4

Faworyzowanie w klasie, chyba że nie może być w klasie, ponieważ pierwszy argument jest nieprawidłowy.

+2

W rzeczywistości zawsze należy faworyzować poza klasą, aby zastosować konwersje zarówno na lewy, jak i na prawy (a nie tylko na właściwy). Jeśli to możliwe, aby uczynić go przyjacielem, to jeszcze lepiej, ponieważ oddziela operatora od klasy implementującej go tylko pod względem interfejsu publicznego. –

+2

Nie chcesz konwersji na operatory porównania, chyba że masz jakiś numer! – Joshua

+1

@Joshua nie zawsze jest prawdą, jeśli jakiś kontener (mapa, sortowany zestaw ...) tego wymaga, możesz go zaimplementować dla klas "nieliczbowych". – Kashyap

5

Najlepszym sposobem na zdefiniowanie mniej operatora jest:

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

To nie zezwala na konwersje po lewej stronie, więc zdecydowanie nie jest * najlepszym sposobem *. – Sjoerd

+2

Ścieżka konwersji ipmlicit jest niebezpieczna, a Twój nie będzie chodził – g24l

Powiązane problemy