Konverziós operátorok Az átdefiniálható operátorok külön családját képezik az ún. konverziós (cast) operátorok. Konverzió kijelölése: (céltípus) változó Értékadásban (ha két oldalon eltérő típus van) és függvényhíváskor (átadott objektum típusa a deklarációban megadottól eltér) automatikus típuskonverzió megy végbe. Implicit típuskonverzió.
Konverziós operátorok átdefiniálása Példa: Két double koordinátát tartalmazó vektor objektumok és az MS_Windows-ban megszokott forma ( egy vektor egy long típusban kerül tárolásra úgy, hogy a long alsó helyiértékű 16 bitje az x, felső helyiértékű 16 bitje az y koordináta) között végzünk átalakításokat.
Típuskonverzió Vector vec ( 1.0, 2.5 ) ; long point = 14L + 36 L << 16 ) ; //14, 36 koordinátájú pont extern f (long) ; extern g (Vector) ; vec = (Vector ) point ; //explicit vec = point ; //implicit g (point ) ; //implicit point = (long ) vec ; //explicit point = vec ; //implicit f (vec ) ; //implicit
Konverziós operátorok átdefiniálása Újdonság a C++-ban: osztállyal gyártott objektumokra is definiálhatunk átalakító operátorokat. Két eset: - osztállyal definiált típusról alakítunk át más típusra ( ami lehet más osztállyal definiált típus vagy beépített típus). - Beépített vagy osztállyal definiált típust konvertálunk osztállyal definiált típusra.
Konverzió osztállyal definiált típusról A Vector -> típus (jelen esetben long) átalakítást kell megvalósítanunk, amely a Vector osztályban egy operator típus ( ) ; tagfüggvénnyel lehetséges. Ehhez a tagfüggvényhez nem lehet visszatérési típus és nem lehet argumentum sem.
Megvalósítás class Vector { double x, y ; public: operator long ( ) { return ((long) x + (long) y <<16 ) ; } }
Beépített vagy osztállyal definiált típust konvertálunk osztállyal definiált típusra Amennyiben egy objektumot akarunk létrehozni egy más típusú változóból, olyan konstruktort kell készíteni, ami argumentumként a megadott típust fogadja el. A long -> Vector átalakításhoz tehát a Vector osztályban egy long argumentumú konstruktor szükséges:
Példa class Vector { double x, y ; public: Vector ( long lo) { x = lo & 0xffff; y = lo >>16 ; }
Szabványos I/O Az operátor átdefiniálás jellegzetes alkalmazása a C++ szabványos I/O könyvtára. Egy változó beolvasása cin >> változó //szabványos inputról Egy változó kiírása cout << változó //szabványos outputra cerr << változó //szabványos hibafájl
Cin és cout objektumok C könyvtári függvények: C++ átdefiniált operátorok #include <stdio.h> #include <iostream.h> main() { main() { int i; int i; i= 5; i = 5; printf (“Hi%d\n”, i); cout<<“Hi”<<i<<‘\n’; scanf (“%d”, &i); cin>>i; } } C++: amennyiben több változót akarunk kiírni vagy beolvasni, azok láncolhatók. Szabványos I/O C++ megoldása mögött a << és >> operátorok átdefiniálása áll.
Nézzük meg a cin és cout objektumok típusát meghatározó istream és ostream osztályokat, melyek az iostream.h deklarációs fájlban találhatók: class ostream { public: ostream& operator<<( int i); //lehetséges implementáció printf(“%d”, i); } ostream& operator<<( char *i); ostream& operator<<( char); } ; extern ostream cout;
istream osztály class istream { public: istream& operator>>( int& i); //lehetséges implementáció {scanf(“%d”, &i); } } ; extern istream cin;
Megoldás: - vagy az ostream osztályt kell kiegészíteni egy Terjesszük ki a szabványos kimenetet a Vector osztályra, úgy, hogy egy v vektor a cout<<v utasítással kiírható legyen! Megoldás: - vagy az ostream osztályt kell kiegészíteni egy operator<<(Vector v) tagfüggvénnyel - vagy egy globális operator<<(ostream& s, Vector v) függvényt kell létrehozni:
Vector típusú adat kiírása ostream& operator<< (ostream& s, Vector v) { s<< v.GetX() << v.GetY() ; return s ; }
Láncolás biztosítása Az első ostream típusú cout objektumot referenciaként vesszük át és visszatérési értékben is referenciaként adjuk vissza. A kapott cout objektum visszatérési értékként való átadására azért van szükség, hogy a megismert láncolás működjön.
Egy újabb feladat (CCurrency osztály létrehozása) class CCurrency {private: long Dollars; int Cents; public: cCurrency() { Dollars = Cents = 0; } cCurrency(long Dol, int Cen) SetAmount ( Dol, Cen) ;
Értékek visszaadása void GetAmount(long *Pdol, int *PCen) { *Pdol = Dollars; *Pcen= Cents; }
Értékek megadása void SetAmount(long Dol, int Cen) { Dollars = Dol + Cen/100; Cents = Cen % 100; }
Adattagok megjelenítése void PrintAmount() { cout.fill(„0”) ; cout.width (1) ; cout<<„$”<<Dollars << „. „ ; cout.width(2) ; cout << cents % 100 ; }
operator+ () class CCurrency { … public: CCurrency operator+ (CCurrency Curr) CCurrency Temp (Dollars + Curr.Dollars, Cents + Curr.Cents); return Temp; } };
operator+() más megoldásasl CCurrency operator+ (CCurrency Curr) { return CCurrency (Dollars + Curr.Dollars, Cents + Curr.Cents); }
Ccurrency Amount1 (12,95); Ccurrency Amount2 (4,38); Ccurrency Total; Total = Amount1 + Amount2; Amount1.operator+(Amount2);
operator+() túlterhelése CCurrency operator+ (long Dol) { return CCurrency (Dollars + Dol, Cents); } Ccurrency Adv (235, 42); Adv = Adv + 100; Adv.operator+(100);
100.operator+(Adv); //globális metódus CCurrency operator+ (long Dol, CCurrency &Curr) { return CCurrency (Dol+Curr.Dollars + Curr. Cents); }
class CCurrency { … friendCCurrency operator+ (long Dol, CCurrency &Curr); }; Adv= 100 + Adv;