Sunteți pe pagina 1din 65

Capitolul III

Programarea orientata pe obiecte in C++:clase, obiecte, functii membru,


structuri si uniuni in analogie cu clasele, functii speciale
III. 1. Notiuni introductive
Programarea orientat pe obiecte este o tehnologie modern in domeniul programrii
calculatoarelor, care a rezultat din necesitatea realizrii de aplicaii din ce n ce mai complexe.
Programarea clasica si structurata avea urmatoarele dezavantaje: control greoi al programelor de
dimensiuni mari, dificultati cu privire la reutilizarea codurilor de programe si inflexibiliatea
adaptarii si extinderii unor module de program deja realizate. Programarea clasica structurata are
la baza celebra ecuatie a lui Nikolaus Wirth:
Program = Structuri de date + Algoritmi
Programarea Orientata pe Obiecte, POO, se fundamenteaza pe conceptul de obiect, care
este definit printr-o multime de date, numite proprietati, si o multime
de proceduri sau functii de prelucrare ale acestor date, numite metode. In consecinta,
ecuatia POO este:
Obiect = Date + Functii
sau
Obiect = Date + Functii
Obiect = Proprietati + Metode
Diferenta dintre cele doua cai de abordare ale programarii calculatoarelor consta in maniera de
abordare a programarii. In timp ce programarea clasica structurata se concentreaza pe prelucrarea
datelor, adica pe programe, proceduri si functii, POO se bazeaza pe definirea obiectelor, adica,
pe proprietatile acestora, numite date, si pe functiile acestor obiecte, numite metode.
III.2. Clase si obiecte
La baza POO stau conceptele de clasa si de obiect.
Definitia 1
Clasa, intr-un anumit limbaj de programare, reprezinta definirea unui tip de obiecte
abstracte sau concrete, adica descrierea proprietatilor, a datelor si a metodelor, a prelucrarilor,
posibile asupra datelor. Clasa este, de fapt, o notiune abstracta, care defineste un anumit tip de
obiecte, sau, altfel spus, o clasa reprezinta multimea posibila a mai multor obiecte de acelasi tip.
Definitia 2
Obiect, reprezinta o multime de date care descrie un anumit obiect concret sau abstract,
numite si proprietati, impreuna cu procedurile, functiile, de prelucrare a cestora,
numite metode.
Crearea unui obiect presupune specificarea clasei din care face parte, astfel identificandu-
se proprietatile obiectului si modul in care acestea pot fi folosite si prelucrate
Observatie:
Crearea sau declararea unui obiect este similara cu crearea sau declararea unor variabile.
Declararea unei variabile se face, dupa cum se stie, prin specificarea identificatorului acesteia,
precedat de tipul variabilei iar declararea unui obiect presupune precizarea identificatorului
acestuia, precedat de clasa din care face parte, clasa care in mod implicit determina proprietatile
si metodele obiectului definit.
O clasa in limbajul C++ poate fi reprezentata ca o extindere a conceptului de structura,
care, ca si o structura, descrie un sablon pentru viitoarele declarari de variabile obiect.
Definirea generala unei clase in C++
class [nume_clasa]
{
specificator_acces1;
date_si_functii1;
specificator_acces2;
date_si_functii2;
..
specificator_accesn;
date_si_functiin;
}[obiect1] [,obiect2] [,obiectm];
unde:
- nume_clasa optional, este un identificator ales de programator care denumeste clasa
definita si prin intermediul caruia se apeleaza aceasta;
- specificator_accesi (i=1,n) este o eticheta care poate fi unul dintre cuvinele
cheie: public, private sau protected.
Spre deosebire de o structura, ai carei membri sunt toti accesibili programului,
o clasa poate avea membri pe care programul ii poate accesa direct (public), utilizand
operatorul punct (.) si alti membri, denumiti privati (private), pe care programul nu-i
poate accesa direct. Unica accesare a datelor si metodelor private (private) se face
numai prin intermediul metodelor publice. Dupa cum se va vedea, o clasa poate deriva
dintr-o clasa de baza, anterior definita, concept cunoscut sub numele
de mostenire. Un membru protejat (protected) are un statut intermediar intre membri
publici si privati. Pentru clasa de baza, obiectele acesteia pot accesa membri protejati,
ca si cum ar fi publici, iar obiectele claselor derivate nu pot accesa un membru
declarat protected in clasa de baza, decat prin intermediul unor functii de interfata
declarate publice.
- date_si_functiii; (i=1,n) descrie datele, adica proprietatile, si functiile, adica metodele
specifice clasei definite care, in functie de specificator_accesi (i=1,n), pot
fi public, private sau protected.
- [obiect1] [,obiect2] [,obiectm] reprezinta identificatorii obiectelor de tipul clasei la
care sunt atasati, adica numele variabilelor obiect respective care vor fi utilizate in programul in
care apar.
Observatii:
- la declararea obiectelor, o data cu definirea clasei asociate, se poate omite
identificatorul de clasa, nume_clasa.
- declararea obiectelor, ulterior definirii clasei asociate, impune obligativitatea
identificatorului de clasa, nume_clasa.
Declararea obiectelor, ulterior definirii clase se face astfel:
class nume_clasa [obiect1] [,obiect2] [,obiectm];
unde, nume_clasa,obiect1,obiect2, ,obiectm au semnificatiilie mai sus prezentate.
Problema 17
Sa se citeasca de la tastatura informatiile specifice cartilor dintr-o librarie: denumire
carte, autorul principal, al doilea autor, numarul de pagini si pretul. Prin intermediul unei clase,
carte, care descrie datele despre o carte, proprietatile (denumire carte, autorul principal, al doilea
autor, numarul de pagini si pretul) si metodele de prelucrare (initializarea si afisarea unei carti)
sa se afiseze pe ecran informatiile despre orice carte tratata.
// definirea clasei carte
#include<iostream.h>
#include<string.h>
#include<stdio.h>
class carte
{
public:
char nume[40];
char autor1[40];
char autor2[40];
int nrpag;
double pret;
void citeste_carte(char *numecarte,char *autorcarte1,char *autorcarte2,int *np,double *p);
void afiseaza_carte();
};
// descrirea functiei de citire carte
void carte::citeste_carte(char *numecarte,char *numeautor1,
char *numeautor2,int *np,double *p)
{
strcpy(nume,numecarte);
strcpy(autor1,numeautor1);
strcpy(autor2,numeautor2);
nrpag=*np;
pret=*p;
}
void carte::afiseaza_carte()
{
cout<<"\n cartea nr."<<i<<":"<<nume<<endl;
cout<<"\n primul autor:"<<autor1<<endl;
cout<<"\n al doilea autor:"<<autor2<<endl;
cout<<"\n nr pagini:"<<nrpag<<endl;
cout<<"\n pretul:"<<pret<<endl;
}
int i=0;
void main()
{
carte carteacitita;
char wnume[40],wautor1[40],wautor2[40];
int wnrpag;
double wpret;
char r='d';
while(r=='d')
{
printf("\n denumirea cartii:");
gets(wnume);
printf("\n primul autor:");
gets(wautor1);
printf("\n al doilea autor:");
gets(wautor2);
cout<<"\n nr. pagini:";
cin>>wnrpag;
cout<<"\n pret:";
cin>>wpret;
carteacitita.citeste_carte(wnume,wautor1,wautor2,&wnrpag,&wpret);
carteacitita.afiseaza_carte();
cout<<"\n continuati?(d/n):";
cin>>r;
}
}
In urma executarii programului anterior s-au obtinut urmatoarele rezultate, care arata cum
se declara o clasa, un obiect al acestei clase si modul in care se apeleaza membrii acestei clase,
prin intermediul unei instante a acestei clase.

denumirea cartii:Trecea o moara pe Siret


primul autor:Mihail Sadoveanu
al doilea autor: --
nr. pagini:200
pret:30

cartea nr.0:Trecea o moara pe Siret


primul autor:Mihail Sadoveanu
al doilea autor: --
nr pagini:200
pretul:30
continuati?(d/n):d

denumirea cartii:O noapte furtunoasa


primul autor:Ion Luca Caragiale
al doilea autor: --
nr. pagini:50
pret:25
continuati?(d/n):n

Problema 18
Daca, in programul de mai sus, textul definirii clasei carte impreuna cu textele functiilor
precizate in clasa, citeste_carte si afiseaza_carte se salveaza ca un fisier header in
directorul include, fie el carti.h, atunci programul de mai sus va arata astfel:
int i;
#include<iostream.h>
#include<string.h>
#include<carti.h>
void main()
{
carte carteacitita;
char wnume[40],wautor1[40],wautor2[40];
int wnrpag;
double wpret;
char r='d';
while(r=='d')
{
printf("\n denumirea cartii:");
gets(wnume);
printf("\n primul autor:");
gets(wautor1);
printf("\n al doilea autor:");
gets(wautor2);
cout<<"\n nr. pagini:";
cin>>wnrpag;
cout<<"\n pret:";
cin>>wpret;
carteacitita.citeste_carte(wnume,wautor1,wautor2,&wnrpag,&wpret);
carteacitita.afiseaza_carte();
cout<<"\n continuati?(d/n):";
cin>>r;
}
}
In urma executarii acestui program, se obtin aceleasi rezultate ca in problema precedenta,
cu deosebirea ca referirea clasei carte se face acum din fisierul header, carti.h.
Problema 19
Pentru orice sir de caractere, introdus de la tastatura, printr-un meniu adecvat, sa se
realizeze, utilizandu-se o clasa clasasir, urmatoarele operatii: conversia sirului la caractere mici,
conversia la caractere mari si adaugarea unui subsir la sirul dat.
#include<stdio.h>
#include<conio.h>
#include<string.h>
class clasasir
{
//definirea clasei sir
char sir[80]; // variabila sir ca membru privat implicit
public:
// declararea functiei de copiere sir
void copy (char *s) { strcpy(sir,s);}
// initializarea cu spatii a sirului s
clasasir(char *s=" ") {copy(s);}
// declararea functiei de scriere
void scrie(FILE *fileptr);
// declararea functiei de citire
void citeste(FILE *fileptr);
// declararea functiei de concatenare siruri
void operator +=(clasasir &s)
{
strcat(sir,s.sir); //concatenare siruri
}
// declararea functiei friend conversie caractere
friend void conversie(clasasir &s,char optiune);
}; // sfarsitul declararii clasei
// descrierea functiei de scriere
void clasasir::scrie(FILE *fileptr)
{
fprintf(fileptr,"\n sirul modificat este:%s",sir);
}
// descrierea functiei de citire
void clasasir::citeste(FILE *fileptr)
{
// citeste din fisierul *fileptr si depune in sir
int sizesir; // se memoreaza lungimea sirului citit
fgets(sir,80,fileptr);
sizesir=strlen(sir)-1;
if(sir[sizesir]=='\n') sir[sizesir]=0;
}
// descrierea functiei de conversie sir
void conversie(clasasir &s,char optiune)
{
clasasir tempsir;
switch (optiune)
{
case '1': strupr(s.sir);//conversie in majuscule
break;
case '2': strlwr(s.sir);//conversie in minuscule
break;
case '3': printf("\n introduceti un sir (max 80):");
tempsir.citeste(stdin); //citeste un alt sir
s+=tempsir; //concateneaza sirurile
break;
default: printf("\n optiune eronata \n");
}
}
void main()
{
clasasir clsir; //declararea obiectului clsir
char alegere='1',r='d';
while (r=='d')
{
printf("\n dati un sir (max=80 caractere):");
clsir.citeste(stdin);
do
{
// afisarea meniului de comenzi
printf("\n ==============================");
printf("\n 1. conversie sir in majuscule");
printf("\n 2. conversie sir in minuscule");
printf("\n 3. adaugare subsir la sirul dat");
printf("\n t. terminare program");
printf("\n ==============================");
printf("\n alegeti o optiune:");
alegere=getchar();getchar();
}
while((alegere!='1')&&(alegere!='2')&&
(alegere!='3')&&(alegere!='t'));
while(alegere!='t')
{
conversie(clsir,alegere);
clsir.scrie(stdout);
do
{
// reafisarea meniului de comenzi
printf("\n ==============================");
printf("\n 1. conversie sir in majuscule");
printf("\n 2. conversie sir in minuscule");
printf("\n 3. adaugare subsir la sirul dat");
printf("\n t. terminare program");
printf("\n ==============================");
printf("\n alegeti o optiune:");
alegere=getchar();getchar();
}
while((alegere!='1')&&(alegere!='2')&&
(alegere!='3')&&(alegere!='t'));
}
printf("\n continuati?(d/n):");
r=getche();
}
printf("\n terminat \n");
}
In urma executarii programului de mai sus, s-au obtinut rezultatele din lista de mai
jos, care pun in evidenta declararea si folosirea membrilor publici si privati, prin intermediul
unei instante a clasei declarate.

dati un sir (max=80 caractere):ana are mere


==============================
1. conversie sir in majuscule
2. conversie sir in minuscule
3. adaugare subsir la sirul dat
t. terminare program
==============================
alegeti o optiune:1
sirul modificat este:ANA ARE MERE
==============================
1. conversie sir in majuscule
2. conversie sir in minuscule
3. adaugare subsir la sirul dat
t. terminare program
==============================
alegeti o optiune:2
sirul modificat este:ana are mere
==============================
1. conversie sir in majuscule
2. conversie sir in minuscule
3. adaugare subsir la sirul dat
t. terminare program
==============================
alegeti o optiune:3
introduceti un sir (max 80): frumoase
sirul modificat este:ana are mere frumoase
==============================
1. conversie sir in majuscule
2. conversie sir in minuscule
3. adaugare subsir la sirul dat
t. terminare program
==============================
alegeti o optiune:1
sirul modificat este:ANA ARE MERE FRUMOASE
=====================================
1. conversie sir in majuscule
2. conversie sir in minuscule
3. adaugare subsir la sirul dat
t. terminare program
==============================
alegeti o optiune:2
sirul modificat este:ana are mere frumoase
==============================
1. conversie sir in majuscule
2. conversie sir in minuscule
3. adaugare subsir la sirul dat
t. terminare program
==============================
alegeti o optiune:3
introduceti un sir (max 80): si mari
sirul modificat este:ana are mere frumoase si mari
====================================
1. conversie sir in majuscule
2. conversie sir in minuscule
3. adaugare subsir la sirul dat
t. terminare program
==============================
alegeti o optiune:1
sirul modificat este:ANA ARE MERE FRUMOASE SI MARI
=============================================
1. conversie sir in majuscule
2. conversie sir in minuscule
3. adaugare subsir la sirul dat
t. terminare program
==============================
alegeti o optiune:2
sirul modificat este:ana are mere frumoase si mari
===================================
1. conversie sir in majuscule
2. conversie sir in minuscule
3. adaugare subsir la sirul dat
t. terminare program
==============================
alegeti o optiune:t
==============================
terminat
continuati?(d/n):n

