2017-09-30 29 views
7

Klasa C++ o numerze ostream zapewnia wiele domyślnych przeciążeń dla operator<<, jednak nie wszystkie są zdefiniowane w ten sam sposób.Przeciążenia operatorów statycznych i użytkowników: std :: operator << i std :: ostream :: operator <<

W overloads do char typy string typy i strumienie RValue są określone jako wolne namespace -Zakres funkcji, takich jak:

namespace std { 
ostream &operator<<(ostream &os, char c); 
} 

Choć overloads dla typów arytmetycznych streambuf i manipulatorów strumienia są określone jako członka funkcje std::ostream takie jak:

namespace std { 
ostream &ostream::operator<<(int val); 
} 

moje pytanie

Czy istnieje powód takiego rozróżnienia? Rozumiem, że połączenia z tymi przeciążeniami operatorów działają nieco inaczej (np. ADL dla wolnych definicji namespace), więc wyobrażam sobie, że może być preferowany szczególny typ przeciążenia operatora w celu optymalizacji. Ale tutaj std::ostream używa obu typów definicji dla różnych typów. Czy istnieją jakieś korzyści z tej optymalizacji semantycznej lub implementacyjnej, na którą to pozwala?

Odpowiedz

5

bym sobie wyobrazić, że może być korzystne dla danego rodzaju przeciążenia operatora do celów optymalizacji

No, no. Na koniec dnia oba są preformowane jako wywołania funkcji. Nie ma nawet widocznej implikacji dla samej rozdzielczości. Ponieważ średnia dyktuje w [over.match] ust 2 i 6:

Jeśli albo operandów jest typu, który jest klasa lub wyliczenie, funkcję operatora zdefiniowany przez użytkownika może być zadeklarowane, że realizuje to Operator lub konwersja zdefiniowana przez użytkownika może być konieczna do przekonwertowania argumentu na typ odpowiedni dla wbudowanego operatora. W tej obudowie używana jest rozdzielczość przeciążania w celu określenia, która funkcja operatora ma zostać wywołana w celu wdrożenia operatora.

Zestaw funkcji kandydujących do oceny przeciążenia jest związkiem kandydatów członków, kandydatów niebędących członkami oraz wbudowanych kandydatów . Lista argumentów zawiera wszystkie operandy operatora . Najlepsza funkcja z zestawu funkcji kandydujących to wybrana zgodnie z opcjami [over.match.viable] i [over.match.best].

Wszystkie przeciążenia operatora są rozwiązywane łącznie. Jedyną różnicą semantyczną jest to, że klasa wywodząca się z ostream może wybrać ukryć przeciążenie niektórych członków. Odbywa się to zgodnie z tym, jak przeciążanie działa w klasie pochodnej. Mogą być stosowane tylko wyraźnie zadeklarowane przeciążenia. W przeciwieństwie do tych członków, przeciążenia wolnej funkcji zawsze będą brać udział w przeciążeniu, nawet dla klas wywodzących się z ostream.

Ponieważ klasa pochodna musi zostać przekonwertowana na ostream&, aby można było wybrać przeciążenie dowolnej funkcji, należy uszeregować jego własną, niejawną sekwencję konwersji.I może powodować niejasności, jeśli wszystkie przeciążenia są wolnymi funkcjami.

Tak więc rozważanie może bardzo dobrze oddzielić typy, które mogą powodować niejednoznaczność (wskaźniki i typy arytmetyczne) od typów użytecznych, które zawsze możemy chcieć mieć (wskaźniki do C-stringów i pojedynczych znaków). I pozwól ukryć te "mniej przydatne", aby uniknąć tych niejednoznaczności.


Jak wskazał W.F. ostream jest w rzeczywistości basic_ostream<char>. Darmowe funkcje są dostępne tylko dla danych, które wymagają tylko przesyłania strumieniowego. Znaki lub łańcuchy w natywnym "alfabecie" strumieni. Tak więc dla basic_ostream<wchar_t> te bezpłatne funkcje będą akceptować wchar_t i wchar_t*. Jest całkiem możliwe, że proste przesyłanie strumieniowe nie wymaga dostępu do sekcji prywatnych strumieni.

Pozostałe przeciążenia dotyczą danych wymagających serializacji przed przesłaniem strumieniowym. Ponieważ wspomniana serializacja jest ściśle powiązana ze stanem wewnętrznym strumieni, rozsądniej jest uczynić te przeciążenia członkami.

+0

"W przeciwieństwie do tych członków, przeciążenia wolnej funkcji zawsze będą brać udział w przeciążeniu, nawet dla klas, które pochodzą od ostream". Ale nie możesz ukryć wolnych funkcji z innymi darmowymi funkcjami, które pasują do bardziej konkretnego zakresu w ADL. –

+0

Nie jest również jasne, w jaki sposób niejawne konwersje do 'ostream &' z klas wyprowadzone z 'ostream' mogą powodować niejednoznaczności w rozwiązywaniu wolnych funkcji? Przepraszam! –

+1

@definecindyconst - Nie ukrywa ich. Tylko przeciąża je. Członek [jest naprawdę ukryty] (https://ideone.com/d7XLZh). – StoryTeller

Powiązane problemy