Administratie | Alimentatie | Arta cultura | Asistenta sociala | Astronomie |
Biologie | Chimie | Comunicare | Constructii | Cosmetica |
Desen | Diverse | Drept | Economie | Engleza |
Filozofie | Fizica | Franceza | Geografie | Germana |
Informatica | Istorie | Latina | Management | Marketing |
Matematica | Mecanica | Medicina | Pedagogie | Psihologie |
Romana | Stiinte politice | Transporturi | Turism |
Supraincarcarea functiilor si a operatorilor
Scopul
lucrarii: Familiarizarea cu operatiile de
supraincarcare a functiilor si a operatorilor.
Desfasurarea
lucrarii: Se vor scrie programe in cadrul carora se vor
supraincarca functii si operatori adecvati pentru
efectuarea anumitor operatii specifice modulelor proiectate.
Se vor utiliza paradigmele de abstractizare a datelor, aplicatiile avand
fisiere header pentru declararea claselor si fisiere sursa
pentru implementarea functiilor membre, precum si un fisier
sursa pentru testare. Se vor identifica si proiecta modulele
corespunzatoare pentru rezolvarea fiecarei aplicatii.
Supraincarcarea
functiilor
De regula, intr-un program, 2
functii nu au acelasi nume. Insa, daca functiile
implementeaza operatii similare asupra unor tipuri diferite de date,
de cele mai multe ori e indicat ca aceste functii sa aiba
acelasi nume. Compilatorul de C++ alege functia adecvata in
cazul unui apel, bazandu-se pe componenta listelor de parametri formali.
De exemplu, pot fi definite 2 functii pentru adunarea a doua numere,
una pentru numere intregi si alta pentru numere complexe:
int power(int,int);
complex power(complex,complex);
Utilizarea aceluiasi nume pentru mai multe functii, in acelasi
domeniu de vizibilitate, se numeste supraincarcarea numelor de
functii sau, pe scurt, supraincarcare. In lucrarea 3 am utilizat deja acest concept, in
contextul constructorilor unei clase. Tehnica supraincarcarii este
aplicata implicit in cadrul limbajului C++ pentru operatiile primare.
Astfel, pentru operatia de adunare se utilizeaza un singur "nume",
adica "+", care se aplica si la numere intregi, si la
numere reale, si la pointeri. Pentru a face posibils distinctia
la nivelul compilatorului intre functii omonime (supraincarcate)
trebuie ca, fie numarul, fie tipurile parametrilor sa difere. Asadar,
NU pot sa fie supraincarcate doua functii care difera
doar prin tipul returnat.
Ambiguitati
la supraincarcarea functiilor
Situatia in care la un apel,
compilatorul nu poate alege intre doua sau mai multe functii
supraincarcate se numeste ambiguitate. Astfel de instructiuni
sunt tratate ca erori, iar programul nu va fi compilat. Exista in principal
doua cai prin care se ajunge la ambiguitate:
Conversiile automate
Desi conversiile automate sunt foarte utile ele reprezinta principala
cauza a ambiguitatilor:
#include <iostream.h>
float getI(float i)
double getI(double i)
void main()
La apelul getI(5.1) nu apare nici o
ambiguitate intrucat, daca nu sunt specificate explicit altfel,
constantele in virgula mobila in C++ sunt automat de tipul double. Ambiguitatea apare insa atunci cand
functia este apelata cu un parametru de tip intreg (5 de exemplu)
intrucat compilatorul nu are stie daca parametrul trebuie convertit
la float sau la double.
Se poate observa asadar ca NU supraincarcarea functiilor in
sine genereaza ambiguitatea, ci apelul functiei cu un argument
determinat.
Parametrii cu valori implicite
#include <iostream.h>
int getI(int i)
int getI(int i, int j=1)
void main()
La primul apel al functiei getI()
sunt specificate doua argumente, fiind clar care dintre functii va fi
apelata. In cel de-al doilea caz insa apare o ambiguitate, deoarece
compilatorul nu stie daca sa apeleze varianta cu un parametru
pentru functie, sau pe cea cu doi parametri, dintre care unul este
implicit.
Parametrii difera doar prin modul de transmitere
(valoare si referinta)
#include <iostream.h>
int getI(int i)
int getI(int &i)
void main()
La primul apel al functiei getI()
este specificat ca argument o constanta care nu se poate transmite prin
referinta, fiind clar care dintre functii va fi apelata. In
cel de-al doilea caz insa apare ambiguitatea, deoarece compilatorul nu
stie daca sa apeleze varianta cu transmitere prin valoare, sau
pe cea cu transmitere prin referinta. Daca varianta cu
referinta ar fi avut semnatura getI(const
int&), atunci si primul apel al functiei ar fi fost raportat ca ambiguu.
Supraincarcarea
operatorilor.Restrictii
La supraincarcarea operatorilor folosind limbajul C++ exista urmatoarele restrictii:
l Nu pot fi utilizate ca simboluri de operatori alte caractere decat cele recunoscute ca atare de limbajul C++; de exemplu putem defini o functie operator*, dar nu putem defini operatorul @.
l Urmatorii operatori nu pot fi supraincarcati: . ?: sizeof
l Nu se poate modifica prin supraincarcare precedenta unui operator (nu exista posibilitatea de a determina, de exemplu, ca '+' sa fie prioritar fata de '/').
l Nu se poate modifica numarul operanzilor preluati de un operator (dar se poate ignora unul din parametri). De asemenea nu se poate modifica sintaxa unui operator, adica nu se poate folosi, de exemplu, in mod postfix un operator pe care limbajul il accepta in mod prefix.
l Un operator trebuie sa fie, ori membru al unei clase, ori sa aiba cel putin un parametru de tipul clasei. De la aceasta regula fac exceptie doar operatorii new si delete; in felul acesta este impiedicata denaturarea semanticii unei expresii care contine doar operanzi de tipuri predefinite ale limbajului (utilizatorul nu are libertatea sa redefineasca de exemplu operatorul '*' pentru operanzi intregi astfel incat 2*2 sa nu mai returneze valoarea 4).
l Nu este posibila definirea unui operator care sa primeasca ca parametri exclusiv pointeri (exceptie operatorii: = &
l Un operator care trebuie sa accepte ca prim operand si valori ale unui tip primitiv NU poate sa fie functie membru.
Teme propuse:
1. Sa se proiecteze si sa se implementeze o clasa asociata numerelor complexe.
Clasa va contine supraancarcarea operatorului de atribuire, a principalilor
operatori aritmetici, precum si a operatorului ~ pentru operatia de calcul a
modulului unui numar complex. De asemenea, se va supraancarca operatorul ^
pentru operatia de ridicre a unui numar complex la o putere intreaga. In plus,
clasa trebuie sa posede o functie de afisare, precum si constructori care sa
permita urmatoarea secventa:
complex z1; // z1 = 0+0i
complex z2(5); // z2 = 5+0i
complex z3(2, 3); // z3 = 2+3i
complex z4 = z2;
Functia de test va utiliza un tablou de numere complexe v = (z , z , , z2*n) pentru
calculul expresiei:
z = (z + z + z2*n-1 ) / (z + z + z2*n )
2. Sa se proiecteze si sa se implementeze o clasa asociata numerelor
frationare. Clasa va contine supraancarcarea operatorului de atribuire, a
principalilor operatori aritmetici, precum si a operatorului ! pentru operatia
de simplificare a unui numar rational. De asemenea, clasa trebuie sa posede o
functie de afisare, precum si constructori adecvati. Functia de test va utiliza
un tablou de numere intregi v = (a , a , , an) pentru determinarea solutiilor rationale
ale ecuatiei:
a + a *x + + an*xn = 0
Indicatie: Daca ecuatia precedenta
are o radacina rationala x0 = p/q, pentru care cmmdc(p,q) = 1, atunci p il
divide a , iar q il divide pe an.
Observatie: Operatorii aritmetici
trebuie supraancarcati de doua ori, pentru a putea lucra si cu numere intregi.
De exemplu, expresia a + b trebuie sa poata fi evaluata, atat in cazul in care
a si b sunt numere rationale, dar si in cazul in care a este rational, iar b
este intreg;
3. Sa se proiecteze si sa se implementeze o clasa asociata fractiilor continue.
O fractie continua este o expresie de forma:
r = a + (a + 1 / (a + (1 / (a + 1 / ()))))
unde coeficientii a , a , , an sunt numere intregi. O notatie formala pentru fracria continua r este: [a , a , a , a , ].
Importanta acestor fractii consta in faptul ca pentru orice numar real x,
exista o unica fractie continua egala cu x. In cazul numerelor rationale, a , a , , anse pot determina
in mod unic, printr-un proces asemanator algoritmului lui Euclid:
r = r
ai = [ri], i = 0, 1, 2,
ri+1 = 1 / (ri - ai), i = 0, 1, 2,
Pentru o fractie continua r = [a , a , a , a , ], al k-lea termen convergent se
noteaza ck si reprezinta fractia continua: ckr = [a , a , a , , ak].
Se vor utiliza urmatorii constructori:
l Constructor implicit, pentru fractia r = 1;
l Constructor de conversie, pentru initializarea coeficientilor fractiei pe baza unui tablou de numere intregi;
l Constructor de conversie, pentru initializarea coeficientilor fractiei plecand de la un numar rational;
l Constructor de copiere.
Se vor supraancarca urmatorii operatori:
l Operatorii + si -, pentru adunarea si scaderea a 2 fractii continue;
l Operatorul [] pentru accesul la coeficientii fractiei continue;
l Operatorul () fara parametri, pentru evaluarea fractiei continue (determinarea valorii reale echivalente a fractiei);
l Operatorul () cu un parametru de tip int, pentru evaluarea celui de-al k-lea termen convergent (determinarea valorii sale reale);
Functia de test va utiliza un tablou de
fractii continue f = (f , f , , fn) pentru calculul expresiilor:
v = f + f + fn, (valoarea reala a sumei fractiilor)
ck = c f[k] + c f[k] + cnf[k], (valoarea reala a sumei termenilor
k-convergenti, pentru un intreg dat k)
4. Sa se proiecteze si sa se implementeze o clasa pentru polinoamele cu
coeficienti reali. Clasa va contine supraancarcarea operatorului de atribuire,
a principalilor operatori aritmetici, precum si a operatorului () pentru
evaluarea polinomului intr-un punct data. De asemenea, se va supraancarca
operatorul [] pentru accesul la coeficientii polinomului. In plus, clasa
trebuie sa posede o functie de afisare a polinomului, precum si constructori
adecvati. Functia de test trebuie sa verifice egalitatea a doua expresii:
v1 = P (x) - P (x) * P (x)
v2 = (P - P * P )(x)
pentru trei polinoame date si o valoare reala x data.
Acest document nu se poate descarca
E posibil sa te intereseze alte documente despre: |
Copyright © 2024 - Toate drepturile rezervate QReferat.com | Folositi documentele afisate ca sursa de inspiratie. Va recomandam sa nu copiati textul, ci sa compuneti propriul document pe baza informatiilor de pe site. { Home } { Contact } { Termeni si conditii } |
Documente similare:
|
ComentariiCaracterizari
|
Cauta document |