In programul de mai sus s-a declarat o clasa numita clasasir, utilizata pentru declararea
obiectelor specifice acesteia (exemplu clasasir tempsir) si are ca membri date si functii. Se
constata ca unii membri sunt publici, marcati cu eticheta public:
functiile copy, scrie, citeste, operator si conversie iar altii sunt privati, nemarcati cu nici o
eticheta sau marcati cu eticheta private: variabila (data) sir de exemplu. Se observa, de
asemenea, ca unele functii sunt descrise in corpul clasei clasasir: copy si operator iar altele sunt
descrise in afara clasei: citeste, scrie si conversie. Membri publici ai unei clase, date sau functii
publice, pot fi accesati din interiorul si exteriorul clasei. De exemplu, functiile citeste si scrie au
fost accesate direct din functia main prin intermediul obiectului clsir al
clasei clasasir : clsir.citestesi respectiv clsir.scrie. Membri privati ai unei clase nu pot fi accesati
decat din interiorul clasei. Membrul privat sir a fost accesat numai din interiorul clasei de catre
functiile membre: copy, citeste si scrieindiferent daca sunt descrise in interiorul sau in exteriorul
clasei.
III. 3. Functii membru ale unei clase
Functiile membru ale unei clase sunt functiile descrise sau declarate in
interiorul unei clase. Deci, descrierea efectiva a functiilor membru ale unei clase se
poate face, fie in interiorul clasei, fie in afara clasei, daca in interiorul clasei s-au
declarat ca prototipuri. Ele pot fi accesate din interiorul clasei si din afara clasei, prin
intermediul obiectelor declarate, daca au fost declarate publice, sau numai direct din
interiorul clasei de catre alte functii membru ale aceleiasi clase, daca au fost declarate
private.
III. 3. 1. Apelarea unei functii membru al unei clase
Apelarea unei functii membru, din interiorul unei clase, se face precizandu-se
numele acesteia si parametrii efectivi:
nume_functie_membru(parametri_efectivi_de_apel)
ca in problema de mai sus: clasasir(char *s=" ") {copy(s);}
Apelarea unei functii membru, din exteriorul unei clase, se face precizandu-se
obiectul declarat, numele acesteia si parametri efectivi:
nume_obiect.nume_functie_membru(parametri_efectivi_de_apel)
asa cum s-a precizat mai sus: clsir.citeste, clsir.scrie.
III. 3. 2. Functii friend
Functiile friend sunt functii obisnuite declarate intr-o clasa, precedate de calificativul friend.
friend nume_functie_membru(parametri_formali)
Acest calificativ le permite sa acceseze membrii privati ai unei clase, din exteriorul
acesteia, asa cum este cazul functiei conversie din problema precedenta:
friend void conversie(clasasir &s,char optiune);
Apelarea unei functii friend se face asemanator cu apelarea oricarei functii din C++,
ca de exemplu, in functia main() a programului de mai sus: conversie(clsir,alegere);
Variabile de tip referinta
O variabila de tip referinta, in definirea unei functii, este precedata de
operatorul adresa &, iar in corpul functiei variabila este referita normal, ca o variabila
de tip structura. De fapt, o variabila de tip referinta este un alias, un pseudonim,
pentru alta variabila, in esenta, un pointer cu urmatoarele precizari:
- odata initializata valoarea sa nu se mai poate modifica
- eliberarea, anularea referirii, se face in mod automat
Variabila referinta se utilizeaza, in corpul functiei, ca o structura (exemplu, in
programul de mai sus: s.sir) si nu ca un pointer la o structura, asa cum eram obisnuiti
la structuri (s->sir)
Variabilele referinta, dupa cum se stie, permit transmiterea parametrilor la functia
apelata, prin adrese si nu prin valoare, eliminand, astfel, pierderile de timp cu copierea
parametrilor efectivi in memoria stiva Apelarea unei functii membru cu parametri de
tip referinta se face fara a preceda parametri respectivi de operatorul
adresa & (exemplu, in functia main()de mai sus:conversie(clsir,alegere))
III. 4. Membri statici ai unei calase
Oricare obiect declarat intr-un program, in mod normal, primeste o copie a
membrilor clasei la care este asociat. Uneori, este nevoie sa se defineasca unii
membrii care sunt folositi in comun de catre toate obiectele clasei. Astfel de membri
se numesc membri statici care au proprietati diferite de ceilalti membri nestatici.
Declararea unui membru static presupune precedarea acestuia de cuvantul
cheie static:
static tip_membru nume_membru_static;
iar referirea unui membru static se face astfel:
nume_clasa::nume_membru_static;
unde, nume_membru_static poate fi o data sau o functie membru statica
Referirea unui membru static se poate face chiar si inaintea declararii de
obiecte ale clasei, in care a fost declarat membru static respectiv, iar initializarea sa se
poate face numai in domeniul sau de vizibilitate.
Problema 20
Se considera o clasa de puncte din spatiu in care se descrie un punct de
coordonate fixe M0(x0,y0,z0), reprezentand centrul unei sfere, raza fixa a unei sferei
ro si un punct oarecare din spatiu M(x,y,z) si functiile:distanta(M0,M) care determina
distanta dintre punctele M0 si M, pozitia_fata_de_centru(M), care
determina coordonatele punctului M in raport cu centrul sferei si pozitia(M) care
precizeaza pozitia punctului M fata de sfera. Sa se scrie un program care sa sa
calculeze distanta dintre punctele M0 si M, coordonatele punctului M fata de centrul
sferei si sa determine pozitia punctului M fata de sfera utilizandu-se obiecte din clasa
declarata.
#include<iostream.h>
#include<conio.h>
#include<math.h>
// definirea clasei clspunct
class clspunct
{
public:
static int x0,y0,z0,raza;
int x,y,z;
double distanta(void)
{
return(sqrt((x-x0)*(x-x0)+(y-y0)*
(y-y0)+(z-z0)*(z-z0)));
}
int poz_x_fata_m0(void)
{
return(x-x0);
}
int poz_y_fata_m0(void)
{
return(y-y0);
}
int poz_z_fata_m0(void)
{
return(z-z0);
}
double poz_m_fata_sfera(void)
{
return(distanta()-raza);
}
};
// initializare datelor statice inainte de
// declararea obiectelor clasei
int clspunct::x0=10;
int clspunct::y0=10;
int clspunct::z0=10;
int clspunct::raza=10;
void main(void)
{
// declararea obiectelor ob1 si ob2
clspunct a;
char r='d';
while(r=='d')
{
cout<<"\n sfera are la inceput raza "
<<a.raza<<" si centrul in M0("
<<a.x0<<','<<a.y0<<','<<a.z0<<")";
cout<<"\n coordonatele unui pct (int x,y,z):";
cin>>a.x>>a.y>>a.z;
cout<<"\n distanta(M0("<<a.x0<<','<<a.y0<<','
<<a.z0<<"),M1("<<a.x<<','<<a.y<<','
<<a.z<<"))="<<a.distanta();
cout<<"\n coordonatel lui M fata de centru("
<<a.poz_x_fata_m0()<<','<<a.poz_y_fata_m0()
<<','<<a.poz_z_fata_m0()<<")";
if(a.poz_m_fata_sfera()>0)
cout<<"\n punctul M("<<a.x<<','<<a.y<<','
<<a.z<<") este exterior sferei";
if(a.poz_m_fata_sfera()<0)
cout<<"\n punctul M("<<a.x<<','<<a.y<<','
<<a.z<<") este interior sferei";
if(a.poz_m_fata_sfera()==0)
cout<<"\n punctul M("<<a.x<<','<<a.y<<','
<<a.z<<") este pe sfera";
// se modifica datele statice
a.x0=1;a.y0=1;a.z0=1;a.raza=10;
cout<<"\n sfera modificata are raza "<<a.raza
<<" si centrul in M0("<<a.x0<<','<<a.y0
<<','<<a.z0<<")";
cout<<"\n distanta(M0("<<a.x0<<','<<a.y0<<','
<<a.z0<<"),M1("<<a.x<<','<<a.y<<','
<<a.z<<"))="<<a.distanta();
cout<<"\n coordonatel lui M fata de centru("
<<a.poz_x_fata_m0()<<','<<a.poz_y_fata_m0()
<<','<<a.poz_z_fata_m0()<<")";
if(a.poz_m_fata_sfera()>0)
cout<<"\n punctul M("<<a.x<<','<<a.y<<','
<<a.z<<") este exterior sferei";
if(a.poz_m_fata_sfera()<0)
cout<<"\n punctul M("<<a.x<<','<<a.y<<','
<<a.z<<") este interior sferei";
if(a.poz_m_fata_sfera()==0)
cout<<"\n punctul M("<<a.x<<','<<a.y<<','
<<a.z<<") este pe sfera";
cout<<"\n continuati?(d/n):";
cin>>r;
}
}
In urma executarii programului de mai sus, s-au obtinut rezultatele din lista de
mai jos, evidentiindu-se declararea si modul de utilizare a membrilor statici precizati
in clasa definita.
sfera are la inceput raza 10 si centrul in M0(10,10,10)
coordonatele unui pct (int x,y,z):20 30 40

distanta(M0(10,10,10),M1(20,30,40))=37.4166
coordonatel lui M fata de centru(10,20,30)
punctul M(20,30,40) este exterior sferei
sfera modificata are raza 10 si centrul in M0(1,1,1)
distanta(M0(1,1,1),M1(20,30,40))=52.1824
coordonatel lui M fata de centru(19,29,39)
punctul M(20,30,40) este exterior sferei
continuati?(d/n):d

sfera are la inceput raza 10 si centrul in M0(1,1,1)


coordonatele unui pct (int x,y,z):1 2 3
distanta(M0(1,1,1),M1(1,2,3))=2.23607
coordonatel lui M fata de centru(0,1,2)
punctul M(1,2,3) este interior sferei
sfera modificata are raza 10 si centrul in M0(1,1,1)
distanta(M0(1,1,1),M1(1,2,3))=2.23607
coordonatel lui M fata de centru(0,1,2)
punctul M(1,2,3) este interior sferei

continuati?(d/n):d
sfera are la inceput raza 10 si centrul in M0(1,1,1)
coordonatele unui pct (int x,y,z):-10 -20 20
distanta(M0(1,1,1),M1(-10,-20,20))=30.3809
coordonatel lui M fata de centru(-11,-21,19)
punctul M(-10,-20,20) este exterior sferei
sfera modificata are raza 10 si centrul in M0(1,1,1)
distanta(M0(1,1,1),M1(-10,-20,20))=30.3809
coordonatel lui M fata de centru(-11,-21,19)
punctul M(-10,-20,20) este exterior sferei
continuati?(d/n):n

Spre deosebire de o functie membru nestatica, o functie membru statica poate fi


apelata cu sau fara sintaxa specifica unei functii membru:
Exemplu:
.
class clsx
{
int b;
public:

static void nume_functie(int a, clsx *ptr);
..
};
.
void main(void)
{
int i=1;
clsx obiect;
// apelari corecte numai pentru functii statice
clsx::nume_functie1(i,&obiect);
obiect.functie(i,&obiect);
// apelare eronata
functie(i.obiect);
..
}
Functiile statice nu sunt aplicate unui obiect anume si din acest motiv ele nu
accepta ca parametru implicit pointerul this. Si ca atare, din corpul unei functii statice
nu se pot accesa membrii obiectelor decat prin calificare explicita, utilizand sageata
dreapta (->) sau punctul (.). Pentru declaratia din exemplul de mai sus descrierea
functiei statice se face astfel:
Exemplu:
void clsx::functie(int i,clsx *ptr)
{
..
ptr->b=i; // se atribuie datei b din obiectul ptr al ckasei clsx
b=i; // atribuire incorecta

}
Observatie:
Utilizarea principala a membrilor statici este determinata de necesitatea
memorarii datelor comune tuturor obiectelor create, de aceeasi clasa, cum ar fi:
- pastrarea unor informatii comune tuturor obiectelor unei clase: semafoare,
comutatori.
- inregistrarea numarului obiectelor create asociate aceleiasi clase
- reducerea numarului declaratiilor globale
- validarea accesului la denumirea campurilor de date

III. 5. Pointerul this din C++


Apelarea unei functii membru pozitioneaza un pointer la obiectul de tipul clasei
asociate. In momentul apelului, acest pointer apare ca un argument suplimentar
nevizibil. El poate fi referit, totusi, cu ajutorul cuvantului cheie this (aici). Utilizarea
de baza a cuvantului cheie this este legata de descrierea functiilor membru care
manipuleaza pointeri. Deoarece this este un cuvant cheie in C++, el nu poate fi
declarat explicit iar, in orice functie membru nestatica a unei clase, pointerul this este
declarat implicit ca nume_clasa *this si initializat sa adreseze spre obiectul pentru
care este apelata functia membru. Utilizarea pointerului this poate fi pusa in evidenta
in functia care insereaza o componenta intr-o lista dublu inlantuita.
Exemplu:
.
class clsinsert
{
clsinsert *anterior;
clsinsert *urmator;
public:
void finsert(clsinsert *);
.
};
void clsinsert::finsert(clsinsert *ptr)
{
//utilizare implicita, ptr->urmator=this->urmator;
ptr->urmator=urmator;
//utilizare explicita a lui this
ptr->anterior=this;
//utilizare implicita, this->urmator->anterior=ptr;
urmator->anterior=ptr;
//utilizare implicita, this->urmator=ptr;
urmator=ptr;
}
III. 6. Structuri si uniuni, analogii cu clasele din C++
Limajul C++, dupa cum am mai precizat, reprezinta o extensie a limajului C.
Toate facilitatile limbajului C se regasesc in limbajul C++. In continuare, se va pune
accentul pe deosebirile dintre cele doua limbaje si, cu precadere, pe extensiile aduse
de C++ la C.
In C++ clasele nu sunt, altceva, decat extensii ale structurilor din limbajul C.
Mai mult, structurile in C++, sunt constructii mult mai puternice decat in C.
Structurile, ca si clasele, pe langa date, pot contine descrieri si/sau declarari de functii
prototip, inclusiv functii constructor, care sunt de fapt metode publice ce au acelasi
nume cu clasa si care se executa automat ori de cate ori se creeaza o instanta,
un obiect, al unei clase, si functii destructor, care sunt tot metode publice ce au
acelasi nume cu clasa si care se executa, de obicei, la terminarea programului pentru
distrugerea instantei unui clase, cu scopul eliberarii memoriei alocate, anterior,
instantei.
III. 6. 1. Structuri in limbajul C++
In C++, o structura este, de fapt, o clasa ai carei membri sunt declarati, in mod
implicit, public. In consecinta in C++, la declararea unei variabile de tip structura nu
mai este obligatorie precizarea cuvantului cheie struct.
Exemplu:
a) descrierea unei structuri in C b) descrierea unei structuri in C++
typedef struct struct tip_student
{ {
int matricola; int matricola;
char nume[20]; char nume[20];
int nr_note; int nr_note;
double nota[15]; double nota[15];
double media; double media;
}tip_student; }
Iar declararea de variabile de tipul structurii de mai sus, in C si in C++ se face astfel:
a) struct tip_student s1,s2,student; b) tip_student s1,s2, student;
Problema 21
Sa se creeze un tablou de structuri de tip student (cod matricol, un numar in
intervalul 1..999; nume student, un sir de 20 caractere; numar de note, un numar in
intervalul 1..15, notele: nota(1), nota(2) si media calculata) pentru maximum nmax
(20) studenti si apoi sa se afiseze un tabel cu mediile studentilor, utilizandu-se
declararea unei structuri specifice limbajului C++ care sa includa descrierea structurii,
functia de citire si cea de afisare a informatiilor unui student.
#include<stdio.h>
#include<iostream.h>
#include<iomanip.h>
#include<conio.h>
#include<string.h>
#define nmax 20
struct tip_student
{
int cm;
char nume[20];
int nrn;
double nota[15];
double media;
void citeste_student(int wcm,char wnume[20],int wnrn,
double wnota[15],double wmedia)
{
int i;
this->cm=wcm;
strcpy(this->nume,wnume);
this->nrn=wnrn;
this->media=0;
for(i=0;i<wnrn;i++)
{
this->media=this->media+wnota[i];
}
this->media=this->media/this->nrn;
wmedia=this->media;
}
void afisaza_student()
{
printf("\n %5d %-22s %6.2lf",this->cm,this->nume,this->media);
}
};
void main(void)
{
tip_student student[nmax]; char r='d';
int wcm,wnrn;char wnume[20];double wnota[15];
int k,i=0;
while((r=='d')&&(i<nmax))
{
do
{
printf("\n cod student (1..999):");
scanf("%d",&wcm);
}
while((wcm<1)||(wcm>999));
printf("\n nume student:");
cin.getline(wnume,20,'\n');
do
{
printf("\n nr note(1..15):");
scanf("%d",&wnrn);
}
while((wnrn<1)||(wnrn>15));
for(k=0;k<wnrn;k++)
{
do
{
printf("\n nota(%d)=",k);
scanf("%lf",&wnota[k]);
}
while((wnota[k]<1)||(wnota[k]>10));
}
student[i].citeste_student(wcm,wnume,wnrn,wnota,0);
i++;
printf("\n continuati?(d/n):");
r=getche();
}
printf("\n mediile studentilor ");
printf("\n =====================================");
printf("\n cod nume si prenume media ");
printf("\n =====================================");
for(k=0;k<i;k++) student[k].afisaza_student();
printf("\n =====================================\n");
}
Rezultatele executiei programului, de mai sus, sunt prezentate in continuare,
putandu-se urmari cum se declara si se utilizeaza o structura care, pe langa campurile
componente, contine si doua functii membre, cu care se prelucreaza datele unei
structuri date
cod student (1..999):100
nume student:popescu ilie
nr note(1..15):3
nota(0)=2.55
nota(1)=8.45
nota(2)=9.50

