Вы находитесь на странице: 1из 86

PROGRAMAREA

CALCULATOARELOR 2
Modul 2, partea I
Curs 4
1
CUPRINS

1. Concepte ale programării obiectuale


2. Clase şi obiecte:
• Noţiuni introductive
• Declararea unei clase
• Accesul la membri
• Autoreferinţa
• Constructori şi destructori
• Constructor de copiere
• Constructor cu conversie de tip

2
1. CONCEPTE ALE PROGRAMĂRII OBIECTUALE
DE CE POO (PROGRAMARE ORIENTATĂ PE OBIECTE)?
 Orice program este compus din 2 părți distincte:
- date (de intrare și/sau iesire) → tipuri de date
- operații → funcții
 Tipuri de date utilizate în programare:
- tipuri predefinite
- tipuri de date utilizator (în C/C++ prin utilizarea struct,
union, enum și typedef); operațiile acționează tot asupra
unor tipuri predefinite de date, elementele componente nu
sunt protejate → programarea structurată
- clasa: tip abstract, reunește date și operații în cadrul
aceluiași tip de dată → Programarea ADT (Abstract Data
Type – abstractizare a datelor) 3
CONCEPTE ALE PROGRAMĂRII OBIECTUALE

 Programarea orientată pe obiecte (POO) este un concept


foarte natural. În jurul nostru sunt o multitudine de
obiecte, interconectate între ele, comunicând unele cu
altele într-un fel sau altul – obiecte fizice (reale) –
complexe.
 Aceste obiecte pot fi reprezentate în calculator prin
obiecte calculator – mult mai simple, reprezentate prin
date concrete și operații specifice.

4
 POO a apărut pentru a elimina dezavantajele
programării structurate, în ceea ce privește tratarea
separată a algoritmilor și a structurilor de date ce se
prelucrează, posibilitatea reutilizării programelor,
scalabilității unor module de program.

 Ideea de bază de la care pleacă programarea orientată


pe obiecte este de a grupa structurile de date cu
operațiile care prelucrează respectivele date. Un
asemenea ansamblu poartă denumirea de clasă.

5
 Proiectarea de programe utilizând clase se numește
programare prin abstractizarea datelor ADT, iar dacă se
consideră și mecanismul moștenirii avem programare
orientată pe obiecte (POO).
Date + Metode = Clasa

 În mod frecvent, pentru structurile de date se utilizează


denumirea de date membre, câmpuri sau atribute, iar
pentru procedurile ce prelucrează aceste date, termenul
de funcții membre sau metode.

6
 Primul limbaj orientat pe obiecte este Simula 67,
dezvoltat în cadrul Norwegian Computing Centre. (anii
‘60)
 Alan Kay este considerat promotorul programării
orientate pe obiecte
 Simula a rămas un instrument în dezvoltarea de noi
limbaje, cele mai importante în anii 70-80 fiind Smalltalk,
Eiffel și C++.
 În acest moment cele mai folosite limbaje obiectuale sunt
derivate din C++, și anume C#, Java, Python, PhP, etc.

7
OBIECTELE
 Ce este un obiect? Un obiect modelează o entitate din
lumea reală sau imaginară.

 Fiecare obiect este unic. Puterea unui obiect e dată de


faptul că poate fi definit și menținut independent de
celelalte obiecte.

 Obiectele pot fi distinse între ele pentru că fiecare obiect


posedă un set de caracteristici unice (prin valori concrete).

 Reprezentarea obiectelor și a comportamentului lor


reprezintă obiectivul principal al analizei și proiectării
orientate spre obiecte.
8
 Definiția obiectelor după Grady Booch: un obiect este
complet caracterizat de 3 elemente:
- starea sa,
- comportamentul său
- identitatea sa.

Starea = setul de date care conțin informații referitoare la


obiect (structura obiectului și valorile sale curente).

Comportamentul = serviciile pe care le pune la dispoziție,


modul în care interacționează cu alte obiecte

Identitatea = un cod unic, ce îl diferențiază de alte obiecte

9
 Clasa = un șablon pentru generarea unor obiecte având
structura și comportamentul identice

 Clasa (conf. OMG) = o implementare care poate fi


instanțiată în vederea creării de multiple obiecte având
același comportament. Un obiect este o instanță a unei
clase.
- există și clase neinstanțiabile, numite abstracte, utilizate
în special în derivare

 Interfața unei clase = implementarea întregului său


comportament. Corespunde metodelor clasei care pot fi
utilizate de clienți ai clasei (publice)

10
 Mesajele fac apel la serviciile pe care obiectul le poate
oferi. Obiectele comunică prin intermediul mesajelor
(emițătoare și receptoare). Mesajul - obiect, numele
metodei și parametrii care rafinează mesajul.

 Metodele sunt secvențe de cod care implementează


mesajele. Metodele au acces direct la starea obiectului (la
date)
 Ex: clasa Student (nume, prenume, facultate, anul, grupa,
data_nașt., note, etc.).
- Mesaje posibile: Care este numele? Care este grupa?
Care este media anuală? etc.
- Servicii (metode) : furnizează toate detaliile despre
student, furnizează vârsta, afișează grupa, schimbă grupa,
furnizează media, etc. 11
 Încapsularea datelor:
 gruparea datelor şi a operaţiilor permise asupra acestora
 ascunderea informaţiei (pentru protejarea împotriva
distrugerii accidentale).
 accesul la date prin intermediul metodelor
 asigurată prin specificatorii de acces

 Abstractizarea datelor:
