Biologie | Chimie | Didactica | Fizica | Geografie | Informatica | |
Istorie | Literatura | Matematica | Psihologie |
Utilizarea unui constructor pentru a specifica o conversie de tip este posibila pentru un numar limitat de situatii deoarece:
Nu exista o conversie implicita de la un tip definit de utilizator (clasa) la un tip predefinit.
Nu se poate defini o conversie de la un tip nou de date la un tip definit mai inainte, fara modificarea tipului vechi.
Aceste probleme se pot rezolva prin definirea unui operator de conversie al clasei. Intr-o clasa X, o functie membra X::operator T(), unde T este un nume de tip (predefinit sau definit de utilizator) realizeaza conversia de la tipul X la tipul T, in modul descris de functia operator. Se pot diferentia doua categorii de operatori de conversie: conversie dintr-un tip definit de utilizator intr-un tip predefinit si conversie dintr-un tip definit de utilizator in alt tip definit de utilizator.
Una din utilizarile frecvente ale operatorilor de conversie este aceea de a converti un tip definit de utilizator (clasa) intr-un tip predefinit printr-o functie membra nestatica a clasei respective. O astfel de functie nu are nici un argument, dat fiind ca operatorul de conversie este un operator unar (foloseste numai obiectul pentru care a fost apelat, al carui pointer this il primeste implicit).
Pentru o clasa data se pot supraincarca mai multi operatori de conversie de la clasa respectiva la unul din tipurile predefinite. Conversia definita prin supraincarcarea operatorului de conversie poate fi apelata explicit sau implicit. Apelul explicit al operatorului de conversie pentru un obiect din clasa X catre tipul predefinit T poate avea doua forme:
T(obiect) sau T(obiect)
Conversia implicita (deci apelul implicit al functiei operator de conversie) are loc la utilizarea unui obiect dintr-o clasa in care s-a definit o astfel de functie intr-o expresie aritmetica sau conditionala. Daca sunt definite mai multe functii operatori de conversie pot sa apara ambiguitati in selectarea uneia dintre acestea in cazul conversiei implicite. Cateva situatii de conversie sunt prezentate in exemplul urmator.
Exemplul 7
Se completeaza clasa Point cu definirea catorva operatori de conversie, care apoi sunt apelati in diferite modalitati.
class Point;
Point::operator double()
Point::operator void*()
void f8()
Se poate evita eroarea de compilare determinata de ambiguitatea la conversia implicita din instructiunea if(p1) fortand in mod explicit unul dintre operatorii de conversie ai clasei, de exemplu astfel if ((void*)p1)
Fie doua clase X si Y. Conversia obiectelor de tip X in obiecte de tip Y se poate realiza fie prin utilizarea constructorilor, fie prin supraincarcarea operatorului de conversie in clasa Y
Daca in clasa Y se defineste un constructor de tipul Y(X ob), atunci se poate realiza o conversie a unui obiect de tip X intr-un obiect de tip Y. Pentru accesul la datele private sau protected ale clasei X, este necesar declararea friend class Y in clasa X
n Exemplul 8
Se considera clasa Point, definita in aceasta sectiune si clasa Complex, definita in sectiunea 2. Conversia datelor intre cele doua tipuri are si o semnificatie matematica bine precizata, dat fiind ca un numar complex poate fi reprezentat printr-un punct intr-un plan bidimensional (imaginea numarului complex). Modul in care se realizeaza conversia datelor de tip Complex in date de tip Point, deci calculul imaginii unui numar complex, este prezentata in continuare.
class Complex
Complex(double r, double i)
friend class Point;
class Point
void f9()
n
Conversia dintr-un tip definit de utilizator intr-un alt tip definit de utilizator se poate realiza si prin supraincarcarea operatorului de conversie. Pentru conversia obiectelor de tip X in obiecte de tip Y, in clasa X se defineste functia operator de conversie
X::operator Y();
Pentru ca aceasta functie membra nestatica a clasei X sa aiba acces la date private sau protejate ale clasei Y, ea se declara functie friend in clasa Y
In exemplul urmator se reia operatia de conversie din clasa Complex in clasa Point prin supraincarcarea operatorului cu conversie in clasa Complex
n Exemplul 9
class Point;
class Complex
Complex(double r, double i)
operator Point();
class Point ;
Complex::operator Point()
void f10()
Se construieste mai intai obiectul p1 folosind constructorul implicit; instructiunea p1 = c1 apeleaza operatorul de conversie la tipul Point definit in clasa Complex; dupa aceasta conversie mai este apelata functia operator de asignare a clasei Point, care, la returnare, construieste un obiect temporar folosind constructorul de copiere al clasei Point
n
Este de mentionat faptul ca este admisa definirea unei singure conversii de la un tip de date la altul. Daca in Exemplul 9 s-ar pastra si constructorul de conversie definit in Exemplul 8, atunci ar apare o eroare de compilare.
Exercitii
E1 Pentru clasa Point, sa se defineasca urmatoarele operatii folosind supraincarcarea unor operatori:
Rotatia vectorului cu un unghi u
Calculul lungimii vectorului.
E2 Fie urmatoarea functie:
void f3();
String sir(v);
cout << sir;
Cum se explica eroarea care apare la executia acestei functii?
Sa se defineasca un alt constructor al clasei String care sa poata fi folosit in astfel de situatii.
E3 Pentru clasa String sa se defineasca urmatoarele operatii de comparatie folosind functii operator friend
int operator ==( const String& s1, const String& s2 );
int operator ==( const String& s1, const char* s2 );
int operator ==( const char* s1, const String& s2 );
int operator !=( const String& s1, const String& s2 );
int operator !=( const String& s1, const char* s2);
int operator !=( const char* s1, const String& s2);
int operator <( const String& s1, const String& s2 );
int operator <( const String& s1, const char* s2);
int operator <( const char* s1, const String& s2);
int operator >( const String& s1, const String& s2 );
int operator >( const String& s1, const char* s2 );
int operator >( const char* s1, const String& s2 );
int operator <=( const String& s1, const String& s2 );
int operator <=( const String& s1, const char* s2);
int operator <=( const char* s1, const String& s2);
int operator >=( const String& s1, const String& s2 );
int operator >=( const String& s1, const char* s2 );
int operator >=( const char* s1, const String& s2 );
Valoarea returnata este diferita de 0 daca cele doua obiecte String indeplinesc conditia de comparatie si este 0 in toate celelate cazuri. Pentru argumentele de tipul (const char* s) se considera pointerii la siruri terminate cu nul.
E5 Pentru clasa String sa se defineasca operatia de concatenare a doua siruri folosind functii friend operator+(). Valoarea returnata este un obiect nou de tip String, al carui sir reprezinta concatenarea sirurilor continute de cele doua argumente
String operator +( const String& s1, const String& s2);
String operator +( const char* s1, const String& s2);
String operator +( const String& s1, const char* s2);
Se considera pointerii la siruri terminate cu nul.
E6 Pentru clasa String sa se defineasca operatia de adaugare a unui sir nou la sfarsitul unui sir existent folosind functii friend operator+=()
const String& operator +=( const String& s );
const String& operator +=( const char* s);
Se considera pointerii la siruri terminate cu nul.
E7 Sa se defineasca urmatoarele functii de cautare a unui caracter sau a unui subsir ale clasei String:
int FindChar(char c) const;
int Find(const char* subsir) const;
int Find(const String s) const;
int FindReverse(char c) const;
int FindReverse(const char* subsir)const;
int FindReverse(const String s)const;
Pointerii subsir trebuie sa fie pointeri la siruri terminate cu nul. Functia Find(char c) returneaza indexul primului caracter cu valoarea c dintr-un obiect String, sau -1 daca obiectul String nu contine acest caracter. Celelate doua functii Find() returneaza indexul primului caracter in sirul de caractere al unui subsir dat prin pointer la caracter sau ca un obiect String, daca acest subsir este continut in sirul dat, sau -1, daca nu exista un astfel de subsir.
Functiile FindReverse() sunt definite in mod asemanator, cu diferenta ca se executa o cautare de la sfarsitul sirului.
E8 In clasa String, sa se defineasca urmatoarele functii:
int GetLength(); // returneaza nr. caractere al sirului
// fara caracterul nul terminal
char *GetBuffer(); // returneaza bufferul de caractere
void MakeUpper(); // converteste in majuscule
void MakeLower(); // converteste in litere mici
void MakeReverse();// inverseaza caracterele in sir
E9 Sa se defineasca un iterator pentru clasa String
Politica de confidentialitate |
Copyright © 2024 - Toate drepturile rezervate