continuati?(d/n):d
cod student (1..999):200
nume student:ionescu stefan
nr note(1..15):4
nota(0)=9.25
nota(1)=7.50
nota(2)=4.95
nota(3)=8.30

continuati?(d/n):d
cod student (1..999):150
nume student:tomescu stan
nr note(1..15):2
nota(0)=8.21
nota(1)=6.13
continuati?(d/n):n

mediile studentilor
==========================
cod nume si prenume media
==========================
100 popescu ilie 6.83
200 ionescu stefan 7.50
150 tomescu stan 7.17
==========================

In problema de mai sus, citirea efectiva a campurilor unei componente a tabloui student poate fi
inclusa chiar in definirea structurii tip_student, ca in problema de mai jos:
Problema 22
Aceeasi problema ca cea de mai sus, cu deosebirea ca citire efectiva a
campurilor unei componente a tabloului student se face in functia citeste_student(),
membru al structurii tip_student.
#include<stdio.h>
#include<iostream.h>
#include<iomanip.h>
#include<conio.h>
#include<string.h>
#define nmax 20
struct tip_student
{
int cm;
char nume[20];
int nrn;
double nota[15];
double media;
void citeste_student()
{
int k;
int wcm,wnrn;char wnume[20];
double wnota[15],wmedia;
do
{
printf("\n cod student (1..999):");
scanf("%d",&wcm);
}
while((wcm<1)||(wcm>999));
printf("\n nume student:");
cin.getline(wnume,20,'\n');
do
{
printf("\n nr note(1..15):");
scanf("%d",&wnrn);
}
while((wnrn<1)||(wnrn>15));
for(k=0;k<wnrn;k++)
{
do
{
printf("\n nota(%d)=",k);
scanf("%lf",&wnota[k]);
}
while((wnota[k]<1)||(wnota[k]>10));
}
this->cm=wcm;
strcpy(this->nume,wnume);
this->nrn=wnrn;
this->media=0;
for(k=0;k<wnrn;k++)
{
this->media=this->media+wnota[k];
}
this->media=this->media/this->nrn;
wmedia=this->media;
}
void afisaza_student()
{
printf("\n %5d %-22s %6.2lf",this->cm,this->nume,this->media);
}
}; // sfarsitul definirii structurii tip_student
void main(void)
{
tip_student student[nmax]; char r='d';
int i=0,k;
while((r=='d')&&(i<nmax))
{
student[i].citeste_student();
i++;
printf("\n continuati?(d/n):");
r=getche();
}
printf("\n mediile studentilor ");
printf("\n =====================================");
printf("\n cod nume si prenume media ");
printf("\n =====================================");
for(k=0;k<i;k++) student[k].afisaza_student();
printf("\n =====================================\n");
}

III. 6. 2. Uniuni in limbajul C++


In limbajul C++, tipul uniune de date, precizat prin cuvantul cheie union, se
defineste in mod similar cu definirea unei structuri, adica, tot ca si o clasa ai carei
membri sunt considerati in mod implicit public, pana la prima
declaratie private explicita. Ca si la declararea variabilelor de tip structura, in C++, la
declararea unei variabile de tip union nu mai este obligatorie precizarea cuvantului
cheie union. Dupa cum se stie, fata de o structura, tipul union declara date de acelasi
tip sau de tipuri diferite care utilizeaza in comun aceeasi zona de memorie, dar la
momente diferite de timp. Partajarea aceleasi zone de memorie de catre doua sau mai
multe variabile nu se poate realiza cu o structura sau o clasa obisnuita. Tipul union de
date are si cateva restrictii importante cum ar fi:
- nu poate include obiecte care sa contina functii constructor si destructor,
fara a se intelege ca tipul union nu poate avea definite
functii constructor si destructor proprii.
- nu poate include membri statici: date si functii statice
- nu poate fi mostenirea altei clase si nu poate servi, ca baza, pentru definirea,
derivarea, altei clase.
Problema 23
Se introduc, pe rand, de la tastatura oricare n (1<=n<=nmax) numere reale
(float) si 2*n numere intregi (int) si care vor folosi in comun aceasi zona de memorie.
Sa se afiseze, pe rand, numerele introduse, cele reale si cele integi, impreuna cu
mediile lor aritmetice, utilzandu-se un tip union adecvat care sa contina datele care
utilizeaza in comun aceeasi zona de memorie precum si functiile membru de citire,
calcul medii si de afisare a datelor si rezultatelor.
#include <stdio.h>
#include <conio.h>
#include<malloc.h>
const int nmax=20;
union tipnumere
{
long int x[nmax];
double y[nmax/2];
void citeste_intregi(long int n)
{
int k;
printf("\n introduceti cele %d de nr. intregi in uniunea u:",n);
for (k=0;k<n;k++)
{
printf("\n x(%d)=",k);
scanf("%d",&this->x[k]);
}
}
void citeste_reale(long int n)
{
int k;
printf("\n introduceti cele %d de numere reale din uniunea u:",n/2);
for (k=0;k<(n/2);k++)
{
printf("\n y(%d)=",k);
scanf("%lf",&this->y[k]);
}
}
void calcul_medie_intregi(int n)
{
int k;
double mint=0;
printf("\n nr intregi si calculul medie in uniune:\n");
/* insumarea numerelor intregi */
for(k=0;k<n;k++)
{
printf("%ld ",this->x[k]);
mint=mint+this->x[k];
}
printf("\n media arit. a celor %d nr. intregi=%1.2lf",n,mint/n);
}
void calcul_medie_reale(int n)
{
int k;
double mfloat=0;
printf("\n nr reale si calculul medie in uniune:\n");
/* insumarea numerelor intregi */
for(k=0;k<(n/2);k++)
{
printf("%1.2lf ",this->y[k]);
mfloat=mfloat+this->y[k];
}
printf("\n media arit. a celor %d nr.reale=%1.2lf",n/2,2*mfloat/n);
}
}; // sfarsitul descrierii uniunii
void main(void)
{
tipnumere u,v1,v2,*pv1,*pv2;int k,n;
double mint,mfloat; char r='d';
while(r=='d')
{
mint=0,mfloat=0;
do
{
printf("\n nr par de numere intregi (1<=n<=%d):",nmax);
scanf("%d",&n);
}
while((n<1)||(n>nmax)||(n%2));
// apelarea functiei membru ptr citirea a n nr intregi
u.citeste_intregi(n);
v1=u; /* atribuire de variabila de tip uniune cu numere intregi*/
// apelarea functiei membru ptr citirea a n/2 nr reale
u.citeste_reale(n);
v2=u; /* atribuire de variabila de tip uniune cu numere reale*/
pv1=&v1; /* adresa variabilei uniune v1 in pointerul pv1 */
pv2=&v2; /* adresa variabilei uniune v2 in pointerul pv2 */
/* afisarea numerelor intregi si calcularea mediei aritmetice a acestora */
// apelarea functiei membru ptr calculul mediei nr intregi
v1.calcul_medie_intregi(n);
printf("\n nr intregi si media calculate in main:\n");
/* insumarea numerelor intregi */
for(k=0;k<n;k++)
{
printf("%ld ",pv1->x[k]);
mint=mint+pv1->x[k];
}
printf("\n media celor %d nr. intregi=%1.2lf",n,mint/n);
/* afisarea numerelor reale si calcularea mediei aritmetice a acestora */
// apelarea functiei membru ptr calculul mediei nr reale
v2.calcul_medie_reale(n);
printf("\n nr reale si media calculate in main:\n");
/* insumarea numerelor reale */
for(k=0;k<(n/2);k++)
{
printf("%1.2lf ",pv2->y[k]);
mfloat=mfloat+pv2->y[k];
}
printf("\n media celor %d nr. reale=%1.2lf",n/2,2*mfloat/n);
printf("\n continuati?(d/n):");
r=getche();
}
}
Rezultatele executiei programului, de mai sus, sunt prezentate in continuare,
putandu-se urmari cum se declara si se utilizeaza o uniune de date care, pe langa
campurile componente, contine si functii membre, cu care se prelucreaza datele
uniunii ce folosesc aceeasi zona de memorie in comun
nr par de numere intregi (1<=n<=20):4
introduceti cele 4 de nr. intregi in uniunea u:
x(0)=25
x(1)=45
x(2)=65
x(3)=35
introduceti cele 2 de numere reale din uniunea u:
y(0)=67.77
y(1)=99.12
nr intregi si calculul medie in uniune:
25 45 65 35
media arit. a celor 4 nr. intregi=42.50
nr intregi si media calculate in main:
25 45 65 35
media celor 4 nr. intregi=42.50
nr reale si calculul medie in uniune:
67.77 99.12
media arit. a celor 2 nr.reale=83.44
nr reale si media calculate in main:
67.77 99.12
media celor 2 nr. reale=83.44

continuati?(d/n):d
nr par de numere intregi (1<=n<=20):6
introduceti cele 6 de nr. intregi in uniunea u:
x(0)=10
x(1)=20
x(2)=30
x(3)=40
x(4)=50
x(5)=60
introduceti cele 3 de numere reale din uniunea u:
y(0)=23.45
y(1)=67.97
y(2)=-34.56
nr intregi si calculul medie in uniune:
10 20 30 40 50 60
media arit. a celor 6 nr. intregi=35.00
nr intregi si media calculate in main:
10 20 30 40 50 60
media celor 6 nr. intregi=35.00
nr reale si calculul medie in uniune:
23.45 67.97 -34.56
media arit. a celor 3 nr.reale=18.95
nr reale si media calculate in main:
23.45 67.97 -34.56
media celor 3 nr. reale=18.95
continuati?(d/n):n

