CATEGORII DOCUMENTE |
In mod automat in limbajele C si C++ se aplica o conversie in urmatoarele trei situatii:
daca un operator se refera la operanzi de tipuri diferite;
daca tipul parametrului actual al unei functii difera de tipul parametrului formal corespunzator;
daca tipul valorii returnate de o functie, tip specificat in antetul functiei, difera de tipul expresiei din instructiunea return.
In primul caz, daca operatorul nu este de atribuire, se va folosi regula conversiilor implicite. Deci mai intai tipurile char si enum se convertesc in int, dupa care tipurile 'inferioare' se convertesc spre cele 'superioare' (de exemplu int in double). Daca operatorul este de atribuire, atunci tipul expresiei din partea dreapta se converteste spre tipul expresiei din partea stanga. In cazul al doilea tipul parametrului actual se converteste spre tipul parametrului formal. In cazul al treilea tipul expresiei din instructiunea return se converteste spre tipul specificat in antetul functiei.
Consideram urmatorul exemplu referitor la clasa numerelor rationale. Clasa va avea doua date membru de tip long pentru memorarea numaratorului si numitorului. Obiectele clasei se vor initializa printr-un constructor. Se va supraincarca operatorul ~, care va efectua simplificarea fractiei, si operatorul *, pentru inmultirea a doua fractii. Deasmenea, se va defini o functie membru afiseaza, pentru afisarea unei fractii. Fisierul conv2.cpp
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
long cmmdc( long a, long b);
class fractie ;
inline fractie::fractie(long a, long b)
fractie& fractie::operator~()
inline fractie fractie::operator *(fractie r)
inline void fractie::afiseaza()
long cmmdc( long a, long b)
return a;
}
int main()
Prin executarea programului se obtine:
3 / 4
8 / 5
Observam ca operatorul de inmultire se poate folosi numai pentru inmultirea a doua numere rationale. Deci in cazul unei expresii de forma urmatoare
z = x * 4;
compilatorul ar semnala o eroare. Totusi ar fi de dorit ca expresiile de forma de mai sus, sa fie corecte. Pentru a realiza acest lucru, trebuie definita o conversie implicita din tipul long in tipul fractie.
In general, conversiile dintr-un tip standard intr-un tip abstract se realizeaza cu ajutorul unui constructor al tipului abstract. Constructorul trebuie sa aiba un parametru, care apartine tipului standard, iar daca sunt si alti parametri, ei trebuie sa fie initializati.
In cazul de mai sus constructorul, care realizeaza conversia din tipul long in tipul fractie, poate fi declarat sub forma:
fractie(long a, long b = 1);
sau
fractie(long a = 0, long b = 1);
sau
fractie(long a);
De exemplu, daca fisierul conv2.cpp se modifica astfel incat constructorul sa fie declarat in forma:
fractie(long a = 0, long b = 1);
atunci expresia
z = x * 4;
este corecta si se obtine numarul rational 8 / 5. Al doilea operand al operatorului de inmultire trebuie sa apartina tipului fractie. Cu ajutorul constructorului se va crea un obiect anonim fractie(4, 1), care se va folosi in locul operandului al doilea. Mentionam, ca de fapt s-au facut doua conversii. Constanta este de tipul int, deci la apelarea constructorului s-a facut o conversie de la tipul int la tipul long, dupa care s-a facut o conversie din tipul long in tipul fractie, prin crearea obiectului anonim.
Totusi compilatorul semnalizeaza o eroare la intalnirea unei expresii de forma urmatoare:
z = 4 * x;
Explicatia este, ca in cazul expresiei x * 4, se apeleaza functia membru operator* pentru obiectul x. Insa in cazul expresiei 4 * x, se incearca apelarea unei functii membru (operatorul de inmultire) pentru constanta 4, ceea ce conduce la eroare.
O solutie ar putea fi ca operatorul de inmultire sa se defineasa printr-o functie prieten, de exemplu in modul urmator:
class fractie ;
fractie operator*(fractie p, fractie q)
Daca operatorul de inmultire se defineste in modul de mai sus, atunci ambele expresii x * 4 si 4 * x vor fi corecte. Dezavantajul acestei metode este, ca prin utilizarea unei functii prieten, gradul de protectie a datelor scade. In continuare prezentam o alta metoda de inlaturare a erorii de mai sus, astfel incat sa nu fie nevoie de introducerea unei functii prieten. Vom defini o functie membru inmultire, care se va apela de catre functia, care supraincarca operatorul de inmultire.
class fractie ;
inline fractie fractie::inmultire(fractie r)
fractie operator*(fractie p, fractie q)
Observam ca si in acest caz, ambele expresii sunt corecte si nu s-a folosit functie prieten.
Definirea adecvata a constructorului poate sa conduca si la conversii dintr-un tip abstract intr-un alt tip abstract. Prezentam un exemplu pentru masurarea unei lungimi, in care sunt definite doua clase, folosind doua unitati de masura diferite. Cu ajutorul clasei Lungime_m se va memora lungimea in metri (mm, cm, dm si m), iar folosind clasa Lungime_inch memorarea lungimii se va realiza in inch (line, inch, foot si yard). Relatiile dintre cele doua unitati de masura sunt urmatoarele:
1 line |
2.54 mm |
|||
1 inch |
10 lines |
2.54 cm |
||
1 foot |
12 inches |
30.48 cm |
||
1 yard |
3 feet |
91.44 cm |
Deasemenea, programul va realiza conversia din inch in metri. Fisierul lung1.cpp
#include <iostream.h>
#include <conio.h>
class Lungime_inch ;
class Lungime_m ;
Lungime_inch::Lungime_inch( int l, int i, int f, int y)
long Lungime_inch::line_lungime()
void Lungime_inch::afisare()
Lungime_m::Lungime_m( int mm_1, int cm_1, int dm_1, int m_1)
Lungime_m::Lungime_m(Lungime_inch L)
void Lungime_m::afisare()
int main()
Prin executarea programului se obtine:
5 line 2 inch 1 foot 3 yard
1225 line
3111.5 mm
3 m 1 dm 1 cm 1.5 mm
Observam, ca si in acest caz s-a folosit un constructor pentru realizarea conversiei din tipul Lungime_inch in tipul Lungime_m. Clasa Lungime_inch s‑a declarat inainte de clasa Lungime_m, deoarece constructorul, care realizeaza conversia, foloseste tipul Lungime_inch
Conversia dintr-un tip abstract intr-un tip standard se poate realiza prin supraincarcarea operatorului de conversie explicita. Pentru a realiza conversia din tipul abstract Clasa in tipul standard tip_standard este necesara o functie membru de forma urmatoare:
class Clasa ;
Clasa::operator tip_standard()
Obiectul de tip Clasa se va converti in valoarea expresiei returnate de catre functia membru, care supraincarca operatorul de conversie explicita. Mentionam ca in declaratia functiei membru, care supraincarca operatorul de conversie explicita, nu trebuie specificat tipul, care se returneaza, deoarece acest tip va fi intotdeauna tipul standard la care se face conversia. Daca se incearca specificarea tipului returnat, atunci compilatorul va semnala eroare. In urmatorul exemplu se va efectua conversia unui numar rational intr‑un numar de tip double. Fisierul conv3.cpp
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
class fractie ;
inline fractie::fractie(long a, long b)
fractie::operator double()
inline fractie fractie::operator* (fractie r)
inline void fractie::afiseaza()
int main()
Prin executarea programului obtinem:
1.8
1.8
Mentionam ca daca parametrul formal b al constructorului clasei fractie ar fi fost initializat, atunci ar fi aparut o eroare la compilare. Intr-adevar, in acest caz expresia x * 4.5 se poate evalua in urmatoarele doua moduri:
conversia variabilei x in tipul double si efectuarea inmultirii a doua date de tip double;
conversia constantei de tip double in tipul long (cu trunchiere), urmata de conversia in tipul abstract fractie prin apelarea constructorului, si efectuarea inmultirii a doua numere rationale.
Deoarece evaluarea expresiei x * 4.5 se poate face in doua moduri diferite, compilatorul nu poate evalua expresia, si se va semnala o eroare.
Supraincarcarea operatorului de conversie explicita se poate folosi si pentru conversii dintr-un tip abstract intr-un alt tip abstract. In continuare se va relua exemplul referitor la masurarea unei lungimi in metri, respectiv in inch. Se va supraincarca operatorul de conversie explicita din inch in metri. Fisierul lung2.cpp
#include <iostream.h>
#include <conio.h>
class Lungime_m ;
class Lungime_inch ;
Lungime_m::Lungime_m( int mm_1, int cm_1,
int dm_1, int m_1, double rest_1)
void Lungime_m::afisare()
Lungime_inch::Lungime_inch( int l, int i, int f, int y)
Lungime_inch::operator Lungime_m()
long Lungime_inch::line_lungime()
void Lungime_inch::afisare()
int main()
Observam, ca rezultatul obtinut dupa executie este identic cu cel al fisierului lung1.cpp. Mentionam ca in acest caz clasa Lungime_m trebuie declarata inainte de clasa Lungime_inch, deoarece tipul Lungime_m se foloseste in cadrul clasei Lungime_inch
In principiu conversia dintr-un tip abstract intr-un alt tip abstract se poate realiza in doua moduri: cu ajutorul unui constructor si prin supraincarcarea operatorul de conversie explicita. Insa in cazul unei aplicatii concrete, numai unul din aceste doua moduri poate fi folosit. In caz contrar compilatorul va semnala o eroare.
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 1104
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved