This, friend, operatory. this dostępny w każdej niestatycznej metodzie dostępny w każdej niestatycznej metodzie jest to wskaźnik do obiektu na rzecz którego.

Slides:



Advertisements
Podobne prezentacje
Tablice 1. Deklaracja tablicy
Advertisements

C++ wykład 2 ( ) Klasy i obiekty.
C++ wykład 4 ( ) Przeciążanie operatorów.
Język C/C++ Funkcje.
Programowanie obiektowe
Deklaracje i definicje klas w C++ Składowe, pola, metody Konstruktory
Programowanie obiektowe
Programowanie obiektowe PO PO - LAB 4 Wojciech Pieprzyca.
Metody wirtualne.
Wzorce.
Prowadzący: mgr inż. Elżbieta Majka
Static, const, volatile.
Dziedziczenie. Po co nam dziedziczenie? class osoba { char * imie, char * imie, * nazwisko; * nazwisko;public: void wypisz_imie(); void wypisz_imie();
formatowanie kodu źródłowego
Szablony (wzorce) Przykład 1: Szablon klasy -
Licznik template<class Count_Type> class Count { public:
ODE Triggery. Wstęp n Triggery są trójką zdarzenie-warunek-akcja (event-condition- action). n Zdarzenia mogą być proste lub złożone, co zostanie omówione.
Struktury.
1 Dygresja: cztery płyty główne…. 2 Dygresja: osobliwości C /* cos o nieistniejacym typie Boolean */ /* oraz o operatorze przecinkowym */ #include int.
C++ wykład 2 ( ) Klasy i obiekty.
Zasady zaliczenia Warunki uzyskania zaliczenia:
Wykład 1: Wskaźniki Podstawy programowania Programowanie w C
Informatyka I Wykład 5 OPERATORY Priorytety i kolejność obliczeń
Podstawy informatyki 2013/2014
Informatyka I Wykład 10 WSKAŹNIKI I ADRESY Jerzy F. Kotowski.
T: Różnice pomiędzy programowaniem strukturalnym a obiektowym
Programowanie obiektowe III rok EiT
Jerzy F. Kotowski1 Informatyka I Wykład 14 DEKLARATORY.
Programowanie obiektowe III rok EiT
Andrzej Repak Nr albumu
Java – coś na temat Klas Piotr Rosik
Inicjalizacja i sprzątanie
Programowanie obiektowe Wykład 3 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21 Dariusz Wardowski.
Programowanie obiektowe Wykład 6 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14 Dariusz Wardowski.
Podstawy informatyki 2013/2014
Przekazywanie parametrów do funkcji oraz zmienne globalne i lokalne
Programowanie obiektowe 2013/2014
Prasek Aneta, Skiba Katarzyna. Funkcje stałe const to takie funkcje, które nie mogą modyfikować stanu obiektu. Oznacza to, że funkcja stała nie może zmieniać.
Kurs języka C++ – wykład 3 ( )
Kurs języka C++ – wykład 9 ( )
Treści multimedialne - kodowanie, przetwarzanie, prezentacja Odtwarzanie treści multimedialnych Andrzej Majkowski informatyka +
K URS JĘZYKA C++ – WYKŁAD 10 ( ) Szablony.
Programowanie strukturalne i obiektowe C++
Kurs języka C++ – wykład 4 ( )
K URS JĘZYKA C++ – WYKŁAD 2 ( ) Klasy i obiekty.
Programowanie obiektowe Wykład 9 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/15 Dariusz Wardowski.
Konstruktory i Destruktory. Konstruktor Konstruktor — co to? Konstruktor — co to? jest metodą służącą do inicjowania obiektów danej klasy jest metodą.
Dziedziczenie wielobazowe. dana klasa może mieć kilka bezpośrednich klas bazowych: dana klasa może mieć kilka bezpośrednich klas bazowych: kolorpołożenie.
Dziedziczenie Wykład 7 Dziedziczenie sekwencyjne
Wykład 4 Klasa Vec, której konstruktory alokują pamięć dla obiektów 1.Przykład definicji klasy Vec 2.Definicje konstruktorów i destruktora 3.Definicja.
PO13-1 / 19 Wykład 13 Wyjątki i ich zgłaszanie Wyłapywanie wyjątków Obsługa wyjątków Wykorzystanie polimorfizmu Filtrowanie wyjątków Błędy w konstruktorach.
Wykład 2 Klasa Zesp i jej hermetyzacja 1.Przykład definicji klasy Zesp 2.Zmiana definicji klasy 3.Zmienne i funkcje statyczne PO2-1 / 28.
Wykład 5 Klasa Vec i jej operatory 1.Kategorie operatorów 2.Operatory ogólne - przykłady 3.Operatory specjalne [ ], ( ) oraz –> 4.Operatory new i delete.
Wykład 8 Polimorfizm 1.Funkcje polimorficzne 2.Czyste funkcje wirtualne i klasy abstrakcyjne PO8-1 / 38.
Podstawy informatyki Funkcje Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi.
Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego Matuszyka Podstawy.
Podstawy informatyki Struktury Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi.
K URS JĘZYKA C++ – WYKŁAD 3 ( ) Przenoszenie Składowe statyczne Funkcje wbudowane Argumenty domyślne.
C++ mgr inż. Tomasz Turba Politechnika Opolska 2016.
Programowanie Obiektowe – Wykład 6
Kurs języka C++ – wykład 3 ( )
Klasy, pola, obiekty, metody. Modyfikatory dostępu, hermetyzacja
(według:
Delegaty Delegat to obiekt „wiedzący”, jak wywołać metodę.
Programowanie Obiektowe – Wykład 2
Kurs języka C++ – wykład 4 ( )
PODSTAWY INFORMATYKI Wykład 4.
Język C++ Typy Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego.
Zapis prezentacji:

this, friend, operatory

this dostępny w każdej niestatycznej metodzie dostępny w każdej niestatycznej metodzie jest to wskaźnik do obiektu na rzecz którego wywołano metodę jest to wskaźnik do obiektu na rzecz którego wywołano metodę można go wykorzystać jeżeli mamy zwrócić wskaźnik bądź referencję do obiektu na rzecz którego wywoływana jest metoda można go wykorzystać jeżeli mamy zwrócić wskaźnik bądź referencję do obiektu na rzecz którego wywoływana jest metoda nie zajmuje pamięci nie zajmuje pamięci nie wymaga deklarowania nie wymaga deklarowania

this person & person::timeTravel(int years) { age += years; age += years; return *this; return *this;} person Boss(„John”, „Kovalsky”, 40); ( Boss.timeTravel(+20) ).timeTravel(-30)

friend po polsku zaprzyjaźnianie po polsku zaprzyjaźnianie jest to deklaracja znosząca ograniczenia dostępu do składowych klasy przez ściśle określony kod jest to deklaracja znosząca ograniczenia dostępu do składowych klasy przez ściśle określony kod

friend class A { friend C::theMethodNoArg(); friend C::theMethodNoArg(); // dotyczy konkretnej metody, tu bezargumentowej // dotyczy konkretnej metody, tu bezargumentowej friend class B; friend class B; // dotyczy całej deklaracji klasy B // dotyczy całej deklaracji klasy B // również deklaracje wewnątrz B mają dostęp // również deklaracje wewnątrz B mają dostęp // do pól prywatnych A // do pól prywatnych A friend fun(); friend fun(); // dotyczy konkretnej funkcji, tu bezargumentowej // dotyczy konkretnej funkcji, tu bezargumentowej}

friend zaprzyjaźnianie nie podlega dziedziczeniu zaprzyjaźnianie nie podlega dziedziczeniu zaprzyjaźnianie nie jest przechodnie zaprzyjaźnianie nie jest przechodnie deklarowane w dowolnej sekcji (nawet prywatnej) klasy deklarowane w dowolnej sekcji (nawet prywatnej) klasy

friend class M { friend void f() … { … } }; jest równoważne class M { friend void f(); }; void f() { … }

Operatory Co to jest operator? Co to jest operator? a = b.val >> 4 + c * d[ e++ ]

Operatory operator definiuje operacje wykonywane na swoich argumentach i typ wyniku takiej operacji – analogicznie do funkcji. operator definiuje operacje wykonywane na swoich argumentach i typ wyniku takiej operacji – analogicznie do funkcji. w C++ można definiować znaczenie operatorów w przypadku wykorzystania ich do obiektów (przynajmniej jeden argument obiektowy). w C++ można definiować znaczenie operatorów w przypadku wykorzystania ich do obiektów (przynajmniej jeden argument obiektowy).

Operatory Można przeciążać większość operatorów Można przeciążać większość operatorów Przeciążanie może poprawić wydajność Przeciążanie może poprawić wydajność Nie ma obowiązku a zwykle nie ma i potrzeby definiowania wielu operatorów, jeżeli operator byłby sporadycznie używany to zaleca się deklarowanie go jako metody bądź zwykłej funkcji. Nie ma obowiązku a zwykle nie ma i potrzeby definiowania wielu operatorów, jeżeli operator byłby sporadycznie używany to zaleca się deklarowanie go jako metody bądź zwykłej funkcji.

Operatory które można przeciążać () [] -> ! ~ * & new delete (typ) // jednoargumentowe ->* * / % + - > > >= >= == != &^|&&|| = += -= *= /= %= &= ^= |= >= // op. przypisania

Operatory nie można przeciążać operatorów: nie można przeciążać operatorów:..* ::?:sizeof operatory, które mogą być jedynie metodami klasy: operatory, które mogą być jedynie metodami klasy: ()[]->newdelete(typ)= operatory domniemane, jeżeli nie zdefiniowane: operatory domniemane, jeżeli nie zdefiniowane: =&

Łączność operatory przypisania i jednoargumentowe są prawostronnie łączne operatory przypisania i jednoargumentowe są prawostronnie łączne a=b=c oznacza a=(b=c) pozostałe lewostronnie pozostałe lewostronnie a+b+c oznacza (a+b)+c

Kolejność wartościowania kolejność wartościowania argumentów niezdefiniowana, za wyjątkiem: kolejność wartościowania argumentów niezdefiniowana, za wyjątkiem:,||&&,||&& „, ”, „ || ”, „ && ” najpierw wartościowany lewy argument, potem prawy „, ”, „ || ”, „ && ” najpierw wartościowany lewy argument, potem prawy dla operacji logicznych stosowane jest skrócone wartościowanie. dla operacji logicznych stosowane jest skrócone wartościowanie.

Operatory a metody inna składnia deklaracji, definicji i wywołania inna składnia deklaracji, definicji i wywołania operatory nie mogą mieć argumentów domyślnych (wyjątek: operator wywołania funkcji) operatory nie mogą mieć argumentów domyślnych (wyjątek: operator wywołania funkcji) określona jest liczba argumentów (wyjątek: operator wywołania funkcji) określona jest liczba argumentów (wyjątek: operator wywołania funkcji) przyjęte jest zwyczajowe znaczenie operatorów przyjęte jest zwyczajowe znaczenie operatorów

Operatory Chcesz += to zdefiniuj go, Chcesz += to zdefiniuj go, nie wystarczy zdefiniować + i = Chcesz ++ to zdefiniuj go, Chcesz ++ to zdefiniuj go, kompilatorowi nie wtstarczy + i = Zachowaj wierność zwyczajowemu znaczeniu operatorów Zachowaj wierność zwyczajowemu znaczeniu operatorów niech jednoarg. & zwraca adres niech jednoarg. & zwraca adres Zachowaj konsekwencję Zachowaj konsekwencję ++i; i++; i+=1; i=i+1; // powinny dawać taki sam efekt. ++i; i++; i+=1; i=i+1; // powinny dawać taki sam efekt.

Operatory jako metody pierwszy argument będzie obiektem klasy pierwszy argument będzie obiektem klasy metoda ma mniej argumentów niż operator metoda ma mniej argumentów niż operator deklarowanie deklarowanie int point::operator<=(point); wywoływanie wywoływanie point point1, point2; int i= point1 <= point2; int j= point1.operator<=(point2);

Operatory jako funkcje przynajmniej jeden z argumentów musi być obiektem przynajmniej jeden z argumentów musi być obiektem wszystkie argumenty są parametrami funkcji operatorowej wszystkie argumenty są parametrami funkcji operatorowej nie ma this nie ma this deklarowanie deklarowanie int operator<=(point, point); wywoływanie wywoływanie point point1, point2; int i = point1 <= point2; int j= operator<=(point1, point2);

Konwencja dla operatorów ++ i -- operator++() i operator--() są przedrostkowe operator++() i operator--() są przedrostkowe ++i--i operatory przyrostkowe deklarujemy i definiujemy z dokładnie jednym nienazwanym parametrem int: operatory przyrostkowe deklarujemy i definiujemy z dokładnie jednym nienazwanym parametrem int: operator++(int); operator--(int); i++i--

Konwencja dla operatorów ++ i -- class X { public: X& operator++(); // prefix ++a X operator++(int); // postfix a++ }; class Y { public: }; Y& operator++(Y&); // prefix ++b Y operator++(Y&, int); // postfix b++

Konwencja dla operatorów ++ i -- void f(X a, Y b) { ++a; // a.operator++(); a++; // a.operator++(0); ++b; // operator++(b); b++; // operator++(b, 0); a.operator++(); // odpowiada ++a; a.operator++(0); // odpowiada a++; operator++(b); // odpowiada ++b; operator++(b, 0); // odpowiada b++; }

Operatory class X // składowe z niejawnym this { X* operator&();// przedrostkowy, jednoargumentowy & X operator&(X);// dwuargumentowy X operator++(int);// przyrostkowy //X operator&(X, X);// blad trzyargumentoowy //X operator/();// blad jednoarg. }; // funkcje globalne, bez this, często zaprzyjazniane X operator-(X);// przedrostkowy X operator-(X, X);// dwuargumentowy X operator--(X&, int);// przyrostkowy dekrementacja // X operator-(X, X, X);// blad trzyargumentoowy // X operator/();// blad operator bezargumentowy! ;)

Operator przypisania Musi być zdefiniowany jako metoda (niestatyczna) a nie jako funkcja Musi być zdefiniowany jako metoda (niestatyczna) a nie jako funkcja T& T::operator=(const T &) Nie ma listy inicjalizacyjnej bo to nie jest konstruktor !!! Nie ma listy inicjalizacyjnej bo to nie jest konstruktor !!!

Operator przypisania person& person::operator=(const person &o) { if (this == &o) // Tom = Tom; if (this == &o) // Tom = Tom; return *this; return *this; delete [] name; delete [] name; name=new char[strlen(o.name) + 1]; name=new char[strlen(o.name) + 1]; strcpy(name, o.name); strcpy(name, o.name); delete [] lastName; delete [] lastName; lastName=new char[strlen(o.lastName) + 1]; lastName=new char[strlen(o.lastName) + 1]; strcpy(lastName, o.lastName); strcpy(lastName, o.lastName); age=o.age; age=o.age; return *this;// zwraca obiekt, będzie przekazany przez referencje return *this;// zwraca obiekt, będzie przekazany przez referencje}

Operator przypisania dlaczego operator przypisania zwraca referencję? dlaczego operator przypisania zwraca referencję? chcemy napisać o1=o2=o3; chcemy napisać o1=o2=o3; person& operator=(const person&); 1. przypisania do: o2 z: o3 2. operator przypisania do: o1 z: (o2=o3) person operator=(const person&); 1. przypisania do: o2 z: o3 2. konstruktor kopiujący (powstaje tymczasowy obiekt t1) 3. operator przypisania do: o1 z: t1 4. konstruktor kopiujący (powstaje tymczasowy obiekt t2) 5. destruktor t2 6. destruktor t1

Operator przypisania dlaczego operator przypisania zwraca referencję? dlaczego operator przypisania zwraca referencję? chcemy napisac o1=o2=o3; chcemy napisac o1=o2=o3; void operator=(const person&); void operator=(const person&); można o2=o3; można o2=o3; nie da się o1=o2=o3; nie da się o1=o2=o3;

Operator przypisania generowany automatycznie jeżeli się nie zdefiniuje operatora przypisania to kompilator dostarczy własny operator przypisania, który skopiuje obiekt pole po polu. jeżeli się nie zdefiniuje operatora przypisania to kompilator dostarczy własny operator przypisania, który skopiuje obiekt pole po polu. nie będzie działał dla pól stałych nie będzie działał dla pól stałych nie będzie działał dla dla referencji nie będzie działał dla dla referencji dla wskaźników skopiuje wartość dla wskaźników skopiuje wartość

Operatory strumieniowe Wejście Wejście friend istream & operator >>(istream &, T &); Wyjście Wyjście friend ostream &operator <<(ostream &, const T &);

Operatory strumieniowe class point { int x, y; int x, y;public:… friend istream &operator >>(istream & s, point & p); friend istream &operator >>(istream & s, point & p); friend ostream &operator <<(ostream & s, const point &); friend ostream &operator <<(ostream & s, const point &);} point p, p2; cin>>p;cin>>p>>p2;cout<<p2<<p;

Operatory strumieniowe istream & operator >>(istream & s, point & p) { s >> p.x >> p.y; s >> p.x >> p.y; return s; return s;} ostream &operator <<(ostream & s, const point & p) { s << p.x << p.y; s << p.x << p.y; return s; return s;}

Operator wyłuskania T* operator->(); T t; T t; t->m jest interpretowane jako: t->m jest interpretowane jako: ( t.operator-> )->m można używać zmiennej jak wskaźnika można używać zmiennej jak wskaźnika jeżeli operator-> nie zwraca wskaźnika to jeżeli operator-> nie zwraca wskaźnika to można użyć go: a=t.operator->(); można użyć go: a=t.operator->(); nie można: a=t->; bo to błąd składniowy nie można: a=t->; bo to błąd składniowy

Operator wywołania funkcji wynik T::operator()(args); Dowolna liczba argumentów, można przeciążać Dowolna liczba argumentów, można przeciążać Wyjątek: tylko ten operator może mieć domyślne argumenty Wyjątek: tylko ten operator może mieć domyślne argumenty potem można obiekt używać tak, jak funkcję potem można obiekt używać tak, jak funkcję T ob; ob(); stosuje się gdy stosuje się gdy nie istnieje odpowiedni operator, a by się przydał nie istnieje odpowiedni operator, a by się przydał jest jakś metoda dominująca dla klasy (będzie bez nazwy ale łatwiejsza do wywołania – np. klasa counter i metoda inkrementacja) jest jakś metoda dominująca dla klasy (będzie bez nazwy ale łatwiejsza do wywołania – np. klasa counter i metoda inkrementacja)

operator indeksowania wynik T::operator[](index); typy wyniku i indeksu dowolne ale zdrowy rozsądek nakazuje indeks całkowity typy wyniku i indeksu dowolne ale zdrowy rozsądek nakazuje indeks całkowity można tworzyć inteligentne agregaty, można tworzyć inteligentne agregaty,

Operator konwersji operator konwersji tworzy obiekt określonego typu lub klasy z obiektu na rzecz którego jest wywoływany operator konwersji tworzy obiekt określonego typu lub klasy z obiektu na rzecz którego jest wywoływany T::operator X(); operator konwersji klasy T do typu X: operator konwersji klasy T do typu X: nie określa się jawnie typu wartości zwracanej, nie określa się jawnie typu wartości zwracanej, jest bezargumentowy jest bezargumentowy musi być metodą (nie funkcją) musi być metodą (nie funkcją)

Operator konwersji np.: np.: person::operator int(); konwersja może następować niejawnie: konwersja może następować niejawnie: person o; int i=o+5; W wyrażeniach W wyrażeniach dla danego obiektu konwersja jest stosowana tylko jeżeli jest konieczna, dla danego obiektu konwersja jest stosowana tylko jeżeli jest konieczna, może być tylko jedna konwersja danego składnika definiowana przez użytkownika może być tylko jedna konwersja danego składnika definiowana przez użytkownika nie może być niejednoznaczności nie może być niejednoznaczności

Operator konwersji np. dla klas: A, B i C, zdefiniowano operatory konwersji B::operator A() i C::operator B(); np. dla klas: A, B i C, zdefiniowano operatory konwersji B::operator A() i C::operator B(); int f(A a); A a; B b; C c; f(a); // ok.. f(b); // f(A(b)) // f(c); // nie ma operatora C::operator A() // nie zrobi się niejawnie f(A(B(c))) // (2 konwersje skladnika)

Operator konwersji aby przekształcić obiekt jednego typu w obiekt innego typu można jawnie użyć konstruktora, ale: aby przekształcić obiekt jednego typu w obiekt innego typu można jawnie użyć konstruktora, ale: nie da się przeprowadzić przekształcenia do typu podstawowego (np. int, bo to nie klasa), nie da się przeprowadzić przekształcenia do typu podstawowego (np. int, bo to nie klasa), nie da się przekształcić do starej klasy bez modyfikowania jej definicji. nie da się przekształcić do starej klasy bez modyfikowania jej definicji.

Przykład class counter { int cnt; int cnt; public: public: counter(int i=0):cnt(i){}; counter(int i=0):cnt(i){}; int operator()(int =1); // increment by arg. or by 1 int operator()(int =1); // increment by arg. or by 1 operator int(); // convert to int operator int(); // convert to int operator double(); // convert to double operator double(); // convert to double counter &operator+=(int); counter &operator+=(int); friend counter operator+(int, counter); // int+counter, friend friend counter operator+(int, counter); // int+counter, friend counter operator+(int); // counter+int counter operator+(int); // counter+int int operator++();// ++counter int operator++();// ++counter int operator++(int);// counter++ int operator++(int);// counter++};

Przykład inline int counter::operator ()(int i) { return cnt+=i; return cnt+=i;} inline counter::operator int() { return cnt; return cnt;} inline counter::operator double() { return double(cnt); return double(cnt);}

Przykład counter & counter::operator +=(int i) { cnt+=i; // operator()(i); (*this)(i) cnt+=i; // operator()(i); (*this)(i) return *this; return *this;} counter operator+(int i, counter l) { l+=i; // zaprzyjaźnianie nie było konieczne l+=i; // zaprzyjaźnianie nie było konieczne return l; return l;}

Przykład counter counter::operator +(int i) { counter l=*this; counter l=*this; l+=i; l+=i; return l; return l;} int counter::operator ++() { cnt+=1; cnt+=1; return cnt; return cnt;} int counter::operator ++(int) { int ret=cnt; int ret=cnt; cnt+=1; cnt+=1; return ret; return ret;}

Przykład class complex { double re, im; double re, im;public: complex(double re, double im):re(re), im(im) {}; complex(double re, double im):re(re), im(im) {}; complex & operator = (const complex &c); complex & operator = (const complex &c); complex & operator += (const complex &c); complex & operator += (const complex &c); complex operator + (const complex &); complex operator + (const complex &); friend complex & operator -= (complex &, const complex &); friend complex & operator -= (complex &, const complex &); friend complex operator - (const complex &, const complex &); friend complex operator - (const complex &, const complex &); friend istream & operator >>(istream &, complex &); friend istream & operator >>(istream &, complex &); friend ostream & operator <<(ostream &, const complex &); friend ostream & operator <<(ostream &, const complex &);};

Przykład complex & complex::operator = (const complex &c) { re=c.re; re=c.re; im=c.im; im=c.im; return *this; return *this; }

Przykład complex & complex::operator += (const complex &c) { re+=c.re; re+=c.re; im+=c.im; im+=c.im; return *this; return *this; } inline complex complex::operator + (const complex & c) { return complex(re+c.re, im+c.im); // complex(double, double) return complex(re+c.re, im+c.im); // complex(double, double)}

Przykład inline complex & operator-=(complex & c1, const complex & c2) //friend { c1.re-=c2.re; c1.re-=c2.re; c1.im-=c2.im; c1.im-=c2.im; return c1; return c1;} complex operator-(const complex & c1, const complex & c2) //friend { complex c=c1; complex c=c1; c-=c2; c-=c2; return c; return c;}

Przykład istream & operator >>(istream & s, complex & c) { s >> c.re >> c.im; s >> c.re >> c.im; return s; return s;} ostream &operator <<(ostream & s, const complex & c) { s << c.re << c.im; s << c.re << c.im; return s; return s;}