Observatie:
Limbajul C++ accepta uniunile anonime, fara specificarea numelui uniunii, ca in
programul de mai jos:
Problema 24
Se considera o uniune anonima, fara nume, de trei date: intreaga, reala si caracter. Sa se
afiseze pe rand toate datele intregi, reale si caracter tastate.
#include<iostream.h>void main(void)
{
union
{
int x;
double y;
char z;
};
char r='d';
while(r=='d')
{
cout<<"\n dati un nr intreg, x=";
cin>>x;
cout<<"\n ati tastat nr intreg "<<x;
cout<<"\n dati un nr real, y=";
cin>>y;
cout<<"\n ati tastat nr real "<<y;
cout<<"\n dati un caracter, z=";
cin>>z;
cout<<"\n ati tastat caracterul "<<z;
cout<<"\n continuati?(d/n):";
cin>>r;
}
}
Problema 25
Se considera trei siruri: primul de numere intregi, al doilea de caractere si al treilea de
numere reale, care utilizeaza in comun aceeasi zona de memorie. Cu ajutorul unei uniuni a celor
trei tipuri de data, sa se citeasca, pe rand, elementele sirurilor, cu ajutorul unei functii membru
(citeste_sir), sa se ordoneze crescator fiecare sir cu o alta functie membru (ordoneaza_sir) si apoi
sa se afiseze sirurile astfel ordonate cu alta functie membru (afisaza_sir)
#include<iostream.h>
#define nmax1 20
#define nmax2 15
#define nmax3 10
int i;
union tip_siruri
{
int sint[nmax1];
char scar[nmax2];
double sreal[nmax3];
void citeste_sir(int n,char tsir) //functia membru de citire
{
for(i=0;i<n;i++)
{
if(tsir=='i')
{
cout<<"\n sint("<<i<<")=";
cin>>sint[i];
}
if(tsir=='c')
{
cout<<"\n scar("<<i<<")=";
cin>>scar[i];
}
if(tsir=='r')
{
cout<<"\n sreal("<<i<<")=";
cin>>sreal[i];
}
}
}
void afisaza_sir(int n,char tsir) //functia membru de afisare
{
for(i=0;i<n;i++)
{
if(tsir=='i') cout<<sint[i]<<' ';
if(tsir=='c') cout<<scar[i]<<' ';
if(tsir=='r') cout<<sreal[i]<<' ';
}
}
void ordonare_sir(int n,char tsir) //functia membru de ordonare
{
int ok,i,auxi; char auxc;double auxr;
ok=1;
while(ok)
{
ok=0;
for(i=0;i<n-1;i++)
{
if(tsir=='i')
{
if(sint[i]>sint[i+1])
{
auxi=sint[i];sint[i]=sint[i+1];
sint[i+1]=auxi;ok=1;
}
}
if(tsir=='c')
{
if(scar[i]>scar[i+1])
{
auxc=scar[i];scar[i]=scar[i+1];
scar[i+1]=auxc;ok=1;
}
}
if(tsir=='r')
{
if(sreal[i]>sreal[i+1])
{
auxr=sreal[i];sreal[i]=sreal[i+1];
sreal[i+1]=auxr;ok=1;
}
}
}
}
}
};
void main(void)
{
tip_siruri u;
int n;char r='d';
while(r=='d')
{
do
{
cout<<"\n dati nr de intregi de citit(n<"<<nmax1<<")=";
cin>>n;
}
while((n<1)||(n>nmax1));
cout<<"\n se citesc "<<n<<" intregi:\n";
cout<<"===============================";
u.citeste_sir(n,'i');
u.ordonare_sir(n,'i');
cout<<"\n=============================";
cout<<"\n sirul de intregi ordonat:";
u.afisaza_sir(n,'i');
cout<<"\n=============================";
do
{
cout<<"\n dati nr de caractere de citit(n<"<<nmax2<<")=";
cin>>n;
}
while((n<1)||(n>nmax2));
cout<<"\n se citesc "<<n<<" caractere:";
cout<<"\n=============================";
u.citeste_sir(n,'c');
u.ordonare_sir(n,'c');
cout<<"\n=============================";
cout<<"\n sirul de caractere ordonat:";
u.afisaza_sir(n,'c');
cout<<"\n=============================";
do
{
cout<<"\n dati nr de reali de citit(n<"<<nmax3<<")=";
cin>>n;
}
while((n<1)||(n>nmax3));
cout<<"\n se citesc "<<n<<" reali:\n";
cout<<"\n=============================";
u.citeste_sir(n,'r');
u.ordonare_sir(n,'r');
cout<<"\n=============================";
cout<<"\n sirul de reali ordonat:";
u.afisaza_sir(n,'r');
cout<<"\n=============================";
cout<<"\n continuati?(d/n):";
cin>>r;
}
}.
Rezultatele executiei programului, sunt prezentate in continuare, putandu-se
urmari cum se declara si se utilizeaza o uniune de siruri de date care, pe langa aceste
siruri, contine si functii membre (citeste_sir(), afisaza_sir() si ordonare_sir()), cu care
se prelucreaza datele uniunii, de tip siruri de date, ce folosesc aceeasi zona de
memorie in comun
dati nr de intregi de citit(n<20)=4
se citesc 4 intregi:
===============================
sint(0)=45
sint(1)=-34
sint(2)=78
sint(3)=-90
=============================
sirul de intregi ordonat:-90 -34 45 78
=============================
dati nr de caractere de citit(n<15)=5
se citesc 5 caractere:
=============================
scar(0)=i
scar(1)=y
scar(2)=3
scar(3)=a
scar(4)=f
=============================
sirul de caractere ordonat:3 a f i y
=============================
dati nr de reali de citit(n<10)=4
se citesc 4 reali:
=============================
sreal(0)=32.45
sreal(1)=89.45
sreal(2)=-67.99
sreal(3)=-23.33
=============================
sirul de reali ordonat:-67.99 -23.33 32.45 89.45
=============================
continuati?(d/n):d
dati nr de intregi de citit(n<20)=3
se citesc 3 intregi:
===============================
sint(0)=45
sint(1)=-34
sint(2)=18
=============================
sirul de intregi ordonat:-34 18 45
=============================
dati nr de caractere de citit(n<15)=4
se citesc 4 caractere:
=============================
scar(0)=k
scar(1)=a
scar(2)=w
scar(3)=h
=============================
sirul de caractere ordonat:a h k w
=============================
dati nr de reali de citit(n<10)=3
se citesc 3 reali:
=============================
sreal(0)=-34.78
sreal(1)=67.33
sreal(2)=-97.5
=============================
sirul de reali ordonat:-97.5 -34.78 67.33
=============================
continuati?(d/n):n

III. 7. Declararea si utilizarea functiilor de clasa speciale


III. 7. 1. Functiile constructor
In mod uzual, cand intr-un program se creeaza o instanta obiect a unei clase, atunci se vor
atribui valori initiale datelor membru ale acelui obiect. Pentru simplificarea procesului de
initializare a membrilor obiectelor declarate, limbajul C++ accepta declararea si utilizarea unei
functii speciale, numita functie constructor, care se executa automat la creearea unei instante
a clasei din care face parte functia.
Structura generala a unei clase cu functie constructor este data mai jos:
class nume_clasa
{
public:
// declararea si/sau descrierea functiei constructor
nume_clasa (parametri_formali)
{
//descrierea algoritmului functiei constructor
}
// declararea datelor publice
// declararea si sau descrierea functiilor publice
private:
// declararea datelor private
// declararea si/sau descrierea functiilor private
protected:
// declararea datelor protejate
// declararea si/sau descrierea functiilor protejate
}
Observatii:
- numele functiei constructor trebuie sa fie acelasi cu numele clasei la care este atasata
- descrierea efectiva a functiei constructor se poate face in corpul clasei respective sau,
ulterior, in afara clasei, declararea prototipului sau fiind obligatorie in interiorul clasei, ca mai
jos:
nume_clasa:: nume_clasa (parametri_formali)
{
// descrierea algoritmului functiei constructor
}
- transmiterea parametrilor efectivi, la apelarea unei functii constructor, se face in partea
executabila a programului astfel:
nume_clasa nume_functie(parametri_efectivi);
- parametrii efectivi transmisi pot fi utilizati pentru initializarea unui obiect creat in
partea executabila a programului sau pentru initializarea membrilor clasei respective.
- functia constructor se executa automat cand, in program, se creeaza o instanta a clasei
respective
- prin definitie, functia constructor nu returneaza nici o valoare, deci numele sau nu
poate fi precedat de nici un tip
- la compilare se va apela functia constructor numai atunci cand in program se declara
un obiect al clasei corespunzatoare. Momentul real, in care compilatorul apeleaza codul functiei
constructor, este dictat de tipul clasei si de locul din cadrul programului. Cand in program se
creaza mai multe obiecte in aceeasi instructiune, apelarea si executarea functiilor constructor se
va face in ordinea declararii acestora, adica de la stanga la dreapta. De asemenea, functia
constructor a unei instante locale se va executa cand, in partea executabila a programului, se va
intalni instructiunea de declarare a unui obiect al clasei respective.
- cand exista ambiguitati intre datele clasei si parametrii functiei constructor, cum ar fi
utilizarea acelorasi identificatori, se procedeaza la calificarea datelor clasei cu ajutorul
operatorului de rezolutie ::, ca mai jos:
nume_clasa::nume_data;
- functiile constructor admit si valori implicite ale parametrilor formali, care,
in lipsa transmiterii de parametri efectivi de catre o instanta a clasei respective, sunt
utilizate pentru initializarea datelor clasei.
Problema 26
Se considera fisele de materiale dintr-un depozit cu materiale de constructii cu
informatiile: cod material, un intreg cuprins intre 10000 si 99999; denumire material,
un sir de 20 caractere maxim; unitatea de masura in multimea (bc, kg, ml, mp, mc, l,
hl); pretul, un numar real si pozitiv; cantitatea din stoc, un numar real si pozitiv si
valoarea, calculata ca produs intre cantitate si pret. Prin intermediul unei clase, in care
s-a declarat o functie constructor, sa se initializeze datele referitoare la fiecare
material din magazie: codul, denumirea si unitatea de masura de tip public, iar pretul,
cantitatea si valoarea de tip privat. Prin intermediul unei functii membru te tip public
sa se afiseeze datele publice: codul, denumirea si unitatea de masura iar prin
intermediul unei functii private sa se afiseze si celelalte date private.
// definirea clasei material
#include<iostream.h>
#include<string.h>
class material
{
public:
material(int codmat, char *denum, char *umas, double pret, double cant, double val)
{
material::cod_material=codmat;
strcpy(material ::denumire, denum);
strcpy(material ::unitate_masura, umas);
material::pret_material=pret;
material::cantitate_stoc=cant;
material::valoare_stoc=cant*pret;
};
int cod_material;
char denumire[20];
char unitate_masura[2];
void afiseaza_fisa(void)
{
afiseaza_date_publice();
afiseaza_date_private();
};
void afiseaza_date_publice()
{
cout<<"\n Informatii de nomenclator ale materialului:"<<endl;
cout<<"\n ===================================="<<endl;
cout <<"\n codul materialui: "<<cod_material;
cout <<"\n denumirea materialului: "<<denumire;
cout <<"\n unitatea de masura: "<<unitate_masura;
cout<<"\n ===================================="<<endl;
};
private:
double pret_material;
double cantitate_stoc;
double valoare_stoc;
void afiseaza_date_private()
{
cout<<"\n Informatii specifice materialului:"<<endl;
cout<<"\n ===================================="<<endl;
cout<<"\n pretul materialului:"<<material::pret_material;
cout<<"\n cantitatea din stoc:"<<material::cantitate_stoc;
cout<<"\n valoarea stocului:"<<material::valoare_stoc;
cout<<"\n ===================================="<<endl;
};
};
void main()
{
int wcod; char wdenum[20],wumas[2];
double wpret, wcant, wval=0;
char r='d';
while(r=='d')
{
cout<<"\n codul materialului:";
cin>>wcod;
cout<<"\n denumirea materialului:";
cin>>wdenum;
cout<<"\n unitatea de masura:";
cin>>wumas;
cout<<"\n pretul materialului:";
cin>>wpret;
cout<<"\n cantitatea din stoc:";
cin>>wcant;
material fisa(wcod,wdenum,wumas,wpret,wcant,wval);
fisa.afiseaza_fisa();
cout<<"\n continuati?(d/n):";
cin>>r;
}
}
Rezultatele executiei acestui program, mai jos afisate, arata cum se transmit parametri
efectivi functiei constructor material, cum se initializeaza datele publice si private si cum se
apeleaza, pentru afisarea datelor initializate, functiile publice si private definite in clasa material.

codul materialului:20000
denumirea materialului:fier*beton*fi16
unitatea de masura:kg
pretul materialului:22.55
cantitatea din stoc:200

Informatii de nomenclator de materiale:


=========================================
codul materialui: 20000
denumirea materialului: fier*beton*fi16
unitatea de masura: kg
====================================
Informatii specifice materialului:
====================================
pretul materialului:22.55
cantitatea din stoc:200
valoarea stocului:4510
====================================
continuati?(d/n):d
codul materialului:30000
denumirea materialului:ciment*alb
unitatea de masura:bc
pretul materialului:16
cantitatea din stoc:150

Informatii de nomenclator de materiale:


====================================
codul materialui: 30000
denumirea materialului: ciment*alb
unitatea de masura: bc
====================================
Informatii specifice materialului:
====================================
pretul materialului:16
cantitatea din stoc:150
valoarea stocului:2400
====================================
continuati?(d/n):n
Deoarece, identificarorii datelor, declarate in interiorul clasei, sunt diferiti de
identificatorii parametrilor formali ai functiei constructor, nu exista ambiguitati in folosirea
acestora, fara calificarea lor cu ajutorul operatorului de rezolutie ::. In
functia afiseaza_date_publice() nu s-a folosit calificarea datelor membre
(cod_material, denumire, unitate_masura), in schimb, in functia afiseaza_date_private() s-a
folosit calificarea cu ajutorul operatorului de rezolutie ::, desi nu era necesara, neexistand
ambiguitati de calificare a
datelor (material::pret_material, material::cantitate_stoc, material::valoare_stoc).

Problema 27
Se considera o suma s0=100000 depusa initial la o banca, cu dobanda 10% pe
o perioada de 10 ani. Sa se determine, dupa fiecare an suma cumulata si dobanda
cumulata, utilizandu-se o clasa cu functie constructor corespunzatoare avand
parametri impliciti dati (s0=100000, p=10% si n=10 ani), care sa permita, totodata,
obtinerea rezultatelor pentru orice suma s0 (100000<=s0<=1000000), orice dobanda p
(10<<p<=100) si pentru orice perioada n (5<=n<=20).
#include<iostream.h>
#include<iomanip.h>
// definirea clasei dobanda
class dobanda
{
public:
// prototipul functiei constructor dobanda()
dobanda(double s0=100000, double p=10, int n=10);
// declararea datelor membru publice
double s0;
double p;
int n;
// prototipul functiei afiseaza_linie,ce lanseaza
// functiile:calcul_dobanda() si afisare_rezultat()
void afiseaza_linie(int m);
private:
// declararea datelor membru private
double suma_cumulata;
double dobanda_cumulata;
// prototipul functiei de calcul a sumei si dobanzii cumulate
void calcul_dobanda(int k);
// prototipul functiei afiseaza_rezultat()
// ce afiseaza rezultatele dupa un anumit an
void afiseaza_rezultat(int k);
};
// descrierea functiei constructor in afara clasei
dobanda::dobanda(double s0, double p, int n)
{
int i;
dobanda::s0=s0;
dobanda::p=p;
dobanda::n=n;
cout<<"\n suma depusa="<<s0<<" dobanda=";
cout<<p<<"%"<<" perioada="<<n<<" ani";
cout<<"\n =====================================";
cout<<"\n anul suma cumulata dobanda cumulata";
cout<<"\n =====================================";
for(i=1;i<=n;i++) afiseaza_linie(i);
cout<<"\n =====================================";
}
// descrierea functiei calcul_dobanda in afara clasei
void dobanda::calcul_dobanda(int k)
{
int j;
suma_cumulata=dobanda::s0;
for (j=1;j<=k;j++)
{
suma_cumulata=suma_cumulata+suma_cumulata*dobanda::p/100;
dobanda_cumulata=suma_cumulata-dobanda::s0;
}
};
// descrierea functiei afiseaza_rezultat in afara clasei
void dobanda::afiseaza_rezultat(int k)
{
cout<<"\n "<<setw(4)<<k<<" ";
cout<<" "<<setw(13)<<setiosflags(ios::fixed);
cout<<setprecision(2)<<dobanda::suma_cumulata;
cout<<" "<<setw(13)<<setiosflags(ios::fixed);
cout<<setprecision(2)<<dobanda::dobanda_cumulata;
};
// descrierea functiei afiseaza_linie in afara clasei
void dobanda::afiseaza_linie(int m)
{
calcul_dobanda(m);
afiseaza_rezultat(m);
}
// descrierea functiei principale main
void main()
{
int wn; double wp, ws0;
char r='d',tip_depozit;
while(r=='d')
{
cout<<"\n tip depozit implicit(s0=100000,p=10%,n=10 ani)?(d/n):";
cin>>tip_depozit;
if (tip_depozit=='d')
{
cout<<"\n tip depozit implicit(s0=100000,p=10%,n=10 ani)";
//apelarea functiei constructor cu parametri impliciti
dobanda implicit;
}
else
{
// citirea parametrilor efectivi expliciti
cout<<"\n tip depozit explicit(s0<>100000,p<>10%,n<>10 ani)";
do
{
cout<<"\n suma initiala depusa (100000<=s0<=1000000):";
cin>>ws0;
}
while((ws0<100000)||(ws0>1000000));
do
{
cout<<"\n dobanda anuala % (10<=p<=100):";
cin>>wp;
}
while((wp<10)||(wp>100));
do
{
cout<<"\n perioada depozitului (5<=n<=20):";
cin>>wn;
}
while((wn<5)||(wn>20));
//apelarea functiei constructor cu parametri expliciti
dobanda explicita(ws0,wp,wn);
}
cout<<"\n continuati?(d/n):";
cin>>r;
}
}
In urma executarii acestui program, s-au obtinut urmatoarele rezultate, care scot in
evidenta: declararea prototipurilor tuturor functiilor, in corpul clasei, inclusiv a functiei
constructor cu parametri formali impliciti, descriera tuturor functiilor in afara clasei, apelarea
functiei constructor cu si fara parametri efectivi expliciti.