− identifică proprietățile generale și esențiale, omițând
unele detalii neesențiale (Ex. – carnet șofer)
 un obiect este caracterizat complet de specificaţiile
metodelor sale, detaliile de implementare fiind
transparente pentru utilizator (principiul lui Parnas)
 modificarea structurii datelor membre are efect numai
asupra metodelor, iar dacă se păstrează specificaţiile
metodelor, nu afectează utilizarea obiectului 12
 Pot exista la un moment dat mai multe obiecte de acelaşi
tip, adică instanţe ale aceleiaşi clase:
 instanţele obiectului vor avea date diferite, dar vor
partaja acelaşi cod corespunzător metodelor clasei din
care provin

 Dacă există o anumită clasă şi cineva doreşte alta, uşor


diferită, nu este nevoie de modificarea primei clase, ci se
poate defini una nouă, care să fie ca şi clasa veche şi să
aibă unele caracteristici suplimentare prin ceea ce se
cheamă derivare sau moştenire.

13
Moștenirea
 Clasa originală se numește clasa de bază sau
superclasă, iar noua clasă - clasa derivată sau sub-clasă.

 Putem considera că toate clasele de obiecte sunt derivate


dintr-o clasă inițială, clasa obiectelor generice.

 Ierarhizarea poate fi realizată în continuare sub forma


unui arbore pe mai multe niveluri.

 Sunt clase (Ex. OM) ce nu pot fi instanțiate. Acestea sunt


clasele Abstracte.
- ele vor conține cel puțin o metodă abstractă. O
metodă abstractă e doar declarată, fiind definită în altă(e)
clasă(e).
14
 Polimorfismul:
 comportament diferit în funcţie de context
 posibilitatea de a opera cu diverse variante ale unor
funcţii ce realizează aceeaşi operaţie în mod specific
pentru diferite obiecte dintr-o ierarhie de clase

 Polimorfism

- static: supraîncărcarea funcțiilor (overloading)


- dinamic: existența unor funcții cu același nume și aceeași
semnătură în clase aflate într-o ierarhie de moștenire –
redefinire (overriding)

15
 POO :
 definire de tipuri abstracte (ADT) +
 derivarea tipurilor +
 [polimorfism (inclus de obicei în ADT și
derivare)]

 Principalele avantaje ale POO sunt :


 uşurinţa proiectării şi reutilizării codului
 fiabilitate crescută (codul odată testat nu mai
generează erori)
 uşurinţa înţelegerii
 creşterea abstractizării prin descompunerea în
subprobleme
 capacitatea de încapsulare: prin combinarea datelor şi
a operaţiilor pe date
 ascunderea informaţiei: se tratează operaţiile ca şi
16
cutii negre
2. CLASE ŞI OBIECTE
Noţiuni introductive

 Clasele permit introducerea unor tipuri noi de date

 Un tip de dată constă dintr-o reprezentare concretă a


obiectelor din acel tip, precum şi dintr-un set de operaţii
ce manipulează aceste obiecte:
 alte operaţii decât cele specificate nu sunt permise
asupra obiectelor

 Ca urmare, aceste operaţii caracterizează acel tip


 de obicei, structura internă a obiectelor este ascunsă
pentru operaţiile ce nu aparţin acelui tip
17
 Avem de-a face cu tipuri de date abstracte

 D.p.d.v. al limbajului C++, o clasă este un nou tip de dată

 După definirea unei clase, compilatorul o tratează ca şi


cum ar fi un tip de dată predefinit, inclusiv prin verificarea
erorilor

18
Declararea unei clase

 Declaraţia unei clase conţine un antet şi un corp:


 antetul specifică numele clasei şi eventual clasele de
bază
 corpul clasei conţine membrii clasei

 Membrii pot fi :
 date membre -> specifică reprezentarea obiectelor
clasei:
 sintactic acestea se declară ca şi variabilele obişnuite

 metode (funcţii) membre (de interfaţă) -> specifică


operaţiile clasei:
 sintactic acestea sunt ca şi prototipurile funcţiilor obişnuite

19
Specificator de acces
Antet clasa class <nume_clasa>
{
[private:]
[declaratii de date] Sectiune
[declaratii de functii]
[protected:]
Corp clasa [declaratii de date] Sectiune
[declaratii de functii]
[public:]
[declaratii de date] Sectiune
[declaratii de functii]
} [lista de obiecte];

20
 Membrii unei clase pot aparţine unor secţiuni delimitate de
etichete de acces sau specificatori de acces:
 public, private şi protected

 Specificatorii de acces:
 permit ascunderea datelor şi metodelor
 ordinea în care apar este nerelevantă
 dacă nu este prezent nici un specificator de acces toate
datele membre şi toate metodele membre se consideră
că sunt private

21
 Un membru care este public poate fi utilizat de orice altă
funcţie (din clasă sau din afara clasei)

 Un membru care este privat poate fi utilizat doar de


metodele membre ale clasei sau de funcţiile prietene
clasei

 Un membru cu atributul protected are aceleaşi


caracteristici ca şi unul privat, în plus poate fi utilizat de
metode membre sau funcţii prietene ale claselor derivate,
dar numai în obiecte de tipul derivat:
 membrii de acest tip se folosesc în cazul derivării
claselor
22
 De obicei, datele unui obiect sunt plasate în secţiunea
private:
 sunt accesibile direct numai metodelor din clasă
 se permite accesul din exterior numai prin intermediul
metodelor publice
 care devin astfel o interfaţă la datele obiectului

 Exemplu:
