Laborator 3
Laborator 3
Laborator 3
3
Tema: Supraincarcarea funcțiilor și a operatorilor, funcții prietene.
Supraîncărcarea funcţiilor
Limbajul C++ permite utilizarea mai multor funcţii care au acelaşi nume,
caracteristică numită supraîncărcarea funcţiilor.
Identificarea lor se face prin numărul de parametri şi tipul lor.
Exemplu:
Dacă se apelează suma (3,5), se va apela funcţia corespunzătoare tipului int, iar
dacă se apelează suma (2.3, 9),
se va apela funcţia care are parametrii de tipul float.
La apelul funcţiei suma (2.3, 9), tipul valorii 9 va fi convertit automat de C++ în float
(nu e nevoie de typecasting).
În funcţie se pot declara valori implicite pentru unul sau mai mulţi parametri.
Atunci cînd este apelată funcţia, se poate omite specificarea valorii pentru acei parametri
formali care au declarate valori implicite. Valorile implicite se specifică o singură
dată în definiţie (de obicei în prototip). Argumentele cu valori implicite trebuie să
fie amplasate la sfîrşitul listei.
Exemplu:
void adunare (int a=5 double b=10)
{...;}
...
Adunare(); //adunare(4,10);
Adunare(1); //adunare(1,10);
Adunare(3,7); //adunare(3,7);
Supraincarcarea operatorilor
O funcţie operator are aceleaşi componente pe care le are orice funcţie, include un
nume, un tip returnat, argumente, corp şi, eventual, apartenenţa la o clasă.
Există trei elemente care trebuie stabilite la declararea operatorului, şi anume:
– este operator unar sau binar,
– este postfixat sau prefixat ca poziţie
– este funcţie membru sau nu – domeniu de acţiune.
Funcţiile operator membri vor avea cu un argument mai puţin decît cele non-
membri.
Puteţi să supraîncărcaţi numai operatorii existenţi. C++ nu vă permite definirea
unor operatori proprii.
Definirea operatorilor ca funcţii membri a unei clase prezintă o restricţie
majoră: primul operand este obligatoriu să fie de tipul clasa respectiv.
În limbajul C++ supradefinirea operatorilor este supusă unui set de restricţii:
– nu este permis introducerea de noi simboluri de operatori;
– patru operatori nu pot fi redefiniţi (vezi mai sus);
– caracteristicile operatorilor nu pot fi schimbate:
1. pluralitatea (nu se poate supradefini un operator unar ca
operator binar sau invers),
2. precedenţa şi asociativitatea,
3. prioritatea lor;
– funcţia operator trebuie sa aibă cel puţin un parametru de tipul clasa căruia îi
este asociat operatorul supradefinit.
Programatorul are libertatea de a alege natura operaţiei realizate de un operator,
însă este recomandat ca noua operaţie să fie apropiată de semnificaţia iniţială.
2. Redefinirea operatorului +
Următorul program creează o clasă Sir şi supraîncarcă operatorul plus (+) astfel
că acesta concatenează şirurile:
#include <iostream.h>
#include <iomanip.h>
#include <string.h>
class Sir // Definirea clasei
{ public:
Sir *operator +(char *sir_adaug); // operator
Sir (char *in_sir) // constructor
{ strcpy(buffer, in_sir);
lungime = strlen(buffer); }
Sir(void) {lungime =0;};
void arata_sir() { cout « buffer; };
private:
char buffer[256];
int lungime;
}; // Aici se termina clasa
void main(void)
{
Sir titlu("Autor ");
titlu = titlu + "Titlul carttii\n";
titlu.aratasir();
}
Atunci când rulaţi programul , el va începe prin atribuirea membrului buffer şirului
„Autor". Programul va utiliza apoi operatorul plus supraîncărcat pentru a
concatena caracterele „Titlul cartii". Observaţi că operatorul supraîncărcat este o
funcţie simplă care primeşte un parametru. Funcţia primeşte numai un singur
parametru. Parametrul este al doilea operand. Operaţia însăşi implică operandul
instanţei.
Operatorul supraîncărcat plus utilizează funcţiile strcpy şi strcat pentru a copia
şirul de caractere dintre ghilimele în obiectul titlu. Observaţi că acest cod din
cadrul funcţiei operator plus supraîncărcate se referă la datele membre ale
obiectului titlu în mod implicit, cu comenzi cum sunt următoarele, care plasează
valoarea curentă a tidului în obiectul temp:
strcpy (temp.buffer, buffer) ;
Programul ar putea la fel de uşor să facă referire la obiect în mod explicit, utilizând
pointerul this, ca mai jos:
strcpy(temp.buffer, this.buffer);
Din punct de vedere tehnic, parametrul i nu trebuie neapărat să fie de tipul int, dar
deoarece veţi defini de obicei matricele cu un parametru întreg, trebuie să evitaţi
utilizarea unui parametru de tipul float sau de alt tip. Atunci când apelaţi funcţia
operator supraîncărcată, C++ va atribui pointerul this la obiect şi va folosi
parametrul pentru a controla dimensiunea. Pentru a înţelege mai bine prelucrările
pe care le efectuează funcţia supraîncărcată [ ] pentru matrice, analizaţi următorul
program:
#include <iostream.h>
class TipOarecare
{
int a[3];
public:
TipOarecare(int i, int j, int k) // constructor
{
a[0] = i;
a[1] = j;
a[2] = k;
}
int operator[] (int i) {return a[i];}
};
void main(void)
{
TipOarecare ob(l, 2, 3);
cout << ob[l] ;
}
Supraîncărcarea operatorului [ ] pentru matrice vă oferă posibilitatea de a controla
mai bine crearea matricelor cu clase. Pe lângă faptul că vă permite să atribuiţi
valori distincte pentru fiecare membru, puteţi utiliza funcţiile supraîncărcate pentru
a crea un program care sî efectueze o indexare sigură a unei matrice. Indexarea
sigură a unei matrice contribuie 1a prevenirea supradepăşirii sau subdepăşirii
limitelor unei matrice în decursul execuţiei unu program. Următorul program
extinde programul precedent pentru a realiza şi indexarea sigură a matricei:
#include <iostream.h>
#include <stdlib.h>
class TipOarecare
{
int a[3];
public:
TipOarecare(int i, int j, int k)
{
a[0]=i;
a[1]=j;
a[2]=k;
}
int &operator[](int i);
};
int &tipoarecare::operator[] (int i)
{ if (i<0 || i>2 )
{
cout <<”eroare la margini. \n”;
exit (1);
}
return a[i];
}
};
void main (void)
{ TipOarecare ob(l, 2, 3) ;
cout <<ob[l]; cout <<endl;
ob[l] = 25;
cout <<ob[1]; cout <<endl;
ob[3] =44;
}
Atunci când încercaţi să accesaţi un obiect de dincolo de marginile matricei, se va
produce o eroare. În cazul programului, încercarea de a accesa elementul de la
indicele 3 se face dincolo de margini şi prin urmare programul va returna o eroare.
Atunci când executaţi programul el va genera următorul rezultat:
2
25
Eroare la margini
C:\>
Funcții prietene
#include<iostream.h>
#include<math.h>
#define PI 3.14159265358979
class complex
{
// date membru protejate(private)
double real;
double imag;
// functii membru neprotejate
public:
// constructor folosit la initializare
complex(double x=0,double y=0);
// constructor de copiere
complex(const complex &);
// modulul numarului complex
double modul();
// argumentul numarului complex
double arg();
// returneaza partea reala
double retreal();
// returneaza partea imaginara
double retimag();
// afiseaza numarul complex
void afiscomplex();
};
complex::complex(double x, double y)
{
real=x;
imag=y;
}
complex::complex(const complex &z)
{
real=z.real;
imag=z.imag;
}
double complex::modul()
{
return sqrt(real*real+imag*imag);
}
double complex::arg()
{
double a;
if( (real==0) && (imag==0) )
return 0.0;
if(imag==0)
if(real>0)
return 0.0;
else
return PI;
if(real==0)
if(imag>0)
return PI/2;
else
return (3*PI)/2;
a=atan(imag/real);
if(real<0)
return a+PI;
else
if(imag<0)
return 2*PI+a;
return a;
// real>0 si imag>0
}
double complex::retreal()
{
return real;
}
double complex::retimag()
{
return imag; }
void complex::afiscomplex()
{ cout<<real<<" + i * "<<imag; }
int main(void)
{ double x,y,sumax=0,sumay=0,i=0,n;
cout<<"Dati numarul de nr. complexe n = "; cin>>n;
while(i<n)
{
cout<<"Partea reala = ";cin>>x;
cout<<"Partea imaginara = ";
cin>>y;
sumax+=x;sumay+=y;
// se construieste nr. complex avand partile citite mai sus; se
apeleaza constructorul care realizeaza initializarea
// obiectului z=x+i*y
complex z(x,y);
// afisez numarul z
cout<<endl; z.afiscomplex(); i++;
}
complex sz=complex(sumax,sumay);
cout<<endl<<"Suma nr. complexe citite este ";
sz.afiscomplex();
return 0;
}
Sarcina
Varianta 1
Să se creeze o clasă de numere întregi. Să se definească operatorii "++" , ca metode ale clasei,
iar "-" ca funcţie prietenă. Operatorii trebuie să permită efectuarea operaţiilor cu variabilele
clasei date. Realizați supaăncărcarea funcției realizînd operații saupra datelor din clasă. Clasa
trebuie să fie absolut funcţională, adică să conţină toţi constructorii necesari şi destructorul.
Varianta 2
Să se creeze clasa 2-D de coordonate în plan. Să se definească operatorii "+" ca funcţie prietenă,
iar operatorul de atribuire – ca metodu ale clasei. De prevăzut posibilitatea efectuării operaţiilor
între coordonate. Realizați supaăncărcarea funcției realizînd operații saupra datelor din clasă.
Clasa trebuie să fie absolut funcţională, adică să conţină toţi constructorii necesari şi destructorul.
Varianta 3
Să se creeze clasa Queue –coadă, utilizînd memoria dinamică. Să se definească operatorul "=" –
de atribuire ca metode ale clasei. Să se definească operatorul de comparare "==" ca funcţie
prietenă. Să se realizeze supaăncărcarea funcției pentru inserarea/eliminarea elementelor în/din
coadă. Clasa trebuie să fie absolut funcţională, adică să conţină toţi constructorii necesari şi
destructorul.
Varianta 4
Să se creeze clasa Date – data, care conţine cîmpurile: ziua, luna, anul. Să se definească
operatorul "-" ca metodă ale clasei, iar operatorul "++" ca funcţie prietenă. Operatorii trebuie
să permită realizarea operaţiilor cu variabilele clasei. Realizați supaăncărcarea funcției pentru
prelucrarea corectă a anilor bisecţi. Clasa trebuie să fie absolut funcţională, adică să conţină toţi
constructorii necesari şi destructorul.
Varianta 5
а) Să se creeze clasa numerelor reale. Să se definească operatorul "+" ca metode ale clasei, iar
operatorul "- -" – ca funcţii prietene. Operatorii trebuie să permită realizarea operaţiilor cu
variabilele clasei date. Realizați supaăncărcarea funcției realizînd operații saupra datelor din
clasă. Clasa trebuie să fie absolut funcţională, adică să conţină toţi constructorii necesari şi
destructorul.
Varianta 6
Să se creeze clasa numerelor mari întregi. Să se definească operatorul "*" ca metode ale clasei,
iar "/" - ca funcţie prietenă. Să se supraîncarce funcția pentru incrementare şi de decrementare.
Operatorii trebuie să permită realizarea operaţiilor cu variabilele clasei date. Realizați
supaăncărcarea funcției realizînd operații saupra datelor din clasă. Clasa trebuie să fie absolut
funcţională, adică să conţină toţi constructorii necesari şi destructorul.
Varianta 7
Să se creeze clasa Bool – variabile logice. Să se definească operatorul – SAU logic ca metodă ale
clasei, iar operatorul – ŞI logic ca funcţie prietenă. Operatorii trebuie să permită realizarea
operaţiilor cu variabilele clasei date. (Dacă numărul întreg este diferit de zero, se consideră că
variabila este adevăr, altfel – fals.) Realizați supaăncărcarea funcției realizînd operații saupra
datelor din clasă. Clasa trebuie să fie absolut funcţională, adică să conţină toţi constructorii
necesari şi destructorul.
Varianta 8
Să se creeze clasa Stack – stivă, utilizînd memoria dinamică. Să se definească operatorul ca
metode ale clasei: "+" – de adunare a două stive, Să se definească operatorul de comparare: "!="
comparare a două stive, ca funcţie prietenă. Clasa trebuie să fie absolut funcţională, adică să
conţină toţi constructorii necesari şi destructorul. Realizați supaăncărcarea funcției realizînd
operații saupra datelor din clasă.
Varianta 9
Să se creeze clasa Queue – coadă, utilizînd memoria dinamică. Să se definească operatorul "+" –
de adunare a două cozi, ca metode ale clasei. Să se definească operatorul de comparare "==", ca
funcţie prietenă. Realizați supaăncărcarea funcției realizînd operații saupra datelor din clasă.
Clasa trebuie să fie absolut funcţională, adică să conţină toţi constructorii necesari şi destructorul.
Varianta 10
Să se creeze o clasă Set – mulţimea numerelor întregi, utilizînd memoria dinamică. Să se
definească operatoriul de lucru cu mulţimile – intersecţia, ca metodă ale clasei, iar "+=" –
înserarea unui nou element în mulţime, ca funcţii prietene. Realizați supaăncărcarea funcției
realizînd operații saupra datelor din clasă. Clasa trebuie să fie absolut funcţională, adică să
conţină toţi constructorii necesari şi destructorul.
Varianta 11
Să se creeze clasa String – şir, utilizînd memoria dinamică. Să se definească operatorul "+=" –
atribuirea ca funcţii prietene. Să se definească operatorul de comparare: "!=", ca metodă ale
clasei. Realizați supaăncărcarea funcției realizînd operații saupra datelor din clasă. Clasa trebuie
să fie absolut funcţională, adică să conţină toţi constructorii necesari şi destructorul.
Varianta 12
b) Să se creeze clasa List – coadă, utilizînd memoria dinamică. Să se definească operatorul "+" –
de adunare a listelor, ca funcţie prietenă. Să se definească operatorul de comparare "==", ca
metodă ale clasei. Realizați supaăncărcarea funcției realizînd operații saupra datelor din clasă.
Clasa trebuie să fie absolut funcţională, adică să conţină toţi constructorii necesari şi destructorul.