tip depozit implicit(s0=100000,p=10%,n=10 ani)?(d/n):d


tip depozit implicit(s0=100000,p=10%,n=10 ani)
suma depusa=100000 dobanda=10% perioada=10 ani
=====================================
anul suma cumulata dobanda cumulata
=====================================
1 110000.00 10000.00
2 121000.00 21000.00
3 133100.00 33100.00
4 146410.00 46410.00
5 161051.00 61051.00
6 177156.10 77156.10
7 194871.71 94871.71
8 214358.88 114358.88
9 235794.77 135794.77
10 259374.25 159374.25
=====================================
continuati?(d/n):d
tip depozit implicit(s0=100000,p=10%,n=10 ani)?(d/n):n
tip depozit explicit(s0<>100000,p<>10%,n<>10 ani)
suma initiala depusa (100000<=s0<=1000000):1000000
dobanda anuala % (10<=p<=100):100
perioada depozitului (5<=n<=20):8
suma depusa=1000000.00 dobanda=100.00% perioada=8 ani
=====================================
anul suma cumulata dobanda cumulata
=====================================
1 2000000.00 1000000.00
2 4000000.00 3000000.00
3 8000000.00 7000000.00
4 16000000.00 15000000.00
5 32000000.00 31000000.00
6 64000000.00 63000000.00
7 128000000.00 127000000.00
8 256000000.00 255000000.00
=====================================
continuati?(d/n):d
tip depozit implicit(s0=100000,p=10%,n=10 ani)?(d/n):d
tip depozit implicit(s0=100000,p=10%,n=10 ani)
suma depusa=100000.00 dobanda=10.00% perioada=10 ani
=====================================
anul suma cumulata dobanda cumulata
=====================================
1 110000.00 10000.00
2 121000.00 21000.00
3 133100.00 33100.00
4 146410.00 46410.00
5 161051.00 61051.00
6 177156.10 77156.10
7 194871.71 94871.71
8 214358.88 114358.88
9 235794.77 135794.77
10 259374.25 159374.25
=====================================
continuati?(d/n):n
III. 7. 2. Alocarea memoriei prin functiile constructor. Controlul alocarii
memoriei.
Dupa cum s-a precizat, functiile constructor permit intializare datelor membre,
inclusiv a datelor de tip tablouri, matrici. In cazul initializarii tablourilor, functiile
constructor pot aloca memoria necesara tablourilor, putand controla modul in care s-a
realizat alocarea de memorie ceruta. Alocarea memoriei necesare pentru tablouri de
caractere se poate face simultan cu testarea modului in care s-a realizat efectiv
alocarea, printr-o constructie de forma:
if (nume_functie_constructor::nume_tablou = new char[numar_octeti] == 0)
{
cerr<<\n eroare de alocare a memoriei pentru tabloul nume_tablou;
exit(0);
}
Constructia de mai sus, poate fi folosita pentru alocarea si verificarea alocarii
pentru mai multe variabile de tip tablou, de tip caracter, in acelasi timp, ca mai jos:
.
nume_functie_constructor::nume_tablou1 = new char[numar_octeti1];
nume_functie_constructor::nume_tablou12= new char[numar_octeti2];
.
nume_functie_constructor::nume_tabloun = new char[numar_octetin];
if ((nume_functie_constructor::nume_tablou1 &&
(nume_functie_constructor::nume_tablou2 &&
.
(nume_functie_constructor::nume_tabloun ) == 0)
{
cerr<<\n eroare de alocare a memoriei pentru toate tablourile specificate;
exit(0);
}
Pentru alocarea memoriei, pentru oricare tipuri de tablouri, prin intermediul
pointerilor la tablouri, se poate folosi functia de alocare dinamica malloc.
nume_functie_constructor::pointer_tablou1 =
(tip_componenta1*)malloc(n*sizeof(tip_componenta1));
nume_functie_constructor::pointer_tablou2 =
(tip_componenta2*)malloc(n*sizeof(tip_componenta2));

nume_functie_constructor::pointer_tabloun =
(tip_componentan*)malloc(n*sizeof(tip_componentan));
iar verificarea alocarii necesarului de memorie se poate face asemanator ca la tablourile de siruri,
prezentata mai sus.
if((!nume_functie_constructor::pointer_tablou1) ||
(!nume_functie_constructor::pointer_tablou2) ||

(!nume_functie_constructor::pointer_tabloun) == 0)
{
cout<<"\n alocarea dinamica a tablourilor, nereusita in functia constructor";
exit(1);
}

Problema 28
Se da o matrice dreptunghiulara de n linii si m coloane, unde m reprezinta numarul de
tipuri de produse fabricate intr-o uzina, iar n numarul de tipuri de materiale folosite la fabricarea
acestora. Un element al matricei a[i,j] reprezinta cantitatea, in aceeasi unitate de masura, din
materialul i consumat pentru produsul j. Un vector de m componente contine numarul de produse
fabricate din fiecare tip. Se cere sa se determine un vector de n componente care sa contina
cantitatile totale, din fiecare tip de material, consumate pentru realizarea fabricatiei celor m tipuri
de produse. Cunoscandu-se, apoi, intr-un vector, costurile unitare de materiale pe fiecare tip de
material, sa se calculuze valoarea fiecarui tip de material consumat si valoarea totala a tuturor
materialelor consumate. Pentru rezolvarea acestei aplicatii se va folosi o clasa adecvat definita
care contine o functie constructor ce va initializa datele membre de tip pointeri la tablouri si va
calcula si afisa cele cerute in problema. Se vor folosi parametri formali si efectivi de tip pointer,
pentru transmiterea lor intre functia principala si functia constructor, utilizanduse, din acest
motiv, alocarea dinamica de memorie si verificarea alocarii memoriei dinamice necesara
tablourilor.

#include<iostream.h>
#include<iomanip.h>
#include<malloc.h>
#include<stdlib.h>
#define nmax 20
#define mmax 20
int i,j;
// definirea clasei consunuri
class consumuri
{
public:
consumuri::consumuri(int n, int m, double *pc, double *pp, double *pv);
// declararea datelor membru publice
int n;
int m;
double *pc; //pointer la matricea consumurilor specifice
double *pp; //pointer la vectorul produselor fabricate
double *pv; //pointer la vectorul costurilor unitare ale materialelor
private:
double *pmateriale; //pointer la vectorul materialelor consumate
double *pcosturi; //pointer la vectorul costurilor materialelor
double costotal;
//declararea prototipurilor functiilor membru private
// prototipul functiei de afisare a consumurilor
//specifice de materiale pe produse
void afiseaza_matrice_consumuri(int n, int m);
// prototipul functiei de calcul a consumurilor de materiale
void calcul_consumuri(int n, int m);
// prototipul functiei de calcul ale costurilor de materiale
void calcul_costuri_materiale(int n);
// prototipul functiei de afiseare vector produse
void afiseaza_vector_produse(int m);
// prototipul functiei de afiseare vector consumuri de materiale
void afiseaza_vector_consumuri(int n);
// prototipul functiei de afiseare vector consturi unitare pe materiale
void afiseaza_vector_costuri_unitare(int n);
// prototipul functiei de afiseare vector consturi totale pe materiale
void afiseaza_vector_costuri_materiale(int n);
};
// descrierea functiei constructor consumuri in afara clasei
consumuri::consumuri(int n, int m, double *pc, double *pp, double *pv)
{
cout<<"\n functia constructor consumuri";
// alocarea dinamica de memorie pentru tablourile aplicatiei
consumuri::pc=(double*)malloc(nmax*mmax);
consumuri::pp=(double*)malloc(mmax);
consumuri::pv=(double*)malloc(nmax);
consumuri::pmateriale=(double*)malloc(nmax);
consumuri::pcosturi=(double*)malloc(mmax);
//verificarea necesarului de memorie
if((!consumuri::pc) ||(!consumuri::pp) || (!consumuri::pc) ||
(!consumuri::pmateriale) || (!consumuri::pcosturi))
{
cout<<"\n alocarea dinamica a tablourilor, nereusita in functia constructor";
exit(1);
}
consumuri::n=n;
consumuri::m=m;
// initializarea matricei consumurilor specifice
for(i=0;i<n;i++)
for(j=0;j<m;j++) consumuri::pc[i*m+j]=pc[i*m+j];
// initializarea vectorului produselor fabricate
for(i=0;i<m;i++) consumuri::pp[i]=pp[i];
// initializarea vectorului costurilor unitare ale materialelor folosite
for(i=0;i<n;i++) consumuri::pv[i]=pv[i];
cout<<"\n matricea consumurilor de materiale pe produse";
cout<<"\n================================\n";
afiseaza_matrice_consumuri(n,m);
cout<<"\n=================================";
cout<<"\n vectorul produselor fabricate";
cout<<"\n ================================\n";
afiseaza_vector_produse(m);
cout<<"\n ================================\n";
cout<<"\n vectorul costurilor unitare pe materiale\n";
cout<<"\n =================================";
afiseaza_vector_costuri_unitare(n);
cout<<"\n =================================";
calcul_consumuri(n,m);
cout<<"\n vectorul materialelor consumate";
cout<<"\n ================================\n";
afiseaza_vector_consumuri(n);
cout<<"\n =================================";
calcul_costuri_materiale(n);
cout<<"\n vectorul costurilor totale pe materiale";
cout<<"\n =================================";
afiseaza_vector_costuri_materiale(n);
cout<<"\n =================================";
};
// descrierea functiei calcul_consumuri
// in afara clasei cu ajutorul pointerilor
void consumuri::calcul_consumuri(int n,int m)
{
for (i=0;i<n;i++)
{
consumuri::pmateriale[i]=0;
for (j=0;j<m;j++)
{
consumuri::pmateriale[i]=consumuri::pmateriale[i]+
consumuri::pc[i*m+j] * consumuri::pp[j];
}
}
}
// descrierea functiei calcul_costuri_materiale
//in afara clasei cu ajutorul pointerilor
void consumuri::calcul_costuri_materiale(int n)
{
consumuri::costotal=0;
for (i=0;i<n;i++)
{
consumuri::pcosturi[i]=consumuri::pmateriale[i] * consumuri::pv[i];
consumuri::costotal= consumuri::costotal + consumuri::pcosturi[i];
}
}
// descrierea functiei afiseaza_matrice_consumuri
//in afara clasei cu ajutorul pointerilor
void consumuri::afiseaza_matrice_consumuri(int n, int m)
{
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
cout<<" "<<setw(7)<<setiosflags(ios::fixed);
cout<<setprecision(3)<<consumuri::pc[i*m+j];
}
cout<<"\n";
}
}
// descrierea functiei afiseaza_vector_produse
// in afara clasei cu ajutorul pointerilor
void consumuri::afiseaza_vector_produse(int m)
{
cout<<"\n";
for(i=0;i<m;i++)
{
cout<<" "<<setw(7)<<setiosflags(ios::fixed);
cout<<setprecision(2)<<consumuri::pp[i];
}
}
// descrierea functiei afiseaza_vector_consumuri
// in afara clasei cu ajutorul pointerilor
void consumuri::afiseaza_vector_consumuri(int n)
{
cout<<"\n";
for(i=0;i<n;i++)
{
cout<<" "<<setw(7)<<setiosflags(ios::fixed);
cout<<setprecision(2)<<consumuri::pmateriale[i];
}
}
// descrierea functiei afiseaza_vector_consturi_unitare
// in afara clasei cu ajutorul pointerilor
void consumuri::afiseaza_vector_costuri_unitare(int n)
{
cout<<"\n";
for(i=0;i<n;i++)
{
cout<<" "<<setw(7)<<setiosflags(ios::fixed);
cout<<setprecision(2)<<consumuri::pv[i];
}
}
// descrierea functiei afiseaza_vector_costuri_materiale
// in afara clasei cu ajutorul pointerilor
void consumuri::afiseaza_vector_costuri_materiale(int n)
{
cout<<"\n";
for(i=0;i<n;i++)
{
cout<<" "<<setw(7)<<setiosflags(ios::fixed);
cout<<setprecision(2)<<consumuri::pcosturi[i];
}
cout<<"\n valoare totala costuri materiale="<<consumuri::costotal;
}
// descrierea functiei principale main()
void main()
{
int n,m;
// declararea pointerilor la tablourile aplivatiei
double *ptrc,*ptrp,*ptrv;
char r='d';
// alocarea memoriei pentru tablourile date in aplicatie
ptrc=(double*)malloc(nmax*mmax);
ptrp=(double*)malloc(mmax);
ptrv=(double*)malloc(nmax);
// verificarea alocarii memoriei pentru tablurile date in aplicatie
if((!ptrc)||(!ptrp)||(!ptrv))
{
cout<<"\n alocarea tablourilor nereusita in functia principala";
exit(1);
}
while(r=='d')
{
do
{
cout<<"\n numarul de produse fabricate,m(1<=m<=20):";
cin>>m;
}
while((m<1)||(m>20));
do
{
cout<<"\n numarul de materiale folosite,n(1<=n<=20):";
cin>>n;
}
while((n<1)||(n>20));
//citirea matricii consumurilor specifice de materiale pe produs
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
cout<<"\n materialul "<<i<<" din produsul "<<j<<" =";
cin>>ptrc[i*m+j];
}
cout<<"\n matricea consumurilor:\n";
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
cout<<ptrc[i*m+j]<<" ";
}
cout<<"\n";
}
for(i=0;i<m;i++)
{
cout<<"\n numarul de bucati fabricate din produsul "<<i<<" =";
cin>>ptrp[i];
}
for(i=0;i<n;i++)
{
cout<<"\n costul unitar al materialului "<<i<<" =";
cin>>ptrv[i];
}
//apelarea functiei constructor, consumuri, cu parametri expliciti
consumuri functie_consumuri(n,m,ptrc,ptrp,ptrv);
cout<<"\n continuati?(d/n):";
cin>>r;
}
}
Rezultatele executiei programului sunt afisate in continuare, putandu-se usor observa,
modul in care, unei functii constructor, i se transmit parametri efectivi de tip pointeri la tablouri,
alocarea dinamica de memorie pentru tablourile pointate ale functiei principale main, cat si
pentru datele membre, de tip pointeri la tablouri, ale clasei corespunzatoare si verificarea alocarii
memoriei pentru tablourile aplicatiei.

numarul de produse fabricate,m(1<=m<=20):3


