2012-03-04 11 views
14

Mam tutaj całkowicie podstawowe pytanie w języku C++.Jak działa łańcuchowanie operatora w C++?

#include <iostream> 
using namespace std; 

int main() { 
    int a = 255; 
    cout << hex << a << endl; // <----- 
} 

w kawałku kodu powyżej, jak jest stwierdzenie std::cout przykuty?

Rozumiem, że implementacja cout wróci odniesienie do cout obiektu w celu umożliwienia łączenia się zdarzyć, więc powinno być wykonywane jako:

(((cout << hex) << a) << endl) 

czyli równoważne do tych, w celu

  1. cout << hex
  2. cout << a
  3. cout << endl

Ale to nie może być przypadek, bo jakoś wartość a należy przekonwertować do hex formie!

W jaki sposób operatorzy są powiązani przez kompilator, aby dokonać konwersji?

Odpowiedz

7

Oto jak hex jest zazwyczaj realizowane:

inline ios_base& 
hex(ios_base& __base) 
{ 
    __base.setf(ios_base::hex, ios_base::basefield); 
    return __base; 
} 

Jak widać, hex nie wykonuje żadnej konwersji sam: zamiast, ustawia odpowiednią opcję w strumieniu podstawy do korzystania z hex do drukowania liczby przekazywane do niego w późniejszym czasie.

EDIT (w odpowiedzi na komentarz)

Jak słusznie zauważa hammar, druga część układanki jest jak hex(ios_base& __base) jest nazywany. Jest przeciążenie operatora << z tym podpisem:

ostream& operator <<(ostream& (*)(ostream&)) 

To przeciążenie jest niezbędna detal realizacja stream manipulators. To przeciążenie wywołuje hex i pozwala mu wykonywać swoją "magię" (co oczywiście nie powinno już brzmieć jak magia).

+1

Powinieneś prawdopodobnie także wspomnij o innej części układanki, o przeciążeniu 'ostream & operator << (ostream & (*) (ostream &)), w ten sposób wywoływane są manipulatory takie jak' hex'. – hammar

+0

@hammar Świetna obserwacja! Dziękuję bardzo za komentarz, zredagowałem odpowiedź, aby odzwierciedlić tę istotną kwestię. – dasblinkenlight

22

Masz rację, tak właśnie działa. hex ma tylko specjalny typ, który zmienia stan wewnętrzny obiektu cout po przejściu na jego funkcję operator<<. Stan wewnętrzny określa, w jaki sposób są przetwarzane przyszłe wartości przekazywane do cout przez .

std::hex jest funkcją. cout << hex nie wywołuje funkcji heksadecymalnej jako takiej, jednak: przekazuje wskaźnik do funkcji heksadecymalnej do przeciążenia operator<< dla ostream, która akceptuje wskaźniki funkcji z konkretną sygnaturą. hex() jest następnie wywoływany z poziomu implementacji operatora przez ten wskaźnik funkcji i modyfikuje obiekt ostream stamtąd, o ile wiem.

+0

'hex' nie jest * specjalnym rodzajem *. To jest funkcja. (lub po prostu mówiąc, 'hex' * ma * specjalny typ, nie ma sensu Co to znaczy * tutaj *?) – Nawaz

+1

Tak, zdarza się, że ma typ funkcji. Jest to typ, który określa, które 'operator <<' zostanie wywołane. 'cout << hex' nie wywołuje funkcji' hex' jako takiej: przekazuje wskaźnik do funkcji heksadecymalnej na przeciążenie 'operator <<', które przyjmuje wskaźniki funkcji z określoną sygnaturą. 'hex()' jest następnie wywoływane z poziomu implementacji operatora, o ile wiem. – pmdj

+0

+1. Teraz odpowiedź wygląda lepiej. – Nawaz

2

std::hex w rzeczywistości ustawia flagę wewnątrz obiektu std::cout, który będzie się trzymać do czasu zresetowania IIRC. Same operator<< są oceniane od lewej do prawej, więc twoje pareny są poprawne.

1

Z mojego punktu widzenia hex jest po prostu obiektem pakietu, który ma efekt uboczny na obiekcie cout. Po tej cout będą wyświetlać tylko wartości szesnastkowe.