class Rectangle
{
int x, y;
public:
void setVal(int, int);
int aria(void) {
return x*y; }
}; 23
Criterii de calitate ale unei clase (Bjarne Stroustrup)
 O clasă trebuie să ofere un set mic, dar suficient și bine
definit de operații publice
 O clasă trebuie să poată fi privită ca și o cutie neagră,
manevrabilă prin setul de operații
 O clasă trebuie să aibă un set restrâns de date publice, pe
cât posibil, niciuna
 O clasă trebuie să fie ușor modificabilă, fără ca acest lucru
să se răsfrângă asupra interfeței publice (cu excepția
extinderii acesteia)

24
Accesul la membri
 Obiectul: o instanţă a unei clase

 Declararea unui obiect se poate face:

 în momentul declarării clasei (între acolada din dreapta


şi terminatorul ;)
 ulterior, printr-o declaraţie separată

 Declararea ulterioară a unui obiect se face astfel:


Nume_clasa nume_obiect;
Nume_clasa lista_nume_obiecte;

25
 Un obiect poate fi privit ca o generalizare a noțiunii de
variabilă, astfel încât toate aspectele referitoare la
variabile sunt păstrate:
- din punct de vedere al accesului avem obiecte
locale și globale
- din punct de vedere al alocării avem obiecte statice,
automatice și dinamice

26
 Accesul din exterior la membrul public al unui obiect (dată
sau funcţie/metodă) se face cu operatorul punct(.) :
nume_obiect.data_membra
nume_obiect.metoda_membra(lista_param_actuali)

 Se pot declara şi pointeri la obiecte :


// declarare si initializare pointer
Nume_clasa *nume_pointer;
nume_pointer = &nume_obiect;
Nume_clasa *pobj = new Nume_clasa(…); //constructor
 Accesul pe baza pointerilor se face similar cu structurile
(folosind operatorul →), în modul următor :
nume_pointer -> data_membra
nume_pointer -> metoda_membra(lista_param_actuali)
27
 Putem să declarăm și obiecte de tip referință, caz în care
trebuie inițializate la declarare.

// declarare si initializare referință


Nume_clasa &nume_referință=nume_obiect;

 Accesul pe baza referinței se face tot cu operatorul “.” în


modul următor :
nume_referință.data_membra
nume_referință. metoda_membra(lista_param_actuali)

28
Definirea metodelor
 Dacă definirea metodei este realizată în interiorul clasei,
sintaxa definiţiei este identică cu cea a oricărei funcţii
întâlnite în programarea non-obiectuală
 În acest caz avem aşa numitele metode inline pentru care
compilatorul va încerca o implementare inline:

class nume_clasa{

// metoda inline
tip_returnat nume_metoda (lista_parametri_formali)
{
// corp metoda
}

29
} [lista_de_obiecte];
 O altă metodă de descriere a unei clase este de a declara
doar prototipul metodelor membre în interiorul clasei şi de a
le defini funcţionalitatea lor în exteriorul zonei de cod
alocate acesteia
 În această situaţie, în momentul implementării corpului
metodei respective, trebuie să specificăm numele clasei
căreia îi aparţine metoda al cărei conţinut urmează să fie
scris
 Pentru aceasta se foloseşte operatorul de rezoluţie sau
scop, simbolizat prin ::

tip_returnat Nume_clasa :: nume_functie (lista_param_formali)


{
// corp metoda
} 30
class Rectangle
{
int x, y;
public:
void setVal(int, int);
// metoda inline
int aria(void) { return x*y; }
}; // Rectangle

void Rectangle::setVal(int a, int b)


{
if (a>0 && b>0) { x = a; y = b; }
else { x = 0; y = 0; }
}

31
int main (void){
Rectangle dr1, dr2; // declarare obiecte
dr1.setVal(4,5); // apel metoda
dr2.setVal(3,4); // apel metoda
cout<< “Aria obiectului 1: “ << dr1.aria( ); // apel metoda
cout<< “\nAria obiectului 2: “ << dr2.aria( ); // apel metoda

Rectangle *pdr; // declarare pointer la tipul Rectangle


pdr = &dr1; // initializare pointer
pdr->setVal(6,3); // apel metoda
cout<< “\nAria obiectului 1: “<< pdr->aria( ); // apel metoda
pdr = &dr2;
pdr->setVal(5,4);
cout<< “\nAria obiectului 2: “<< pdr->aria( );

Rectangle &ref_dr=dr1; // declarare si initializare


// referinta de tipul Rectangle
ref_dr.setVal(10,5); // apel metoda
cout<< "\nAria obiectului 1: "<< ref_dr.aria( ); // apel metoda 32

}
 Operatorul de rezoluţie mai poate fi folosit pentru a distinge
între datele membre şi variabile locale cu acelaşi nume
dintr-un bloc (funcţie sau instrucţiune compusă) :

class Point
{
private:
int x, y;
public:
void setVal(int x, int y)
{
Point::x = x;
Point::y = y;
}
}; 33
class Access {
int nA;
int getA( ) { return nA; }
private: // redundant
int nB;
int getB( ) { return nB; }
protected:
int nC;
int getC( ) { return nC; }
public:
int nD;
int getD( ) { return nD; }
};