numarul de materiale folosite,n(1<=n<=20):2
materialul 0 din produsul 0 =1
materialul 0 din produsul 1 =2
materialul 0 din produsul 2 =3
materialul 1 din produsul 0 =4
materialul 1 din produsul 1 =5
materialul 1 din produsul 2 =6
matricea consumurilor:
123
456
numarul de bucati fabricate din produsul 0 =1
numarul de bucati fabricate din produsul 1 =2
numarul de bucati fabricate din produsul 2 =3
costul unitar al materialului 0 =1
costul unitar al materialului 1 =2
functia constructor consumuri
matricea consumurilor de materiale pe produse
=============================================
1.000 2.000 3.000
4.000 5.000 6.000
==============================================
vectorul produselor fabricate
=============================================
1.00 2.00 3.00
=============================================
vectorul costurilor unitare pe material
=============================================
1.00 2.00
==============================================
vectorul materialelor consumate
=============================================
14.00 32.00
==============================================
vectorul costurilor totale pe materiale
=============================================
14.00 64.00
valoare totala costuri materiale=78.00
==============================================
continuati?(d/n):d
numarul de produse fabricate,m(1<=m<=20):2
numarul de materiale folosite,n(1<=n<=20):3
materialul 0 din produsul 0 =6
materialul 0 din produsul 1 =5
materialul 1 din produsul 0 =4
materialul 1 din produsul 1 =3
materialul 2 din produsul 0 =2
materialul 2 din produsul 1 =1
matricea consumurilor:
6.00 5.00
4.00 3.00
2.00 1.00
numarul de bucati fabricate din produsul 0 =1
numarul de bucati fabricate din produsul 1 =2
costul unitar al materialului 0 =1
costul unitar al materialului 1 =2
costul unitar al materialului 2 =3
functia constructor consumuri
matricea consumurilor de materiale pe produse
=============================================
6.000 5.000
4.000 3.000
2.000 1.000
==============================================
vectorul produselor fabricate
=============================================
1.00 2.00
=============================================
vectorul costurilor unitare pe materiale
=============================================
1.00 2.00 3.00
==============================================
vectorul materialelor consumate
=============================================
16.00 10.00 4.00
==============================================
vectorul costurilor totale pe materiale
=============================================
16.00 20.00 12.00
valoare totala costuri materiale=48.00
==============================================
continuati?(d/n):n
III. 7. 3. Supraincarcarea functiilor constructor si a functiilor membre
Dupa cum s-a invatat, functia constructor este o metoda speciala a claselor care se
executa automat cand se creeaza diverse instante ale unui obiect. Supraincarcarea functiilor
presupune declararea si definirea unor functii cu acelasi nume, astfel incat, in functie de
parametrii transmisi, la compilare, sa se poata decida care dintre functiile cu acelasi nume sa fie
adresata. Ca orice functie in C++ si functiile constructor pot fi supraincarcate si adresate. Daca o
functie constructor este supraincarcata, atunci, la creearea unei instante a unui obiect, se va
executa totdeauna prima functie constructor, cea de-a doua executandu-se cand prima nu poate fi
executata din diferite motive, ca de exemplu, transmiterea eronata a parametrilor.
Problema 29
Se considera un vector care contine numarul variabil de perechi de pantaloni
(p[20]), care se pot produce intr-o fabrica de confectii, costurile fixe necesare
producerii acestor produse (cf), costul de productie variabil pe unitatea de produs (cp)
si pretul de vanzare pe piata a acestui produs (pv). Se cere, utilizandu-se o functie
constructor intr-o clasa adecvat definita, vectorul costurilor totale (ct), vectorul
veniturilor obtinute prin vanzarea produselor (vt), vectorul profiturilor realizate si
determinarea punctului critic care desparte zona pierderilor de zona de zona profitului.
Se va utiliza supraincarcarea functiei constructor cu o a doua functie care sa afiseze
un mesaj de eroare in cazul in care, functiei constructor principale, nu i se transmit toti
parametrii necesari rezolvarii aplicatiei. De asemenea, se va utiliza tehnica pointerilor
pentru vectorii utilizati, alocarea dinamica a memoriei necesare si verificarea alocarii
corecte a volumului de memorie necesar.
#include<iostream.h>
#include<iomanip.h>
#include<malloc.h>
#include<stdlib.h>
#define nmax 20 //nr maxim de variante de productie
int i,j;
// definirea clasei cost_venit
class cost_venit
{
public:
// declararea primei functii constructor, de baza
cost_venit (int n, int *p, double cf, double cp, double pv);
// supraincarcarea functiei constructor prin declararea
// celei de-a doua functie constructor
cost_venit(void);
// declararea datelor membru publice
int n; // numarul de componente ale vectorului produse
int *p; // pointer la vectorul cu cantitatile de produse de fabricat
double cf; // cheltuielile fixe de fabricatie a produselor
double cp; // cheltuielile variabile de fabricatie pe produs
double pv; // pretul unitar de vanzare a produsului private:
private:
// pointer la vectorul costurilor totale
// pe cantitati variabile de productie
double *ct;
//pointer la vectorul veniturilor pe cantitati variabile de produse
double *vt;
int produs_critic;
int maxim_produse; // numarul maxim de produse propuse ptr fabricare
double cost_critic; // costul total critic
double venit_critic;// venitul total critic
// declararea prototipurilor functiilor membru private
// prototipul functiei de ordonare vector produse
void ordonare_vector_produse(int n);
void determinare_max_produse(int n);
// prototipul functiei de afisare a cantitatilor
// produselor de fabricat
void afiseaza_vector_produse(int n);
// prototipul functiei de afisare a datelor: cf,cp,pv
// ale produselor de fabricat
void afiseaza_date_produse(void);
// prototipul functiei de calcul al costurilor totale
void calcul_costuri_produse(int n);
// prototipul functiei de calcul ale veniturilor din vanzari
void calcul_venituri_produse(int n);
// prototipul functiei de afiseare vector costuri
void afiseaza_vector_costuri(int n);
// prototipul functiei de afiseare vector venituri
void afiseaza_vector_venituri(int n);
// prototipul functiei de afiseare vector profit
void afiseaza_vector_profit(int n);
// prototipul functiei de calcul al punctului critic
void calcul_punct_critic(int n);
// prototipul functiei de afiseare a punctului critic
void afiseaza_punct_critic();
};
// descrierea primei functii constructor, de baza.
// cost_venit in afara clasei
cost_venit::cost_venit (int n, int *p, double cf, double cp, double pv)
{
cout<<"\n functia constructor cost_venit";
// alocarea dinamica de memorie pentru tablourile aplicatiei
cost_venit::p=(int*)malloc(nmax);
cost_venit::ct=(double*)malloc(nmax);
cost_venit::vt=(double*)malloc(nmax);
//verificarea necesarului de memorie
if((!cost_venit::p) ||(!cost_venit::ct) || (!cost_venit::vt))
{
cout<<"\n alocarea dinamica a tablourilor, nereusita in functia constructor";
exit(1);
}
// initializarea numarului cu variantele cantitatilor de fabricat
cost_venit::n=n;
// initializarea datei cu costurile fixe
cost_venit::cf=cf;
// initializarea datei cu costurile unitare pe produs
cost_venit::cp=cp;
// initializarea datei cu preturile unitare pe produs
cost_venit::pv=pv;
// initializarea vectorului cu cantitatile de fabricat
for(i=0;i<n;i++) cost_venit::p[i]=p[i];
cout<<"\n=================================";
// lansarea functiei de ordonare vector de produse
ordonare_vector_produse(n);
cout<<"\n vectorul produselor fabricate";
cout<<"\n ================================\n";
afiseaza_vector_produse(n);
cout<<"\n ================================\n";
cout<<"\n datele produselor cf,cp,pv ";
cout<<"\n ================================\n";
afiseaza_date_produse();
cout<<"\n ================================\n";
calcul_costuri_produse(n);
cout<<"\n vectorul costurilor totale pe produse";
cout<<"\n =======================================\n";
afiseaza_vector_costuri(n);
cout<<"\n =================================";
calcul_venituri_produse(n);
cout<<"\n vectorul veniturilor totale pe produse";
cout<<"\n =======================================\n";
afiseaza_vector_venituri(n);
cout<<"\n =================================";
cout<<"\n vectorul profitului total pe nr de produse";
cout<<"\n =======================================\n";
afiseaza_vector_profit(n);
cout<<"\n =================================";
determinare_max_produse(n);
calcul_punct_critic(n);
}
// supraincarcarea functiei constructor prin declararea
// celei de-a doua functie constructor in afara clasei
cost_venit::cost_venit(void)
{
cerr<<"\n lista parametrilor efectivi eronata";
//exit(1);
}
// descrierea functiei calcul_costuri_produse
//in afara clasei cu ajutorul pointerilor
void cost_venit::ordonare_vector_produse(int n)
{
int ok,paux;
ok=1;
while(ok)
{
ok=0;
for(i=0;i<n-1;i++)
{
if(p[i]>p[i+1])
{
paux=cost_venit::p[i]; cost_venit::p[i]=p[i+1];
cost_venit::p[i+1]=paux; ok=1;
}
}
}
}
void cost_venit::determinare_max_produse(int n)
{
cost_venit::maxim_produse=cost_venit::p[0];
for(i=0;i<n;i++)
if(cost_venit::p[i]>cost_venit::maxim_produse)
cost_venit::maxim_produse=cost_venit::p[i];
cout<<"\n nr maxim de produse de fabricat:";
cout<<cost_venit::maxim_produse;
}
void cost_venit::calcul_costuri_produse(int n)
{
for (i=0;i<n;i++)
cost_venit::ct[i]=cost_venit::cf+cost_venit::cp * cost_venit::p[i];
}
// descrierea functiei calcul_venituri_produse
//in afara clasei cu ajutorul pointerilor
void cost_venit::calcul_venituri_produse(int n)
{
for (i=0;i<n;i++)
cost_venit::vt[i]=cost_venit::pv*cost_venit::p[i];
}
// descrierea functiei afiseaza_vector_produse
// in afara clasei cu ajutorul pointerilor
void cost_venit::afiseaza_vector_produse(int n)
{
cout<<"\n";
for(i=0;i<n;i++)
{
cout<<" "<<setw(7)<<setiosflags(ios::fixed);
cout<<setprecision(2)<<cost_venit::p[i];
}
}
// descrierea functiei afiseaza_vector_costuri
//in afara clasei cu ajutorul pointerilor
void cost_venit::afiseaza_vector_costuri(int n)
{
for(i=0;i<n;i++)
{
cout<<" "<<setw(7)<<setiosflags(ios::fixed);
cout<<setprecision(3)<<cost_venit::ct[i];
}
}
// descrierea functiei afiseaza_vector_profit
//in afara clasei cu ajutorul pointerilor
void cost_venit::afiseaza_vector_profit(int n)
{
for(i=0;i<n;i++)
{
cout<<" "<<setw(7)<<setiosflags(ios::fixed);
cout<<setprecision(3)<<cost_venit::vt[i]-cost_venit::ct[i]<<" ";
}
}
// descrierea functiei afiseaza_vector_venituri
//in afara clasei cu ajutorul pointerilor
void cost_venit::afiseaza_vector_venituri(int n)
{
for(i=0;i<n;i++)
{
cout<<" "<<setw(7)<<setiosflags(ios::fixed);
cout<<setprecision(3)<<cost_venit::vt[i];
}
}
// descrierea functiei calcul_punct_critic
//in afara clasei cu ajutorul pointerilor
void cost_venit::calcul_punct_critic(int n)
{
int ok=0;double ct,vt;
for(i=0;i<cost_venit::maxim_produse;i++)
{
ct=cost_venit::cf+cost_venit::cp * i;
vt=cost_venit::pv * i;
if (vt<ct)
continue;
else
{
ok=1;
cost_venit::cost_critic=ct;
cost_venit::venit_critic=vt;
cost_venit::produs_critic=i;
break;
}
}
if(!ok)
{
cout<<"\n nu exista punct critic";
cout<<"\n la structura aleasa fabrica inregistreaza pierderi";
}
else
{
cout<<"\n afisarea punctului critic ";
cout<<"\n =================================\n";
afiseaza_punct_critic();
cout<<"\n =================================\n";
}
}
// descrierea functiei afiseaza_punct_critic
//in afara clasei cu ajutorul pointerilor
void cost_venit::afiseaza_punct_critic()
{
cout<<"\n punctul critic este atunci cand:\n";
cout<<"\n nr produse ="<<cost_venit::produs_critic;
cout<<"\n costurile totale ="<<cost_venit::cost_critic;
cout<<"\n veniturile totale ="<<cost_venit::venit_critic;
}
void cost_venit::afiseaza_date_produse()
{
cout<<"\n cheltuielile fixe ale fabricii:"<<cost_venit::cf;
cout<<"\n costul de productie pe produs :"<<cost_venit::cp;
cout<<"\n pretul de vanzare al produsului:"<<cost_venit::pv;
}
void main()
{
int n;
// declararea pointerului la vectorul produse al aplicatiei,
// a cheltuielilor fixe, variabile pe produs si a pretului de vanzare
int *ptrp; double cf,cp,pv;
char r='d';
// alocarea memoriei pentru tabloul produse
ptrp=(int*)malloc(nmax);
// verificarea alocarii memoriei pentru tablul de produse
if(!ptrp)
{
cout<<"\n alocarea vectorului de produse nereusita in functia principala";
exit(1);
}
while(r=='d')
{
do
{
cout<<"\n numarul de variante de fabricate,n(1<=n<=20):";
cin>>n;
}
while((n<1)||(n>20));
do
{
cout<<"\n cheltuielile fixe ale fabricii(10000<<cf<<1000000):";
cin>>cf;
}
while((cf<10000)||(cf>1000000));
do
{
cout<<"\n costurile unitare de productie (10<<cp<<100):";
cin>>cp;
}
while((cp<10)||(cp>100));
do
{
cout<<"\n preturile unitare de vanzare (100<<cp<<300):";
cin>>pv;
}
while((pv<100)||(pv>300));
//citirea vectorului cu cantitatile posibile de fabricat
for(i=0;i<n;i++)
{
cout<<"\n cantitatea de fabricat din varianta "<<i<<" =";
cin>>ptrp[i];
}
cout<<"\n variantele cantitatile de fabricat:\n";
for(i=0;i<n;i++) cout<<ptrp[i]<<" ";
//apelarea functiei constructor, consumuri, cu parametri expliciti
cost_venit f_cost_venit(n,ptrp,cf,cp,pv);
// apelarea fara parametri a functiei constructor supraincarcata
cost_venit f_cost_venit_vida;
cout<<"\n continuati?(d/n):";
cin>>r;
}
}
In urma executarii acestui program se obtin rezultatele afisate mai jos, care ilustreaza
modul in care se realizeaza supraincarcarea functiei constructor, alocarea dinamica de memorie
pentru vectorii folositi precum si verificarea alocarii memoriei necesare acestora. Apelarea
functiei constructor cu parametri efectivi valizi, determina initializarea datelor membre,
obtinerea si afisarea rezultatelor, iar apelarea eronata a functiei constructor, in cazul de fata fara
specificarea parametrilor efectivi, antreneaza executarea celei de-a doua functii constructor, care
va afisa mesajul de eroare corespunzator "lista parametrilor efectivi eronata".

numarul de variante de fabricate,n(1<=n<=20):4


