Explorați Cărți electronice
Categorii
Explorați Cărți audio
Categorii
Explorați Reviste
Categorii
Explorați Documente
Categorii
Obiectul reprezinta un element (entitate) care se constituie atat din structuri de date (atribute,
caracteristici) cat si din operatii (actiuni, comportament). Totodata, un obiect este considerat o instanta a unei clase,
un caz particular a acesteia.
Clasa reprezinta o colectie de obiecte similare care impartasesc aceleasi atribute si acelasi comportament.
Operatia de creare a unui obiect dintr-o clasa se numeste instantiere, de aici rezultand si denumirea de instanta
pentru un obiect creat.
Mesajul reprezinta o functie care confera un comportament unui obiect. Trimiterea unui mesaj este
echivalenta unei cereri adresata unui obiect de a invoca o functie. Mesajele sunt cele care permit comunicarea intre
obiecte.
Incapsularea reprezinta principiul asociat abstractizarii datelor, in sensul ca structura de date utilizata este
ascunsa, fiind furnizata doar o interfata. In POO incapsularea datelor se realizeaza cu ajutorul claselor.
Mostenirea: acea tehnica de programare prin care se pot utiliza si extinde clase deja create, utilizand astfel
codul sursa deja scris. Mecanismul mostenirii permite dezvoltarea de noi clase numite clase derivate (subclase)
din clase de baza (superclase). Avantajul este faptul ca o clasa derivata mosteneste toate atributele si
comportamentele clasei de baza, la care se pot adauga atribute si comportamente proprii.
Polimorfismul indica mai multe comportamente alternative intalnite in clase derivate inrudite. Se
intalneste si sub sintagma “o singura interfata, mai multe metode”, avantajul fiind numarul redus de elemente in
cazul unei interfete comune care permite acces la mai multe actiuni.
Tipul de date struct nu ofera protectie a datelor, ceea ce determina ca tipurile de date introduse prin
structuri sa nu poata fi supuse unor controale ce tin de operatiile executate asupra lor.
Implementarea tipurilor de date abstracte cu protejarea datelor si functiilor au condus la aparitia claselor,
din limbajul C++.
Operatiile de I/O se bazeaza pe conceptul de stream ce reprezinta un model abstract al dispozitivelor de
I/O. Un stream este o secvente de octeti.
Sintaxa operatiei de intrare: cin>>v1>>v2>>...>>vn;
Sintaxa operatiei de iesire: cout<<ei<<e2<<...<<en;
Biblioteca folosita este iostream.h. Aceasta include si 4 stream-uri predefinite:
-cin – stream de intrare conectat la intrarea standard
-cout – stream de iesire conectat la iesirea standar
-cerr – strean de iesire setat pentru o iesire fara buffer catre un dispozitiv standard de eroare
-clog – stream similar cu cerr, dar avand buffer
Alocarea dinamica a memoriei – functiile malloc
Eliberarea memoriei – functia free
In limbajul C++ exista 2 operatori new si delete care joaca acelasi rol de alocare, respectiv dealocare a
memoriei.
Operatorul new returneaza un pointer la zona de memorie alocata dinamic, in caz de insucces returnand
NULL.
Operatorul delete elibereaza zona de memorie indicata de argumentul sau, care este de fapt un pointer
obtinut ca urmare a alocarii cu operatorul new.
Sintaxa generala a operatorului de alocare dinamica a memoriei:
tip * pt_tip;
pt_tip=new tip;
sau direct:
tip * pt_tip=new tip;
unde tip reprezinta un tip de date fundamental, iar pt_tip reprezinta pointerul catre tipul de date dorit.
Sintaxa generala a operatorului de dealocare dinamica a memoriei este:
delete pt_tip;
unde pt_tip reprezinta pointerul catre tipul de date dorit pentru care s-a alocat memorie.
Clasa este un tip de date abstract si contine date membru si functii membru sau metode. Clasele ofera un
nivel superior de protectie atat datelor, cat si functiilor membru, prin incapsularea datelor.
Clase si obiecte
O multime de obiecte ce impartasesc aceleasi atribute si aceleasi comportamente alcatuiesc o clasa.
Obiectele sunt instante ale unei clase care comunica intre ele prin intermediul metodelor (invocate la
primirea unui mesaj).
O metoda reprezinta o functie membru a unei clase. Comportamentul unui obiect reprezinta totalitatea
metodelor care ii pot fi asociate.
Tablouri de obiecte
Tablourile de obiecte reprezinta o colectie de obiecte similare ce apartin aceleiasi clase. In limbajul C++,
tablourile de obiecte pot fi implementate doar daca acea clasa care incluse tabloul de obiecte contine un constructor
implicit. Aceasta restrictie se datoreaza imposibilitatii de a furniza argumentele necesare constructorilor.
Exemplu: Persoana tab[20];
Exemplu de program:
#include<iostream.h> int numar_rational::getNumarator()
class numar_rational {
{ return this->numarator;
int numarator, numitor; }
public: numar_rational(){numarator=0;numitor=1;} void main()
void setare_numar_rational() {
{cout<<”\n Numarator=”; numar_rational tablou[10];
cin>>numarator; int i, n;
cout<<”\n Numitor=”; cout<<”\n Numarul de obiecte ce vor fi create:”;
cin>>numitor; cin>>n;
} for(i=0;i<n;i++)
inline int getNumarator(); tabolou[i].setare_numar_rational();
int getNumitor() cout<<”\n Au fost create urmatoarele obiecte:\n”;
{return this->numitor; for(i=0;i<n;i++)
} tabolou[i].afisare();
void afisare() cout<<”\n Numitorul obiectului tablou[3]
{cout<<numarator<<”/”<<numitor<<”\n”; este:”<<tablou[3].getNumitor();
} }
};
Definirea membrilor statici
In limbajul C++ prefixarea membrilor unei clase cu cuvantul cheie static le confera acestora proprietati
deosebite. Membrii statici nu apartin unui anumit obiect, ci sunt comuni tuturor obiectelor unei clase. Membrii
statici sunt folositi in situatiile in care obiectele unei clase folosesc date in comun, reducandu-se numarul de
variabile globale. Initializarea membrilor statici se face o singura data.
Exemplu:
#include<iostream.h> angajat(char* F, int V, double S){
#include<string.h> functie=new char[strlen(F)+1];
class angajat strcpy(functie, F);
{ char *functie; vechime=V;
int vechime; salariu=S;
double salariu; ++Nr;//s-a creat un obiect din clasa angajat
static int Nr; }
public: angajat(){ static int getNrAngajati();
strcpy(functie, ” ”); double getsalariu(){ return salariu;}
vechime=10; int getvechime(){return vechime;}
salariu=0.0; void setsalariu(double);
} };
int angajat::Nr=0; angajat *A1= new angajat(”inginer”, 15, 2450.57);
int angajat::getNrAngajati(){ return Nr;} angajat *A1=new angajat(” economist”, 25,
angajat::~angajat() 4500.64);
{delete functie; cout<<”\n Numarul de angajati dupa
--Nr; creare:”<<A1-
} >getNrAngajati();
void angajat::setsalariu(double x) delete A1;
{ A1=0;
salariu+=salariu*x/100; delete A2;
cout<<“\n Salariul indexat cu “<<x<<“% A2=0;
este”<<this->salariu; Cout<<”\n Numarul de angajati dupa eliberarea
} spatiului de
void main() memorie:”<<angajat::getNrAngajati();
{ }
cout<<”\n Initial sunt ”<<angajat::getNr()<< ”
angajati”;
Pointeri la metode
Limbajul C++ ofera posibilitatea de a lucra cu pointeri catre membrii unei clase (date sau functii membru),
acestia avand asociate atat tipul membrului, cat si tipul clasei respective. Un pointer catre un membru al unei clase
(data sau functie) nu este asociat unui anumit obiect, ci clasei. Preluarea adresei unui membru se face cu ajutorul
operatorului de adresa &, precizandu-se identitatea membrului.
Sintaxa definirii unui pointer la o functie membru:
NumeClasa::*;
PointerMembru=&NumeClasa::Membru
Dupa preluarea adresei, accesarea membrului respectiv se face astfel:
NumeObiect.*PointerMembru
PointerObiect->*PointerMembru
Supraincarcarea operatorilor
Redefinirea operatorilor
Limbajul C++ preia operatorii din limbajul C, dar utilizeaza si operatori noi precum operatorii de alocare,
respectiv dealocarea spatiului memoriei (new si delete). Pentru a extinde orizontul de utilizare a operatorilor a
aparut mecanismul de redefinire a operatorilor, care permite definirea propriilor functii asociate operatorilor, pe
care compilatorul sa le apeleze atunci cand intalneste acei operatori redefiniti.
Sintaxa redefinirii unui operator: operator simbol_operator
Pot exista mai multe redefiniri ale unui operator, dar ele trebuie sa aiba argumente diferite, pentru a putea
fi posibila diferentierea lor de catre compilator.
Exista doua modalitati de redefinire a operatorilor:
-prin functii membru ale clasei respective
-prin functii friend ale clasei respective
Mostenirea
Mostenirea este o modalitate de reutilizare a codului si este folosita pentru extinderea claselor deja create.
Mecanismul mostenirii presupune definirea unei clase noi, numita clasa derivata sau subclasa dintr-o clasa
existenta numita clasa de baza sau superclasa.
Clasa derivata mosteneste (preia) toate caracteristicile clasei de baza si poate adauga alte caracteristici noi,
specifice.
Sintaxa declararii unei clase derivate:
Class NumeClasaDerivata: ModificatorAcces NumeClasaBaza
{
// membrii clasei derivate
}
Exemplu:
class Angajat: public Persoana
{ float salariu;
public:
Angajat(char*, char*,int, float);
void afisare();
float getSalariu();
};
Observatii:
-modificatorul de acces determină modul în care elementele clasei de bază sunt moştenite în clasa derivată.
Exemplu:
o în cazul în care modificatorul de acces este public, toţi membrii publici din clasa de bază rămân
membri publici în clasa derivate.
o când modificatorul de acces este private, atunci toţi membrii publici din clasa de bază devin
membri privaţi în clasa derivată.
-la moştenire, membrii privaţi din clasa de bază nu sunt accesibili claselor derivate decât prin intermediul
funcţiilor membru moştenite din clasa de bază.
-pentru a avea acces direct la membrii clasei derivate, aceştia se pot declara în secţiunea protected.
-funcţiile friend nu se moştenesc.
Ierarhii de clase
Functii virtuale
Funcţiile virtuale sunt identificate cu ajutorul cuvântului cheie virtual şi au următoarea sintaxă:
virtual tip nume_functie(lista parametri);
Caracteristici:
o Funcţiile nemembre, funcţiile membre statice şi cele inline nu pot fi declarate funcţii virtuale;
o Dacă o funcţie este declarată virtuală în clasa de bază, ea trebuie redefinită în clasele derivate din clasa de bază
respectivă;
o Funcţiile declarate virtuale în clasa de bază şi redefinite cu acelaşi prototip în clasele derivate sunt automat
identificate ca fiind virtuale, astfel încât specificatorul virtual poate lipsi;
o Constructorii nu pot fi funcţii virtuale, în schimb destructorii pot fi.
Clase abstracte
O funcţie virtuală care este doar declarată, nu şi definită, iar iniţializarea ei se face cu valoarea 0 este o
funcţie virtuală pură. Compilatorul este înştiinţat astfel că acea funcţie din clasa de bază nu are corp (fiind
iniţializată cu 0), şi prin urmare nu se pot crea obiecte din acea clasă de bază. O clasă care conţine o funcţie
virtuală pură este o clasă abstractă şi, neavând instanţieri (obiecte) nu este proiectată pentru crearea obiectelor,
fiind o clasă generică. Din clasa abstractă se pot deriva clase noi care vor redefini funcţia virtuală pură existentă în
clasa de bază. Clasele abstracte sunt folosite pentru crearea ierarhiilor de clase, având un grad sporit de
generalitate, permiţând astfel definirea de caracteristici comune pentru întreaga familie de clase.
Sintaxa declarării unei funcţii virtuale pure:
class NumeClasaAbstracta
{
public: NumeClasaAbstracta()
{ //…
}
virtual tip nume_functie_pura()=0;
};
Exemplu:
#include<iostream.h> {
class Figura_geometrica class Triunghi : public Forma_geometrica{
{ public: double aria()
private: double dim1, dim2; {
public: void init_dimensiuni(double x1, double x2) double d1, d2;
{ actualizareDim(d1, d2);
dim1 = x1; dim2 = x2; return 0.5*d1*d2;
} }
virtual double aria()=0; //Functie care trebuie };
redefinita in clasele derivate void main()
void actualizareDim(double &x1, double &x2) {
{ Forma_geometrica *ptr;
x1 = dim1; x2 = dim2; Dreptunghi Ob1;
} Triunghi ob2;
}; Ob1.init_dimensiuni(2.5, 1.5);
class Dreptunghi : public Forma_geometrica Ob2.init_dimensiuni(3.5, 7.5);
public: double aria() ptr = &Ob1;
{ cout << "\n Aria dreptunghiului este: " << ptr-
double d1, d2; >aria();
actualizareDim(d1, d2); ptr = &Ob1;
return d1*d2; cout << "\n Aria triunghiului este:" << ptr->aria();
} }
};
Observatii:
-o clasă abstractă nu poate fi transferată prin valoare şi nu poate fi returnată de către o funcţie.
-o modalitate de transfer este prin intermediul pointerilor şi a referinţelor, dar numai pentru a putea fi
posibilă implementarea polimorfismului.