34
int main( )
{
Access cAccess;
cAccess.nD = 5; // corect
std::cout << cAccess.getD( ); // corect

cAccess.nA = 2; // gresit, e private


std::cout << cAccess.getB( ); // gresit, e private

cAccess.nC = 7; // gresit, e protected


std::cout << cAccess.getC( ); // gresit, e protected

35
 Pentru accesul la date putem utiliza funcții de tip accesor
(care returnează valoarea unei date membre – getter)
sau funcţii de tip mutator (care setează valoarea unei
date membre – setter)
class Date{
private:
int nMonth;
int nDay;
int nYear;
public:
// Getters
int getMonth( ) { return nMonth; }
int getDay( ) { return nDay; }
int getYear( ) { return nYear; }
// Setters
void setMonth(int Month) { nMonth = Month; }
void setDay(int Day) { nDay = Day; } 36
void setYear(int Year) { nYear = Year; }
};
 Avantaje:
 Dacă se doreşte modificarea datelor membre, se
modifică funcţiile accesor și/sau mutator şi, atât timp cât
nu se modifică specificaţiile acestora, utilizarea acestor
metode nu se modifică

 Utilizatorii clasei nu au nevoie să cunoască detaliile de


implementare (date membre, alte funcţii private), ci doar
interfaţa (funcţiile accesor și mutator)

 Folosirea acestor funcţii accesor/mutator asigură o


protecţie a datelor membre:
 Nu permit modificări accidentale sau nepermise
 Asigură şi alte modificări alte altor date membre corelate

37
• Se simplifică depanarea programului, deoarece
modificarea datelor membre se face controlat, prin
intermediul unei singure funcţii

 Uzual se separă declaraţia claselor de definiţia acestora


şi de fişierele unde sunt utilizate
 Astfel se crează fişiere antet (.h) ce conţin declaraţiile
claselor şi fişiere sursă (.cpp) ce conţin definiţiile claselor

38
STRUCTURI ÎN C++
 În limbajul C structurile au doar date membre
 În limbajul C++, o structură e asimilată unei clase, toți
membrii fiind implicit public:
 o structură în C++ poate include metode

struct Point { class Point {


int x, y; public:
Point(int, int); int x, y;
void offsetPt(int, int); Point(int, int);
}; void offsetPt(int, int);
};//class Point
- Celelalte consideratii privind structurile sunt păstrate în
C++ (acces la membri, inițializare, etc.) 39
REUNIUNI ÎN C++
 O reuniune, union, în C++ e considerată o clasă având
datele memorate în aceeași zonă de memorie a unei
instanțe (a unui obiect):
 Dimensiunea unui obiect va fi definită de cea mai mare
dimensiune a datelor membre
 Utilizarea reuniunilor e realizată în cazul în care un obiect
are valori de tipuri diferite la momente diferite, dar de un
singur tip la un moment dat
 Toți membrii unei reuniuni sunt considerați implicit public

 Într-o reuniune și într-o structură putem considera


specificatorii de acces public, private și protected pentru a
controla accesul la membrii structurii sau reuniunii
40
Autoreferinţa

 Pentru a defini metodele (funcţiile) membre trebuie


făcute referiri la datele membre fără a specifica un obiect
anume

 La apelul unei metode, aceasta este informată asupra


identităţii obiectului asupra căruia va acţiona prin
transferul unui parametru implicit care reprezintă adresa
acelui obiect

 Acest parametru se numeşte autoreferinţa sau pointerul


this= adresa obiectului curent
41
 În definiţia unei funcţii membre, este permis accesul la
această adresă folosind cuvântul cheie this:
 acesta este un pointer la obiectul pentru care s-a apelat
funcţia şi corespunde următoarei declaraţii:
Nume_clasa *const this;

 În interiorul clasei, accesul la o variabilă se poate face, în


afară de modul prezentat în exemplele anterioare, cu
ajutorul pointer-ului this:
this->x=0;  x=0;

42
 Utilizări ale autoreferinţei :
 în cazul în care avem de-a face în interiorul unei funcţii
dintr-o clasă cu alte instanţe ale clasei:
 this ajută la diferenţierea variabilelor din clasă în ceea ce
priveşte obiectele de care aparţin
 pointerul în discuţie va indica întotdeauna obiectul curent

 pentru a verifica dacă parametrul unei metode este


chiar obiectul însăşi:

int MyClass::isthis(MyClass param)


{
if(&param == this) return 1;
else return 0;
}

43
 Utilizări ale autoreferinţei :
 în metode ce supraîncarcă operatorul de atribuire -
asignare ( = ), când se returnează obiectul curent
 în clase în care parametrul unei metode are același
nume cu un atribut al clasei :

class X{
int a;
public:
X(int a){
this->a=a; // X::a = a;
}
…};
44
EX. POINTERUL THIS
#include <iostream>
using namespace std;
class TimeClass {
int hours, minutes;
public:
TimeClass ( int new_hours, int new_minutes) // constructor
{ hours = new_hours; minutes = new_minutes; }
void setTime ( int new_hours, int new_minutes )
{ hours = new_hours; minutes = new_minutes; }
void getTime ( int &current_hours, int &current_minutes){
current_hours = hours; current_minutes = minutes; }
void copyTime( TimeClass &Time2);
};//TimeClass
45
void TimeClass::copyTime (TimeClass &Time2){
this->hours=Time2.hours;
this->minutes=Time2.minutes;};
int main(void){
TimeClass Time1 (11,25), Time2 (12,12),Time3(1,1); // instantieri
int hrs, mins;
Time1.getTime(hrs, mins);
cout<<"time1 is: " <<hrs<< ":" <<mins<<endl;
Time2.getTime(hrs, mins);
cout<<"time2 is: " <<hrs<< ":" <<mins<<endl;
Time3.copyTime(Time2);
Time3.getTime(hrs, mins);
cout<<"\nAfter copying Time2 to Time3, the time is :
"<<hrs<<":"<<mins<<endl;
cout<<"\npress Enter to continue."; cin.get();
46
}//main
Constructori şi destructori

 Printre funcţiile membre ale unei clase există două tipuri


particulare: constructori şi destructori

 Constructorul are rolul de a crea şi inţializa un obiect al


clasei
 are acelaşi nume ca şi clasa căreia îi aparţine

 Destructorul are rolul de a distruge obiecte create de


către constructor
 numele destructorului este compus din caracterul
tilda(~) urmat de numele clasei căreia îi aparţine

47
 Teoretic constructorii și destructorii pot fi publici sau
privaţi, dar uzual se folosesc ca membri publici

 Aceste metode efectuează operaţii prealabile utilizării


unui obiect, respectiv distrugerii acestuia

 Alocarea şi eliberarea spaţiului de memorie necesar


datelor membre este făcută de către compilator (a nu se
confunda cu alocarea dinamică la iniţiativa
programatorului)

48
TIPURI DE OBIECTE
 Automatice, sunt create de fiecare dată când apare o
definiție a unui obiect la execuție și sunt distruse când se
părăsește blocul unde au fost create
 Statice (globale, locale), sunt create o singură dată,
când programul e pornit (în cadrul blocului pentru cele
locale) și sunt distruse la sfârșitul programului.
 Dinamice, sunt create de programator în heap-ul
dinamic cu operatorul new și sunt distruse cu delete.
 Derivate, aparțin claselor derivate, dar înainte se
apelează constructorul clasei de bază și apoi
constructorul din clasa derivată, dacă e necesar
 Anonime, au o existență temporară, fiind necesare în
evaluarea expresiilor sau la transferul parametrilor pe
49
stivă
 Caracteristici comune constructori/destructori :

nu returnează valori; nu se specifică void în declaraţii


nu pot fi moşteniţi, dar o clasă derivată poate apela
constructorul/destructorul clasei de bază
nu se poate obţine adresa acestor funcţii
dacă nu sunt definiţi explicit, sunt generaţi automat de
către compilator, caz în care vor avea specificatorul de
acces public (impliciți)

ca orice alte metode, constructorii și destructorii pot fi


doar declaraţi în interiorul clasei şi apoi implementaţi în
exteriorul acesteia (utilizând operatorul de rezoluţie :: )
50
 Caracteristici specifice constructorilor :
❑ constructoriipot avea parametri, parametri impliciţi şi pot
fi supraîncărcați (overloading)
▪ constructorul explicit vid, este constructorul care nu
are nici un argument; de obicei, aceste funcţii
iniţializează variabilele din clasă cu valori implicite (0,
NULL, etc.)
▪ constructorul explicit cu parametri, este acel
constructor care iniţializează anumite variabile din
clasă şi/sau efectuează anumite operaţii asupra
variabilelor primite ca parametri. Putem avea
constructori expliciti cu toti parametrii impliciți, o parte
dintre ei sau nici un parametru implicit.

❑ compilatorul apelează automat constructorul la 51

definirea obiectelor
 Caracteristici specifice destructorilor :

destructorii nu pot avea parametri


într-o clasă putem defini doar un destructor
compilatorul apelează automat destructorul la
distrugerea obiectelor

52
Observații constructori:

 dacă în corpul clasei apare un constructor explicit


(indiferent de numărul de parametri), compilatorul nu mai
generează constructorul implicit
 În cazul în care într-o clasă avem constructor explicit,
declaraţia unui obiect poate să conţină valori de
inițializare (dacă acel constructor are parametri).
 Dacă este necesară crearea unui tablou de obiecte și
clasa prezintă constructori expliciți, atunci trebuie să
existe un constructor fără parametri sau în unele medii de
programare e acceptat un constructor explicit cu toți
parametrii impliciți
53
Observații constructori:

 o clasă poate conţine un constructor explicit vid (fără


parametri), care:
-poate să nu aibă implementare (nerecomandat)
-dacă are implementare, face iniţializări ale datelor
membre cu valori implicite (recomandat)

 Momentul apelului unui constructor depinde de clasa de


memorare a obiectului:
 pentru un obiect global apelul se face la începerea
execuţiei programului
 în cazul unui obiect local apelul se face la intrarea în
execuţie a blocului respectiv
54
Observații destructori:

 Destructorii expliciţi sunt utili atunci când în constructori se


fac alocări dinamice

 simpla prezenţă a unui pointer printre datele membre nu


impune crearea unui destructor explicit:
 acesta trebuie să apară numai dacă se face o alocare dinamică
în constructor (ce implică data membră pointer)

 Momentul apelului unui destructor depinde de clasa de


memorare a obiectului:
 pentru un obiect global apelul se face la terminarea
execuţiei programului
 în cazul unui obiect local apelul se face la ieşirea din
execuţie a blocului respectiv
55
Exemplul 1:
// directive preprocesor pentru includerea bibliotecilor necesare

class Rectangle {
int x,y;
public:
//constructor explicit cu parametri impliciți
Rectangle(int a=0, int b=0) {
x = a; y = b;
}
void setX(int);
void setY(int);

int aria(void) {
return x*y;
} 56

};
void Rectangle::setX(int a) {
if (a>0) x=a;
else x = 0;
}
void Rectangle::setY(int b) {
if (b>0) y=b;
else y = 0;
}

int main (void){


Rectangle ob_r(4, 5); // declarare obiect
cout<< “Aria obiectului: “ << ob_r.aria( ); // apel metoda
ob_r.setX(6); // apel metoda
ob_r.setY(9);
cout<< “Aria obiectului: “ << ob_r.aria( ); // apel metoda
cin.get();
} 57
Exemplul 2:
// directive preprocesor pentru includerea bibliotecilor necesare
class Stiva
{
private:
int dim;
char *stack;
int next; // poz. ultimului element in stiva

public:
Stiva( void );
Stiva( int );
~Stiva( void );
int push( char c );
int pop( char &c );
int isEmpty( void );
int isFull( void );
58
};
// constructori
Stiva :: Stiva(void) {
next = -1;
dim = 256;
stack = new char [dim];
}

Stiva :: Stiva(int dim_i) {


next = -1;
dim = dim_i;
stack = new char [dim];
}

// destructor
Stiva :: ~Stiva(void) {
delete [ ] stack;
} 59
// test stiva goala
int Stiva :: isEmpty(void) {
if (next < 0)
return 1;
else
return 0;
}

// test stiva plina


int Stiva::isFull(void) {
if(next >= dim)
return 1;
else
return 0;
}
60
// introducere in stiva
int Stiva::push(char c) {
if(isFull( ))
return 0;
stack[++next] = c;
return 1;
}

// extragere din stiva


int Stiva::pop(char &c) {
if(isEmpty( ))
return 0;
c = stack[next--];
return 1;
} 61
int main(void){
int i;
Stiva mesaj;
Stiva subiecteR1(10000);
Stiva subiecteR2(20000);
char buf[64];

strcpy(buf, “Programare obiectuala”);


for(i=0; i<strlen(buf); i++)
mesaj.push(buf[i]);

buf[0] = ‘\0’;
i=0;
while(!mesaj.isEmpty( ))
mesaj.pop(buf[i++]);
cout << endl << buf << endl;
cin.get();
62
}
Constructorul de copiere

 Considerăm clasa Stiva:

class Stiva {
private:
int dim;
char *stack;
int next;

public:
Stiva(int dim_i);
~Stiva(void);
// …
};
63
Stiva :: Stiva(int dim_i)
{
next = -1;
dim = dim_i;
stack = new char [dim];
}

int main(void)
{
Stiva ob1(10);
Stiva ob2(ob1); // copiază obiectul 1 in obiectul 2
// …
}
64
 Compilatorul generează automat un constructor de
copiere (implicit):
 acesta face copierea element cu element

 Probleme la utilizarea constructorului de copiere implicit:


 nu se face şi o copiere a elementelor stivei, ci numai o
atribuire între pointeri
 ambele obiecte vor utiliza aceeaşi zonă alocată dinamic
(cea corespunzătoare obiectului ob1)
 dacă va fi apelat destructorul pentru ob2, se va elibera
zona de memorie aferentă obiectului ob1 și o utilizare
ulterioară a obiectului ob1 va genera erori
 la distrugerea celor 2 obiecte se încearcă eliberarea de
2 ori a zonei de memorie a obiectului 1. 65
 Există şi alte situaţii când iniţializarea unui obiect cu datele
altui obiect de acelaşi tip conduce la o situaţie
asemănătoare cu cea precedentă:
 transferul unui obiect ca parametru către o funcţie
 transferul unui obiect ca rezultat al unei funcţii
 crearea unui obiect temporar

 În acest caz se recomandă utilizarea unui constructor


special numit constructor de copiere (copy constructor):

Nume_clasa(const Nume_clasa &ob);

66
class Stiva {

public:
Stiva(int dim_i=256);
~Stiva(void);
Stiva(const Stiva &);

};

Stiva::Stiva(const Stiva &inStiva)


{
next = inStiva.next;
dim = inStiva.dim;
stack = new char [dim];
for(int i=0; i<next; i++)
67
stack[i] = inStiva.stack[i];
}
 Exemplu de declaraţie cu iniţializare :

int main(void)
{
Stiva ob1(10);
Stiva ob2(ob1);
// Stiva ob2=ob1;

// …
}

68
 Constructori cu conversie de tip
Sunt constructori care au primul parametru de tipul unui
atribut al clasei și dacă există alți parametri, aceștia
trebuie să aibă valori implicite.

class Student{
private: char nume[30];
int anul;
int nr_matricol;
public: Student(const char *n, int an=1, int nr=1234);

};
69
Student::Student(const char *n, int an, int nr) {
strcpy(nume, n);
anul=an;
nr_matricol=nr;
}
int main() {
Student s=“Popescu”;

}
Obs. Constructorul convertește un char * într-un obiect de
tip Student

70
Concluzie: în funcție de tipul argumentelor pasate
constructorilor aceștia pot fi:

1. Constructor implicit: furnizat de compilator, în cazul în


care clasa nu prezintă nici un constructor explicit
2. Constructor explicit vid (fără parametri)
3. Constructor explicit cu parametri
4. Constructor explicit cu unul sau mai mulți (chiar și cu
toți) parametri impliciți
5. Constructor de copiere
6. Constructor cu conversie de tip

71
Alte observații legate de constructori:

 Constructorii pentru obiectele statice globale dintr-un


fișier se execută în ordinea declarațiilor, iar destructorii se
apelează în ordine inversă.
 Dacă se apelează un constructor pentru un obiect static
local, el se va apela după apelul constructorului pentru
obiectele statice globale. Argumentele pentru acești
constructori trebuie să fie expresii constante.

 Execuția lui main() nu e începutul unei aplicații C++,


obiectele statice globale cin, cout, cerr, fiind instanțiate
înainte de main(). Dacă programul se termină prin exit(),
destructorii pentru obiectele statice globale vor fi aplelați
automat. De aceea. prin apelul lui exit() într-un destructor
se poate ajunge la recursivitate infinită. Dacă programul
se termina cu abort() destructorul nu va fi apelat. 72
 Obiectele de memorie liberă se mai numesc obiecte
dinamice. Ele sunt create cu operatorul new și distruse
cu delete. C++ nu oferă garanția că un destructor este
întotdeauna apelat pentru obiectele create cu new.
Neeliminarea unui obiect nu e o eroare, doar pierdere de
memorie, dar ștergerea de două ori a aceluiași obiect
poate să ducă la situații incontrolabile.
Considerând clasa Student definită anterior, putem crea

un obiect dinamic astfel:
Student *sd=new Student(“Moldovan”, 1, 1023);
Obiectul va fi distrus cu delete:
delete sd;

73
EXEMPLE: CONSTRUCTORI EXPLICITI
#include <iostream>
using namespace std;
class C{
int x,y;
public: C(){
cout<<"\nCons. explicit fara param. Atributele x si y nedefinite \n";
cout <<"x = "<< x <<'\n';
cout <<"y= "<< y <<'\n'; }
C(int a){ x=a;
cout<<"\nCons. cu un param explicit; Atributul y nedefinit \n";
cout << "x = "<<x <<'\n';
cout << "y= "<<y << '\n'; }
C(int a, int b){ x=a;
y=b;
cout<<"\nCons. cu doi param. expliciti. Atribute definite \n";
cout <<"x = "<<x <<'\n'; 74
cout <<"y= "<< y <<'\n';
}
void setX(int a) { x=a; }
void setY(int b) { y=b; }

void afis(){
cout<<"Afis. metoda"<<endl;
cout <<"x = "<< x <<'\n';
cout <<"y= "<< y <<'\n'; }
};//C class
int main(){
C ob1(10,20);
ob1.setX(7); ob1.setY(7);
ob1.afis();
C ob2(10);
ob2.afis();
C ob3; //val nedefinita, constr. explicit fara param.
ob3.afis();
ob3.setX(1); ob3.setY(1);
ob3.afis(); cin.get(); 75

}//main
76
CONSTRUCTORI PENTRU ALOCAREA DINAMICA A MEMORIEI
#include<string.h>
#include <iostream>
using namespace std;
const int MaxBufferSize=1023;

class CFieldEdit{
private:
char *buffer;
int bufferSize;
public:
CFieldEdit(int FieldSize);
~CFieldEdit();
int getBufferSize() { return bufferSize; }
char *getBuffer() { return buffer; }
}; //CFieldEdit Class

77
//begin constructor
CFieldEdit::CFieldEdit(int fieldSize){
if (fieldSize>MaxBufferSize)
fieldSize=MaxBufferSize;
//lungimea introdusa poate fi mai mare decat cea maxima prestabilita
//in acest caz se reduce la cea maxima prestabilita
buffer=new char[fieldSize];
bufferSize=fieldSize;
printf("\nAm construit un obiect de tip CFieldEdit");
} //CFieldEdit constr

//begin destructor
CFieldEdit::~CFieldEdit(){
delete [ ] buffer;
printf("\nAm distrus un obiect de tip CFieldEdit");
78
} //~CfieldEdit destructor
int main(){
CFieldEdit *aField;
char *str, c;
aField=new CFieldEdit(500);
str=aField->getBuffer();

cout<<"\nAvem un buffer de "<< aField->getBufferSize()<<" octeti";


cout<<"\nIntroduceti un sir de caractere:";
cin>> str;
cout<< aField->getBuffer();
delete aField;
cin.ignore();
cin.get();
}//main

79
80
COPY-CONSTRUCTOR
#include <iostream>
using namespace std;
class ObiectSimplu {
public:
int valoare;
ObiectSimplu() {
valoare = 0;
}
ObiectSimplu(int v) {
valoare = v;
}
ObiectSimplu(const ObiectSimplu &o) {
valoare = o.valoare;
} //nu e necesar – oferit implicit 81
};//ObiectSimplu Class
class ObiectPointer {
public:
int * valoare;
ObiectPointer() {
valoare=new int;
*valoare = 0;
}
ObiectPointer(int v) {
valoare=new int;
*valoare = v;
}
};// ObiectPointer Class

82
class ObiectPointerCC {
public:
int * valoare;
ObiectPointerCC() {
valoare=new int;
*valoare = 0;
}
ObiectPointerCC(int v) {
valoare=new int;
*valoare = v;
}
ObiectPointerCC(const ObiectPointerCC & o) {
valoare=new int;
*valoare = *o.valoare;
}
83
};// ObiectPointerCC
int main() {
cout<<"Se creaza un obiect simplu a cu valoarea 2.\n";
ObiectSimplu a(2);
cout<<"Se copiaza a in b.\n";
ObiectSimplu b = a;
cout<<"Valoarea lui b este "<< b.valoare<< endl;
cout<<"Se modifica valoarea lui a la 3.\n";
a.valoare = 3;
cout<<"Valoarea lui a este " << a.valoare << endl;
cout<<"Valoarea lui b este « << b.valoare <<endl;
cout<<"\nSe creaza un obiect cu pointer c cu valoarea 10.\n";
ObiectPointer c(10);
cout<<"Se copiaza c in d.\n";
ObiectPointer d = c;
cout<<"Valoarea lui d este " <<*d.valoare <<endl;
84
cout<<"Se modifica valoarea lui c la 13.\n");
*c.valoare = 13;
cout<<"Valoarea lui d este " << *d.valoare << endl;
cout<<"Valoarea lui c este " << *c.valoare << endl;

cout<<"\nSe creaza un obiect cu pointer, cu copy constructor, e cu val 7.\n";


ObiectPointerCC e(7);
cout<<"\n Se copiaza e in f.\n";
ObiectPointerCC f = e;
cout<<"Valoarea lui f este " << *f.valoare << endl;
cout<<"Se modifica valoarea lui e la 8.\n";
*e.valoare = 8;
cout<<"Valoarea lui f este " << *f.valoare << endl;
cout<<"Valoarea lui e este ", << *e.valoare << endl;
cin.get();
return 0;
}
85
86