cheltuielile fixe ale fabricii(10000<<cf<<1000000):20000
costurile unitare de productie (10<<cp<<100):40
preturile unitare de vanzare (100<<cp<<300):200
cantitatea de fabricat din varianta 0 =200
cantitatea de fabricat din varianta 1 =50
cantitatea de fabricat din varianta 2 =150
cantitatea de fabricat din varianta 3 =100
variantele cantitatile de fabricat:
200 50 150 100
functia constructor cost_venit
=================================
vectorul produselor fabricate
================================
50 100 150 200
================================
datele produselor cf,cp,pv
=======================================
cheltuielile fixe ale fabricii:20000.00
costul de productie pe produs :40.00
pretul de vanzare al produsului:200.00
=======================================
vectorul costurilor totale pe produse
=======================================
22000.000 24000.000 26000.000 28000.000
=======================================
vectorul veniturilor totale pe produse
=======================================
10000.000 20000.000 30000.000 40000.000
=======================================
vectorul profitului total pe nr de produse
==========================================
-12000.000 -4000.000 4000.000 12000.000
==========================================
nr maxim de produse de fabricat:200
afisarea punctului critic
=================================
punctul critic este atunci cand:
nr produse =125
costurile totale =25000.000
veniturile totale =25000.000
=================================
lista parametrilor efectivi eronata
continuati?(d/n):d
numarul de variante de fabricate,n(1<=n<=20):5
cheltuielile fixe ale fabricii(10000<<cf<<1000000):50000
costurile unitare de productie (10<<cp<<100):50
preturile unitare de vanzare (100<<cp<<300):100
cantitatea de fabricat din varianta 0 =150
cantitatea de fabricat din varianta 1 =200
cantitatea de fabricat din varianta 2 =50
cantitatea de fabricat din varianta 3 =100
cantitatea de fabricat din varianta 4 =250
variantele cantitatile de fabricat:
150 200 50 100 250
functia constructor cost_venit
=================================
vectorul produselor fabricate
=======================================
50 100 150 200 250
=======================================
datele produselor cf,cp,pv
================================
cheltuielile fixe ale fabricii:50000.00
costul de productie pe produs :50.00
pretul de vanzare al produsului:100.00
================================
vectorul costurilor totale pe produse
=================================================
52500.000 55000.000 57500.000 60000.000 62500.000
=================================================
vectorul veniturilor totale pe produse
=================================================
5000.000 10000.000 15000.000 20000.000 25000.000
=================================================
vectorul profitului total pe nr de produse
==========================================================
-47500.000 -45000.000 -42500.000 -40000.000 -37500.000
==========================================================
nr maxim de produse de fabricat:250
nu exista punct critic
la structura aleasa fabrica inregistreaza pierderi
lista parametrilor efectivi eronata
continuati?(d/n):n
In limbajul C++, exista posibilitatea supraincarcarii functiilor membre, prin folosirea
acelorasi identificatori pentru mai multe functii, care urmeaza sa fie apelate si executate, la un
anumit moment de timp. Inlaturarea ambiguitatilor legate de apelarea functiilor supraincarcate
se poate face prin diferentierea parametrilor efectivi cum ar fi: numar diferit de parametri, tipuri
diferite de parametri, etc..
Problema 30
Se considera o factura care contine mai multe materiale: cod material, un numar natural
cuprins intre 1000 si 9999, denumirea materialului, un sir alfanumeric de carcatere, unitatea de
masura in multimea (bc,kg,ml,mp,mc,etc), cantitatea si pretul. Prin intermediul unei clase, in
care sunt definite doua functii cu acelasi nume sa se ordoneze elementele facturii dupa cod si sa
se calculeze factura, adica sa se determine valoarea fiecarui material si TVA aferent precum si
valoarea totala fara TVA si TVA total. Pentru inlaturarea ambiguitatii cu privire la functia
apelata se va folosi un pointer declarat la functii care trebuie sa difere prin parametri.
#include<iostream.h>
#include<iomanip.h>
int i;
struct tipfact
{
unsigned int cod;
char denumire[20];
char umas[2];
double pret;
double cant;
double valoare;
double tva;
};
class facturare
{
public:
// void factura_citita (struct tipfact f,int i)
void f_factura (struct tipfact f,int i)
{
facturare::factura[i]=f;
}
struct tipfact factura[20];
//void factura_ordonare (int n)
void f_factura (int n) //a doua functie cu acelasi nume
{
int ok; struct tipfact aux;
ok=1;
while (ok)
{
ok=0;
for(i=0;i<n-1;i++)
if(facturare::factura[i].cod>facturare::factura[i+1].cod)
{
aux=facturare::factura[i];
facturare::factura[i]=facturare::factura[i+1];
facturare::factura[i+1]=aux;
ok=1;
}
}
}
void calculeaza_factura(int n)
{
for(i=0;i<n;i++)
{
facturare::factura[i].valoare=facturare::factura[i].pret*facturare::factura[i].cant;
facturare::factura[i].tva=0.19*facturare::factura[i].valoare;
}
}
void afiseaza_factura(int n)
{
for(i=0;i<n;i++)
{
cout<<"\n";
cout<<setw(5)<<setiosflags(ios::right)<<facturare::factura[i].cod;
cout<<setw(12)<<setiosflags(ios::left)<<facturare::factura[i].denumire;
cout<<setw(3)<<setiosflags(ios::right)<<facturare::factura[i].umas;
cout<<setw(10)<<setprecision(2)<<setiosflags(ios::fixed);
cout<<setiosflags(ios::right)<<facturare::factura[i].pret;
cout<<setw(10)<<setprecision(2)<<setiosflags(ios::fixed);
cout<<setiosflags(ios::right)<<facturare::factura[i].cant;
cout<<setw(10)<<setprecision(2)<<setiosflags(ios::fixed);
cout<<setiosflags(ios::right)<<facturare::factura[i].valoare;
cout<<setw(10)<<setprecision(2)<<setiosflags(ios::fixed);
cout<<setiosflags(ios::right)<<facturare::factura[i].tva;
}
}
};
void main(void)
{
int n; struct tipfact f;char r='d';
while(r=='d')
{
facturare obfactura;
do
{
cout<<"\n numarul de pozitii din factura (1<=n<=20):";
cin>>n;
}
while((n<1)||(n>20));
for(i=0;i<n;i++)
{
do
{
cout<<"\n cod material "<<i<<" (1000-9999):";
cin>>f.cod;
}
while((f.cod<1000)||(f.cod>9999));
cout<<"\n denumire material "<<i<<":";
cin>>f.denumire;
cout<<"\n unitate de masura (bc,kg,mp,ml,mc) "<<i<<":";
cin>>f.umas;
cout<<"\n cod pret "<<i<<":";
cin>>f.pret;
cout<<"\n cantitate material "<<i<<":";
cin>>f.cant;
//obfactura.factura_citita(f,i);
// se aleleaza functia pentru inregistrarea unui rand al facturii
obfactura.f_factura(f,i);
}
// obfactura.factura_ordonare(n);
// se aleleaza functia pentru ordonarea dupa coduri a produselor facturii
obfactura.f_factura(n);
cout<<"\n factura furnizor ";
cout<<"\n ==========================================";
cout<<"\n cod denumire umas pret cant valoare tva ";
cout<<"\n =========================================\n";
// se apeleaza functia de calcul a facturii
obfactura.calculeaza_factura(n);
// se apeleaza functia de afisare a facturii
obfactura.afiseaza_factura(n);
cout<<"\n ==========================================";
cout<<"\n continuati facturarea?(d/n):";
cin>>r;
}
}
In urma executarii acestui program sau obtinut rezultatele afisate mai jos, care pun in
evidenta elementele de calcul ale unei facturi, cat, mai ales, modul de supraincarcare si utilizare
a unor functii membre, inlaturandu-se ambiguitatile legate de folosirea acelorasi identificatori,
prin utilizarea de parametri efectivi de apel diferiti ca numar sau ca tip.

numarul de pozitii din factura (1<=n<=20):2


cod material 0 (1000-9999):500
denumire material 0:var
unitate de masura (bc,kg,mp,ml,mc) 0:kg
pret art 0:0.85
cantitate material 0:255.00
cod material 1 (1000-9999):300
denumire material 1:ciment
unitate de masura (bc,kg,mp,ml,mc) 1:kg
pret art 1:0.55
cantitate material 1:375.85
factura furnizor
====================================================
cod denumire umas pret cant valoare tva
====================================
300 ciment kg 0.85 255.00 216.75 41.18
500 var kg 0.55 375.85 206.72 39.28
====================================
continuati facturarea?(d/n):d
numarul de pozitii din factura (1<=n<=20):
cod material 0 (1000-9999):
denumire material 0:
unitate de masura (bc,kg,mp,ml,mc) 0:
cod pret 0:
cantitate material 0:
cod material 1 (1000-9999):
denumire material 1:
unitate de masura (bc,kg,mp,ml,mc) 1:
cod pret 1:
cantitate material 1:
cod material 2 (1000-9999):
denumire material 2:
unitate de masura (bc,kg,mp,ml,mc) 2:
cod pret 2:
cantitate material 2:
factura furnizor
=======================================
cod denumire umas pret cant valoare tva
=======================================
100 lapte hl 255.56 45.26 11566.65 2197.66
300 unt bc 2.50 35.00 87.50 16.63
700 mere kg 2.55 34.75 88.61 16.84
========================================
continuati facturarea?(d/n):n
III. 8. Functiile destructor
Dupa cum s-a precizat, daca intr-o clasa se declara si se descrie o functie constructor,
atunci cand se ceeaza o instanta obiect a acelei clase, functia constructor se executa automat
determinand initializarea diversilor membri ai clasei respective. De asemenea, la declararea unei
instante obiect se aloca memoria necesara acesteia. In mod asemanator, limbajul C++ permite
definirea unei functii destructor care se va executa automat cand se distrugea instanta obiect a
unei clase. In mod uzual, functia destructor se executa automat in urmatoarele doua situatii: in
cazul in care in program se intalneste operatorul delete in vederea eliberarii memoriei anterior
alocata instantei obiect sau in cazul terminarii efective a programului. Mai jos, sunt date
prototipurile generale ale unei functii constructor si functiei destructor asociata.

// declararea prototipului functiei constructor


nume_functie_constructor (parametrii_formali_ai_functiei_constructor);
// declararea prototipului functiei destructor
~nume_functie_constructor (void);
Observatii:
- functia destructor trebuie sa aiba acelasi nume ca functia constructor
asociata, preccedat in mod definitoriu de caracterul tilda(~);
- functia destructor nu accepta parametri formali si, ca si functia constructor, nu poate
returna nicio valoare;
- utilitatea evidenta a functiilor destructor se face imperios simtita, mai ales, atunci cand
clasele aloca memorie dinamica unor date membre, cum ar fi matricele, structurile si alte tipuri
complexe de date. Prin functiile destructor se poate elibera memoria alocata pe parcursul
executarii programului, unor date membre;
- prin functiile destructor se pot efectua multe din operatiile specifice listelor simplu si
dublu inlantuite, cum arfi: stergerea sau adaugarea, unuor elemente in lizta;
- functiile destructor nu trebuie apelate si executate inaintea incheierii ciclului de
existenta a instantei obiect respective, ci numai cand se asigura faptul ca instanta obiect urmeaza
efectiv sa fie distrusa.
Problema 31
Se considera o echpa de muncitori (max=20) cu structura: cod matricol (intre 1000 si 9999),
nume, prenume, salariu brut, somaj, CAS (Contributia pentru Asigurari Sociale),
CASS (Contributia pentru Asigurari Sociale de Sanatate), baza de impozitare, impozitul pe
salariu, retineri si rest de plata. Prin intermediul unei clase, in care a fost definita o functie
constructor careia i se transmit parametri efectivi: cod matricol, nume, prenume, salariu brut si
retinerile, sa se calculeze: contributia de somaj, CAS, CASS, baza de impozitare, impozitul, si
restul de plata pentru toti muncitorii din echipa, condusi de seful de achipa aflat in capul listei,
pentru seful de sectie si inginerul sef. Concomitent cu functia constructor adecvata, se va defini
si functia destructor asociata, care, la terminarea programului, sa afiseze mesajele cu privire la
distrugerea instantelor declarate in functia principala main().
#include<iostream.h>
#include<iomanip.h>
#define nmax 20
int i;
// declararea structurii unui angajat
struct tipangajat
{
unsigned int matricol;
char nume[10];
char prenume[10];
double brut;
double somaj;
double cas;
double cass;
double bazaimpozit;
double impozit;
double retineri;
double restplata;
};
// declararea procentelor de somaj, CAS si CASS
double psomaj=1;
double pcas=9.5;
double pcass=6.5;
// declararea clasei salarii
class salarii
{
public:
// descrierea functiei constructor de initializare
// a vectorului cu articolele de salarii
salarii (struct tipangajat a[nmax],int n,char tm)
{
for(i=0;i<n;i++) salarii::statplata[i]=a[i];
salarii::tm=tm;
};
// descrierea functiei destructor
~salarii (void)
{
if(tm=='m')
{
cout<<"\n s-a distrus instanta muncitorilor cu seful de achipa ";
cout<<statplata[0].nume<<" "<<statplata[0].prenume<<"\n";
}
if(tm=='a')
{
cout<<"\n s-a distrus instanta sefului de sectie ";
cout<<statplata[0].nume<<" "<<statplata[0].prenume;
}
if(tm=='s')
{
cout<<"\n s-a distrus instanta inginerului sef ";
cout<<statplata[0].nume<<" "<<statplata[0].prenume;
}
};
// declararea vectorului cu structurile angajatilor
struct tipangajat statplata[nmax];
char tm;
// descrierea functiei de calcul al salariilor
void calculeaza_statplata(int n)
{
for(i=0;i<n;i++)
{
salarii::statplata[i].somaj=salarii::statplata[i].brut*psomaj/100;
salarii::statplata[i].cas=salarii::statplata[i].brut*pcas/100;
salarii::statplata[i].cass=salarii::statplata[i].brut*pcass/100;
salarii::statplata[i].bazaimpozit=salarii::statplata[i].brut -
salarii::statplata[i].somaj-salarii::statplata[i].cas-salarii::statplata[i].cass;
salarii::statplata[i].impozit=salarii::statplata[i].bazaimpozit*0.16;
salarii::statplata[i].restplata=salarii::statplata[i].bazaimpozit -
salarii::statplata[i].impozit-salarii::statplata[i].retineri;
}
};
// descrierea functiei de afisare stat de plata
void afiseaza_statplata(int n)
{
for(i=0;i<n;i++)
{
cout<<"\n";
cout<<"\n matricol:"<<salarii::statplata[i].matricol;
cout<<"\n nume:"<<salarii::statplata[i].nume;
cout<<"\n prenume:"<<salarii::statplata[i].prenume;
cout<<"\n salariu brut:"<<setprecision(2)<<setiosflags(ios::fixed);
cout<<salarii::statplata[i].brut;
cout<<"\n somaj:"<<setprecision(2)<<setiosflags(ios::fixed);
cout<<salarii::statplata[i].somaj;
cout<<"\n CAS:"<<setprecision(2)<<setiosflags(ios::fixed);
cout<<salarii::statplata[i].cas;
cout<<"\n CASS:"<<setprecision(2)<<setiosflags(ios::fixed);
cout<<salarii::statplata[i].cass;
cout<<"\n impozit:"<<setprecision(2)<<setiosflags(ios::fixed);
cout<<salarii::statplata[i].impozit;
cout<<"\n retineri:"<<setprecision(2)<<setiosflags(ios::fixed);
cout<<salarii::statplata[i].retineri;
cout<<"\n rest plata:"<<setprecision(2)<<setiosflags(ios::fixed);
cout<<salarii::statplata[i].restplata;
}
};
};
void main(void)
{
// declararea vectorilor de structuri pentru
// angajati, sef de sectie si inginer sef
struct tipangajat p[nmax],psefsectie[1],pingsef[1];
char r='d';int n;
while(r=='d')
{
do
{
cout<<"\n numarul de angajati (1<=n<="<<nmax<<"):";
cin>>n;
}
while ((n<1)||(n>nmax));
// citirea datelor unui angajat
for(i=0;i<n;i++)
{
cout<<"\n cod matricol "<<i<<" (1000-9999):";
cin>>p[i].matricol;
cout<<"\n nume :";
cin>>p[i].nume;
cout<<"\n prenume :";
cin>>p[i].prenume;
cout<<"\n salariu brut :";
cin>>p[i].brut;
cout<<"\n retineri :";
cin>>p[i].retineri;
}
cout<<"\n==================================";
// creearea instantei angajat a clasei salarii
salarii angajat(p,n,'m');
cout<<"\n stat de plata muncitori";
cout<<"\n==================================";
// apelarea functiei ptr calcularea salariilor angajatilor
angajat.calculeaza_statplata(n);
// afisarea salariilor angajatilor
angajat.afiseaza_statplata(n);
cout<<"\n ==================================";
cout<<"\n cod matricol sef sectie (1000-9999):";
cin>>psefsectie[0].matricol;
cout<<"\n nume sef sectie:";
cin>>psefsectie[0].nume;
cout<<"\n prenume sef sectie:";
cin>>psefsectie[0].prenume;
cout<<"\n salariu brut sef sectie :";
cin>>psefsectie[0].brut;
cout<<"\n retineri sef sectie:";
cin>>psefsectie[0].retineri;
cout<<"\n ===================================";
// creearea instantei sefsectie a clasei salarii
salarii sefsectie(psefsectie,1,'a');
cout<<"\n stat de plata sef de sectie ";
cout<<"\n==================================";
// apelarea functiei ptr calcularea salariului sefului de sectie
sefsectie.calculeaza_statplata(1);
// afisarea salariului sefului de sectie
sefsectie.afiseaza_statplata(1);
cout<<"\n ===================================";
cout<<"\n cod matricol ing. sef (1000-9999):";
cin>>pingsef[0].matricol;
cout<<"\n nume ing. sef:";
cin>>pingsef[0].nume;
cout<<"\n prenume ing. sef:";
cin>>pingsef[0].prenume;
cout<<"\n salariu brut ing. sef :";
cin>>pingsef[0].brut;
cout<<"\n retineri ing. sef:";
cin>>pingsef[0].retineri;
cout<<"\n ===================================";
// creearea instantei ingsef a clasei salarii
salarii ingsef(pingsef,1,'s');
cout<<"\n stat de plata inginer sef ";
cout<<"\n==================================";
// apelarea functiei ptr calcularea salariului ing sef
ingsef.calculeaza_statplata(1);
// afisarea salariului ing sef
ingsef.afiseaza_statplata(1);
cout<<"\n ===================================";
cout<<"\n continuati salarizarea?(d/n):";
cin>>r;
// la terminarea programului, prin functia destructor definita
// se distrug instantele creeate cu mesajele predeclarate
}
}
In urma executarii programului de mai sus, s-au obtinut rezultatele urmatoare, punandu-
se in evidenta declararea, descrierea si utilizarea functiei destructor pentru distrugerea instantelor
create in functia main(), cu afisarea mesajelor de rigoare, transmiterea si utilizarea structurilor,
ca parametri formali in functia constructor.
numarul de angajati (1<=n<=20):2
cod matricol 0 (1000-9999):100
nume :pop
prenume :ion
salariu brut :3000
retineri :1000
cod matricol 1 (1000-9999):200
nume :stanescu
prenume :stefan
salariu brut :2000
retineri :850
====================================================
stat de plata muncitori
====================================================
matricol:100
nume:pop
prenume:ion
salariu brut:3000.00
somaj:30.00
CAS:285.00
CASS:195.00
impozit:398.40
retineri:1000.00
rest plata:1091.60

