Sunteți pe pagina 1din 68

http://software.ucv.ro/~mburicea/Cap3POO.

htm
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 precizanduse 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 precizanduse 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, putanduse 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, utilizanduse 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