Вам также может понравиться

  • ASC - Laborator 3
    ASC - Laborator 3
    Документ10 страниц
    ASC - Laborator 3
    Julia Varga
    Оценок пока нет
  • Modulul VI - Ecaterina Lombada I
    Modulul VI - Ecaterina Lombada I
    Документ38 страниц
    Modulul VI - Ecaterina Lombada I
    corneliamarcela
    Оценок пока нет
  • Prob 6
    Prob 6
    Документ4 страницы
    Prob 6
    Julia Varga
    Оценок пока нет
  • Prob 6
    Prob 6
    Документ4 страницы
    Prob 6
    Julia Varga
    Оценок пока нет
  • Educația Reprezintă o Dimensiune Permanetă A PDF
    Educația Reprezintă o Dimensiune Permanetă A PDF
    Документ5 страниц
    Educația Reprezintă o Dimensiune Permanetă A PDF
    Julia Varga
    Оценок пока нет
  • Grafică Asistată de Calculator
    Grafică Asistată de Calculator
    Документ1 страница
    Grafică Asistată de Calculator
    Julia Varga
    Оценок пока нет
  • Educația Reprezintă o Dimensiune Permanetă A
    Educația Reprezintă o Dimensiune Permanetă A
    Документ5 страниц
    Educația Reprezintă o Dimensiune Permanetă A
    Julia Varga
    Оценок пока нет
  • Curs14 Clasa String
    Curs14 Clasa String
    Документ8 страниц
    Curs14 Clasa String
    Sabina Lavinia
    Оценок пока нет
  • Constructori Si Referinte
    Constructori Si Referinte
    Документ12 страниц
    Constructori Si Referinte
    Tudor Domenti
    Оценок пока нет
  • Patrat PDF
    Patrat PDF
    Документ2 страницы
    Patrat PDF
    Julia Varga
    Оценок пока нет
  • Culoare
    Culoare
    Документ3 страницы
    Culoare
    Julia Varga
    Оценок пока нет
  • Circuite RC
    Circuite RC
    Документ3 страницы
    Circuite RC
    Julia Varga
    Оценок пока нет
  • Culoare
    Culoare
    Документ3 страницы
    Culoare
    Julia Varga
    Оценок пока нет
  • Component A
    Component A
    Документ3 страницы
    Component A
    Julia Varga
    Оценок пока нет
  • Delta
    Delta
    Документ4 страницы
    Delta
    Julia Varga
    Оценок пока нет
  • POO Introducere
    POO Introducere
    Документ29 страниц
    POO Introducere
    alexcojocaru72
    Оценок пока нет
  • Curs6 PDF
    Curs6 PDF
    Документ12 страниц
    Curs6 PDF
    andreea3198
    Оценок пока нет
  • Patrat
    Patrat
    Документ2 страницы
    Patrat
    Julia Varga
    Оценок пока нет
  • An1 Sem2 Curs09 Most 18 19 PDF
    An1 Sem2 Curs09 Most 18 19 PDF
    Документ78 страниц
    An1 Sem2 Curs09 Most 18 19 PDF
    Julia Varga
    Оценок пока нет
  • Curs14 Clasa String
    Curs14 Clasa String
    Документ8 страниц
    Curs14 Clasa String
    Sabina Lavinia
    Оценок пока нет
  • Supraincarcarea Operatorilor
    Supraincarcarea Operatorilor
    Документ12 страниц
    Supraincarcarea Operatorilor
    RobertCozianu
    Оценок пока нет
  • Programare Orientata Pe Obiecte
    Programare Orientata Pe Obiecte
    Документ46 страниц
    Programare Orientata Pe Obiecte
    Julia Varga
    Оценок пока нет
  • POO
    POO
    Документ61 страница
    POO
    becheanu13
    100% (1)
  • Siruri de Caractere in C Si C++
    Siruri de Caractere in C Si C++
    Документ9 страниц
    Siruri de Caractere in C Si C++
    emina288
    Оценок пока нет
  • Curs C
    Curs C
    Документ112 страниц
    Curs C
    alexsicoe
    Оценок пока нет
  • Constructori Si Referinte
    Constructori Si Referinte
    Документ12 страниц
    Constructori Si Referinte
    Tudor Domenti
    Оценок пока нет
  • Programare Orientata Obiectcurs1
    Programare Orientata Obiectcurs1
    Документ54 страницы
    Programare Orientata Obiectcurs1
    Manuela Iancu
    Оценок пока нет
  • Modulul VI - Ecaterina Lombada I
    Modulul VI - Ecaterina Lombada I
    Документ38 страниц
    Modulul VI - Ecaterina Lombada I
    corneliamarcela
    Оценок пока нет
  • MI - Modulul VI - Ecaterina Lombada I
    MI - Modulul VI - Ecaterina Lombada I
    Документ51 страница
    MI - Modulul VI - Ecaterina Lombada I
    corneliamarcela
    Оценок пока нет