matricol:200
nume:stanescu
prenume:stefan
salariu brut:2000.00
somaj:20.00
CAS:190.00
CASS:130.00
impozit:265.60
retineri:850.00
rest plata:544.40
====================================================
cod matricol sef sectie (1000-9999):300
nume sef sectie:popescu
prenume sef sectie:sandu
salariu brut sef sectie :4000
retineri sef sectie:1200
====================================================
stat de plata sef de sectie
====================================================
matricol:300
nume:popescu
prenume:sandu
salariu brut:4000.00
somaj:40.00
CAS:380.00
CASS:260.00
impozit:531.20
retineri:1200.00
rest plata:1588.80
========================================
cod matricol ing. sef (1000-9999):500
nume ing. sef:stabu
prenume ing. sef:spiridon
salariu brut ing. sef :5000
retineri ing. sef:2000
========================================
stat de plata inginer sef
========================================
matricol:500
nume:stabu
prenume:spiridon
salariu brut:5000.00
somaj:50.00
CAS:475.00
CASS:325.00
impozit:664.00
retineri:2000.00
rest plata:1486.00
========================================
continuati salarizarea?(d/n):n
s-a distrus instanta inginerului sef stabu spiridon
s-a distrus instanta sefului de sectie popescu sandu
s-a distrus instanta muncitorilor cu seful de achipa pop ion
Functiile destructor sunt utilizate si pentru distrugerea instantelor obiectelor
care gestioneaza diverse stive de date, ocazie cu care se si elibereaza memoria alocata
unei stive, prin functia constructor.
Problema 32
Se considera o stiva de containere cu caracteristicile:cod container, un numar cuprins intre 1 si
99, continut, un camp alfanumeric de 20 caractere, data ambalarii (zi, luna si an) si greutatea in
kg. Sa se simuleze activitatile de stivuire si de incarcare intr-un mijloc de transport a
containerelor din stiva prin intermediul unei clase stivuire_incarcare, care contine: o functie
constructor utilizata pentru initializarea stivei (alocarea spatiului de memorie adecvat), o functie
destructor necesata distrugerii instantelor obiectelor folosite, o functie de depunere container in
stiva si o functie de extragere container din stiva.
#include<iostream.h>
#include<string.h>
#include<malloc.h>
#include<stdlib.h>
#define nmax 6
int nrob=2;
struct tipdata
{
int zi;
int luna;
int an;
};
struct tipstiva
{
int cc;
char continut[20];
struct tipdata data;
int greutate;
};
class stivuire_incarcare
{
public:
// declararea functiei constructor
stivuire_incarcare (void);
// declararea functiei destructor
~stivuire_incarcare (void);
// declararea functiei de depunere in stiva
int depune_in_stiva(struct tipstiva *ptrstructura);
// declararea functiei de extragere din stiva
int extrage_din_stiva(struct tipstiva *ptrstructura);
struct tipstiva *varfstiva;
};
// descrierea functiei constructor care aloca spatiul pentru stiva
stivuire_incarcare::stivuire_incarcare(void)
{
cout<<"\n initializarea stivei de containere ";
stivuire_incarcare::varfstiva=
(struct tipstiva*)malloc(nmax*sizeof(struct tipstiva));
if(stivuire_incarcare::varfstiva==NULL)
{
cout<<"\n memorie insuficienta ptr memoria stivei ";
exit(1);
}
}
// descrierea functie destructor
stivuire_incarcare::~stivuire_incarcare (void)
{
cout<<"\n s-a distrus instanta obiect"<<nrob;
nrob--;
}
// descrierea functiei depune_in_stiva()
int stivuire_incarcare::depune_in_stiva(struct tipstiva *ptrstructura)
{
struct tipstiva *ptrcontainer;
ptrcontainer=(struct tipstiva*)malloc(sizeof(struct tipstiva));
if(ptrcontainer==NULL)
{
cout<<"\n memorie insuficienta ptr un container ";
return 0;
}
*ptrcontainer=*ptrstructura;
*stivuire_incarcare::varfstiva=*ptrcontainer;
cout<<"\n varf stiva ="<<stivuire_incarcare::varfstiva;
cout<<"\n cod container ="<<stivuire_incarcare::varfstiva->cc;
stivuire_incarcare::varfstiva++;;
return 1;
}
/* descrierea functiei de extragere din stiva */
int stivuire_incarcare::extrage_din_stiva(struct tipstiva *ptrstructura)
{
if(!stivuire_incarcare::varfstiva)
{
cout<<"\n stiva goala "<<endl;
return 0;
}
stivuire_incarcare::varfstiva--;
*ptrstructura=*stivuire_incarcare::varfstiva;
ptrstructura=stivuire_incarcare::varfstiva;
return 1;
}
void main(void)
{
int k,n;
struct tipstiva *ptrcontainera,*ptrcontainers,container,containers;
stivuire_incarcare obiect1,obiect2;
char rasp;k=0;
int terminat=0;
ptrcontainera=(struct tipstiva*)malloc(sizeof(struct tipstiva));
if(ptrcontainera==NULL)
{
cout<<"\n memorie insuficienta un container ";
exit(1);
}
do
{
cout<<"\n numarul maxim de containere, n(1<=n<="<<nmax<<")=";
cin>>n;
}
while((n<1)||(n>nmax));
while(!terminat)
{
cout<<"\n a - asezare container in stiva";
cout<<"\n s - scoatere container din stiva";
cout<<"\n t - terminare program";
cout<<"\n Alegeti operatia dorita:";
cin>>rasp;
switch (rasp)
{
case 'a':
if(k<n)
{
k++;
cout<<"\n cod container:";
cin>>container.cc;
cout<<"\n continut container:";
cin>>container.continut;
cout<<"\n ziua ambalarii:";
cin>>container.data.zi;
cout<<"\n luna ambalarii:";
cin>>container.data.luna;
cout<<"\n anul ambalarii:";
cin>>container.data.an;
cout<<"\n greutate container:";
cin>>container.greutate;
ptrcontainera=&container;
if(k%2)
obiect1.depune_in_stiva(ptrcontainera);
else
obiect2.depune_in_stiva(ptrcontainera);
}
else
cout<<"\n depasirea capacitatii de depozitare";
break;
case 's':
if(k>=1)
{
ptrcontainers=(struct tipstiva*)malloc(sizeof(struct tipstiva));
if(ptrcontainers==NULL)
{
cout<<"\n memorie insuficienta ptr un container ";
exit(1);
}
if(k%2)
{
obiect1.extrage_din_stiva(ptrcontainers);
containers=*ptrcontainers;
cout<<"\n s-a extras containerul obiectului 1:";
cout<<"\n =======================================:";
cout<<"\n cod container :"<<containers.cc;
cout<<"\n continut container :"<<containers.continut;
cout<<"\n data containerului :"<<containers.data.zi;
cout<<"/"<<containers.data.zi<<"/"<<containers.data.an;
cout<<"\n greutate container :"<<containers.greutate;
}
else
{
obiect2.extrage_din_stiva(ptrcontainers);
containers=*ptrcontainers;
cout<<"\n s-a extras containerul obiectului 2:";
cout<<"\n ===================================:";
cout<<"\n cod container :"<<containers.cc;
cout<<"\n continut container :"<<containers.continut;
cout<<"\n data containerului :"<<containers.data.zi;
cout<<"/"<<containers.data.zi<<"/"<<containers.data.an;
cout<<"\n greutate container :"<<containers.greutate;
}
k--;
}
else
cout<<"\n nu mai sunt containere depozitate";
break;
case 't':
terminat=1;
break;
default:
cout<<"\n operatie gresit selectata";
}
}
}
Rezultatele executiei programului de mai sus, sunt afisate in continuare, punandu-se in
evidenta urmatoarele: initializarea si alocarea memoriei pentru o stiva de structuri, depunerea
adreselor structurilor intr-o stiva si a structurilor aferente la adresle specificate in stiva,
extragerea adreselor structurilor din stiva si a structurilor corespunzatoare de la aceste adrese
precum si distrugerea instantelor celor doua obiecte create in program dupa terminarea folosirii
acestora.
initializarea stivei de containere
initializarea stivei de containere
numarul maxim de containere, n(1<=n<=6)=4
a - asezare container in stiva
s - scoatere container din stiva
t - terminare program
Alegeti operatia dorita:a
cod container:100
continut container:ciment
ziua ambalarii:11
luna ambalarii:11
anul ambalarii:2005
greutate container:150
varf stiva =0x00790610
cod container =100
a - asezare container in stiva
s - scoatere container din stiva
t - terminare program
Alegeti operatia dorita:a
cod container:200
continut container:var
ziua ambalarii:21
luna ambalarii:11
anul ambalarii:2005
greutate container:400
varf stiva =0x007904F0
cod container =200
a - asezare container in stiva
s - scoatere container din stiva
t - terminare program
Alegeti operatia dorita:a
cod container:300
continut container:suruburi
ziua ambalarii:11
luna ambalarii:10
anul ambalarii:2005
greutate container:125
varf stiva =0x00790638
cod container =300
a - asezare container in stiva
s - scoatere container din stiva
t - terminare program
Alegeti operatia dorita:a
cod container:400
continut container:saibe
ziua ambalarii:07
luna ambalarii:09
anul ambalarii:2005
greutate container:175
varf stiva =0x00790518
cod container =400
a - asezare container in stiva
s - scoatere container din stiva
t - terminare program
Alegeti operatia dorita:r
operatie gresit selectata
a - asezare container in stiva
s - scoatere container din stiva
t - terminare program
Alegeti operatia dorita:d
operatie gresit selectata
a - asezare container in stiva
s - scoatere container din stiva
t - terminare program
Alegeti operatia dorita:a
depasirea capacitatii de depozitare
a - asezare container in stiva
s - scoatere container din stiva
t - terminare program
Alegeti operatia dorita:s
s-a extras containerul obiectului 2:
===================================:
cod container :400
continut container :saibe
data containerului :07/09/2005
greutate container :175
a - asezare container in stiva
s - scoatere container din stiva
t - terminare program
Alegeti operatia dorita:s
s-a extras containerul obiectului 1:
=======================================:
cod container :300
continut container :suruburi
data containerului :11/10/2005
greutate container :125
a - asezare container in stiva
s - scoatere container din stiva
t - terminare program
Alegeti operatia dorita:s
s-a extras containerul obiectului 2:
===================================:
cod container :200
continut container :var
data containerului :21/i1/2005
greutate container :400
a - asezare container in stiva
s - scoatere container din stiva
t - terminare program
Alegeti operatia dorita:s
s-a extras containerul obiectului 1:
=======================================:
cod container :100
continut container :ciment
data containerului :11/11/2005
greutate container :150
a - asezare container in stiva
s - scoatere container din stiva
t - terminare program
Alegeti operatia dorita:s
nu mai sunt containere depozitate
a - asezare container in stiva
s - scoatere container din stiva
t - terminare program
s-a distrus instanta obiect2
s-a distrus instanta obiect1