Sunteți pe pagina 1din 22

ELEMENTE FUNDAMENTALE ALE POO

Conceptele fundamentale ale POO sunt noiunile de clas i obiect precum i relaiile dintre
clase, obiecte i dintre clase i obiecte.
Obiectul este o entitate dinamic, caracterizat prin:
-stare
-comportament
-identitate
Starea unui obiect semnific temporalitatea lui. El poate fi creat i distrus n timp de alt obiect
sau de utilizator. Starea obiectului este caracterizat de atribute care au
nume asociat
-valori asociate
Comportarea unui obiect exprim metoda (modalitatea) de rspuns a sa la mesaje (aciuni)
provenite din exterior, care determin schimbarea strii sale.
Identitatea este proprietatea care distinge un obiect de alte obiecte. Ea se pstreaz i dup ce
obiectul a fost supus unor transformri sau i-a modificat starea iniial.
Obiectele cu stari i comportari asemanatoare se grupeaz n clase.
O clas abstractizeaz proprietile comune ale unui set de obiecte, asfel ca fiecare obiect este
o instan (reprezentant sau individ) a unei clase. O clas poate avea nici unul, unul sau mai
multe obiecte instan. Clasa este o entitate static i nu dinamic precum obiectul, deoarece
dup specificare i implementare se modific foarte greu.
Relaiile stabilesc conexiunile logice dintre diferite entiti.
Relaiile obiect-obiect sunt
de utilizare-ntre obiecte ce schimba mesaje ntre ele
de coninere-obiecte complexe care conin alte obiecte
Relatia obiect clas este cea de instaniere.
Relaiile clas clas pot fi
mostenite
de asociere n utilizari
de coninere (agregare)
Paradigmele POO sunt:

abstractizarea
incapsularea
motenirea
polimorfismul

Abstractizarea reprezint procesul de ignorare intentionata a detaliilor nesemnificative i


retinerea proprietilor definitorii ale unei entiti. Ea poate fi: -procedural
-a datelor
Abstractizarea procedural ignor detaliile privitoare la desfasurare proceselor. Este specific
programarii procedurale n care datele de I/E i funciile sunt distincte i folosite separat
(exemplu C++ permite programare procedural).
Abstractizarea datelor ignor detalii privind reprezentarea unui tip de date . n POO pentru
entiti de nivel inalt cele 2 abstractizari sunt combinate n cadrul claselor.
Incapsularea (ascunderea informaiilor) implementeaz abstraciile prin clase. Ea separ
informaiile de manipulare a unei entiti de informaiile de implementare.
Incapsularea informaiei la nivel de tip se face prin mprirea unei clase n 2 seciuni
distincte: interfa i implementare.
Interfaa unei clase, transmisa tuturor obiectelor instan ale clasei respective, permite accesul
la clasa din exterior al potenialilor utilizatori.

Implementarea clasei, care cuprinde reprezentarea abstraciei i algoritmii metodelor de


interfa, nu este cunoscut i accesibil utilizatorilor.
Motenirea permite clasificarea tipurilor prin organizarea lor n ierarhii. n funcie de poziia
ocupata n ierarhie, un tip poate fi: -generalizarea altor tipuri , sau
-specificarea altor tipuri.
Astfel, o clas este clas de baz sau superclas sau supertip pentru toate clasele care o
specializeaz i clas derivat sau subclas sau subtip pentru toate clasele pe care le
specializeaz. O clas derivat preia de la clasa de baz toate caracteristicile acesteia, la care
se mai pot aduga i altele noi.
Polimorfismul permite unei valori de a avea mai multe tipuri. n C + + polimorfismul este:
- parametric
- ad-hoc
- de motenire
Polimorfismul parametric apare cnd aplicam o funcie pe argumente de tipuri diferite.
Polimorfismul ad-hoc permite suprancarcarea funciilor (implementrii diferite), redefinirea
metodelor unei clase de baz prin redefinirea i suprancarcarea lor n clase derivate.
Polimorfismul de motenire permite manipularea obiectelor de un anumit tip n situaii ce
necesit tipuri diferite de cele ale obiectelor.
Declararea claselor
Clasa este un tip de date abstracte definit de utilizator, care se comport ca un tip predefinit.
O clas C + + incapsuleaz datele membre, ce reprezint atributele clasei precum i funcii
membre (sau metode) care efectueaz operaii asupra datelor clasei.
Clasa are un nume ce poate fi orice identificator, unic n domeniul respectiv de existen.
Declararea unei clase folosete cuvntul cheie class i are sintaxa:
class nume_clasa
{
[private:
<date membre private>
<constructori privai>
<funcii membre private>]
[protected:
<date membre protejate>
<constructori protejai>
<funcii membre protejate>]
[public:
<date membre publice>
<constructori publici>
<destructor public>
<funcii membre publice>]
};
C + + asigur o limitare a accesului la membrii unei clase i de aceea n declararea unei clase
folosim specificatori de control ai accesului: private, protected i public.

Specificatorul private precizeaz membrii proprii ai clasei. Ei pot fi accesai de orice funcie,
membr a clasei. Instanele clasei nu au acces la membrii privai.
Specificatorul protected precizeaz membrii protejai care pot fi accesai nu numai de funcii
membre ale clasei, ci i de funcii membre ale claselor derivate din clasa respectiv.
Specificatorul public precizeaz membrii publici care pot fi accesai de orice funcie din
domeniul declaraiei clasei (funcii membre i instane).
Implicit membrii unei clase au atributul de acces privat. Dac sunt prezeni, specificatorii de
acces pot fi n orice ordine i se pot chiar repeta.
O funcie membru a unei clase are acces la toate datele membre ale oricrui obiect din clasa
respectiv, indiferent de specificatorul de acces. Se recomand plasarea datelor membre n
seciunea protejat pentru a facilita accesul la ele de catre toate funciile membre ale claselor
derivate. n declaraia unei clase pot aprea numai prototipurile funciilor membre. Definirea
lor poate fi inclus n acelai fiier sau n fiiere separate n cadrul bibliotecilor de programe.
Funciile definite n cadrul clasei fac implicit parte din categoria inline.
Pentru a defini o funcie membru aflat n afara declaraiei clasei folosim operatorul de
rezoluie :: conform sintaxei:
nume_clasa :: nume_funcie
unde nume_clasa este numele clasei din care face parte funcia.
Operatorul de rezoluie :: spune ca funcia are acelai domeniu cu declararea clasei i este
membr a clasei.
Dup declararea unei clase, numele ei poate fi folosit ca identificator de tip pentru a declara
instane ale clasei, cu o sintax asemanatoare cu cea de la declararea variabilelor.
Exemplu: Clasa coordonate incapsuleaz 2 date membre x,y i 2 funcii membre(translatare
i tiprire).Cele 2 date membre sunt coordonatele unui punct din plan. Funcia translatare ( )
translateaz coordonatele punctului considerat cu a respectiv b, iar funcia tiprire() afieaz
coordonatele punctului.
# include<iostream.h>
class coordonate
{
private:
float x,y;
public :
void translatare (float a, float b);
void tiprire ();
};
void coordonate :: traslatare(float a, float b)
{
x + = a;
y + = b;
}
void coordonate :: tiprire ()
{
cout << Coordonatele punctului sunt: x = << x << i y = << y << endl ;
{
class coordonate M , N ;
aici se declar dou obiecte de tip coordonate.
Definirea funciilor membre translatare () i tiprire () este fcut n afara declararii clasei
coordonate creia i aparin.
Putem opera cu obiectele dintr-o clas ca i cu orice tipuri de date predefinite.

Exemplu:
coordonate pct1, pct2;
coordonate *p;
coordonate ir [10] ;
pct1 = pct2 ;
*p =ir ;

declar 2 obiecte
declar un pointer la obiect
declar un ir de 10 obiecte
atribuiri

Putem accesa orice membru public prin operatorul .. Membrii privai nu pot fi accesai
dect de funcii membre ale clasei. Putem atribui o valoare unei date membre private numai
printr-o funcie membr a clasei, care poate testa validitatea respectivei valori.
Exemplu : Program ce declar clasa angajat care include 2 funcii membre publice i 4 date
membre private. Funcia valori () iniializeaz datele private ale clasei i folosete
instruciunea if pentru a asigura lui salariu o valoare corect. Funcia de afisare () afieaz
datele membre private. Funciile sunt accesate prin operatorul ..
# include <iostream.h>
#include <conio.h>
#include <string.h>
class angajat
{
public:
int valori (char*, int, long, float);
void afisare (void) ;
private :
char nume [50] ;
int varsta ;
long marca ;
float salariu ;
};
int angajat :: valori (char*ang_nume, int ang_varsta, long ang_marca, float ang_salariu)
{
strcpy(nume,ang_nume);
varsta = ang_varsta;
marca = ang_marca;
if ( ang_salariu < 3000000)
{salariu =ang_salariu;
return (0);
}
else return (1);
}
void angajat :: afisare (void)
{
cout <<Nume: <<nume<<endl;
cout << Varsta : <<varsta<<endl ;
cout << Marca :<<marca<<endl ;
cout <<Salariu :<<salariu<<endl ;
}

void main (void)


{
clrsc() ;
angajat lucrator ;
if (lucrator.valori(Popescu ,55,1313,2000000) = = 0)
{
cout <<Date angajat :<<endl ;
lucrator.afisare () ;
}else cout <<Valoarea salariului este incorecta ;
}
Observaia 1 : Dup compilare i rulare apare pe ecran :
Date angajat :
Nume :Popescu
Varsta :55
Marca :1313
Salariu :2000000
Observaia 2 :Este posibil ca anumite clase s conin funcii membre private. Ele nu pot fi
apelate de program prin operatorul . , ci doar de ali membri ai claselor de care aparin.
Funcii membre inline
Definirea unei funcii membru n interiorul unei clase este considerat inline.
Exemplu :Aici se declar clasa coordonate de mai sus n care funcia translatare nu este doar
declarat ci i definit ; ea devine implicit funcie inline. Ca urmare, la fiecare apel, ea nu este
doar apelat ci expandat. Definirea unei funcii ntr-o clas se numete i declarare inline
implicit. Funcia membru tiprire este doar declarat n cadrul clasei. Definirea ei n afara
declaraiei clasei este prefixat de cuvntul cheie inline. Acest fapt este echivalent cu
definirea funciei n cadrul declaraiei clasei al crei membru este. Acestea este o declaraie
inline explicit.
# include <iostream.h>
class coordonate
{
float x,y;
void translatare (float a, float b)
{
x + = a;
y + = b;
}
void tiprire () ;
};
inline void coordonate :: tiprire ()
{
cout << Coordonatele punctului sunt : x = <<x<< i y = <<y<< endl ;
}
Observaie : Este interzis folosirea n funciile inline a instruciunilor repetitive

for
while
do-while

Deoarece compilatorul are nevoie de ntreaga definiie a unei funcii inline, funcia nu poate fi
folosit dect n fiierul n care a fost definit.
Constructori
Constructorul este o funcie membru special a unei clase, care are acelai nume cu clasa
creia i aparine. El servete la crearea i iniializarea obiectelor i de aceea este apelat
implicit de fiecare dat cnd se creaz noi instanieri ale clasei.
Declarare i caracteristici
ntr-o clas pot exista nici unul, unul sau mai multi constructori. Dac nu este nici un
constructor, compilatorul genereaz automat unul care este public, fr argumente i cu o list
vid de instruciuni.
O funcie constructor nu ntoarce un tip de date, deci n corpul ei nu trebuie folosit return. Se
declar un constructor prin :
class nume_clasa
{
public:
nume_clasa ();
constructor prestabilit fr
argumente
nume_clasa (nume_clasa & c);
constructor de copiere
nume_clasa ( argumente);
constructorii cu argumente
};

La declararea i la definirea unei funcii constructor tipul void nu poate fi specificat ca tip
returnat.
Constructorii pot avea argumente (inclusiv din cei implicii) i pot fi supradefinii. Pointeri
catre constructori nu se pot folosi, deci adresa lor nu ne este accesibi.
ntr-un constructor putem folosi operatorii new i delete.
Un constructor prestabilit nu are argumente sau are o list de argumente n care toi argumente
folosesc argumente prestabilite.
Ex.1:

clasa coordonate
{
protected:
float x,y;
public:
coordonate( );
coordonate(coordonate&c);
coordonate(float a, float b);
........ alte funcii......
};
Ex.2: Program care creeaz clasa angajat ce conine funcia constructor angajat. Acesta se
definete ca orice funcie membr a clasei i atribuie valori iniiale la trei obiecte lucr1, lucr2
i lucr3 fr a ntoarce vreo valoare.
# include <iostream.h>
# include <conio.h>
# include <string.h>
class angajat
{
public:
declararea funciei constructor angajat
angajat(char*, int, long, float);
void afisare (void);
private :
char nume [50];
int varsta;
long marca;
float salariu;
};
definirea funciei constructor angajat
angajat :: angajat(char*nume, int varsta,
long marca, float salariu);
{
strcpy (angajat::nume,nume);
angajat :: varsta = varsta;
angajat :: marca = marca;
if (salariu <3000000.0)
angajat :: salariu =salariu;
else
angajat :: salariu = 0.0;
}

definirea funciei membru afiare

void angajat :: afisare (void)


{
cout << endl;
cout << Nume: << nume <<endl;
cout << Varsta: << varsta <<endl;
cout << Marca << marca <<endl;
cout << Salariu: <<salariu <<endl;
}
void main (void )
{
clrscr( );
angajat lucr1 (M. Pop,50, 1313, 2000000.0);
angajat lucr2 (A. Pop,17, 1713, 3000000.0);
angajat lucr3 (Marian P., 43, 1317, 3200000.0);
cout <<Date angajati: << endl;
lucr1.afisare( );
lucr2.afisare( );
lucr3.afisare( );
}
Dup compilare i rulare pe ecran se vor afia datele:

Date angajati:
Nume: M.Pop
Varsta: 50
Marca: 1313
Salariu: 2000000.0
Nume: A. Pop
Varsta: 17
Marca:1713
Salariu: 3000000.0
Nume : Marian P.
Varsta: 43
Marca 1317
Salariu 3200000.0
Dac nu precizm valori pentru toate argumentele, funcia constructor, ca orice funcie,
folosete valori implicite.

Supradefinirea constructorilor
O funcie constructor se supradefinete ca orice alt funcie prin specificarea unor
funcii alternative care corespund unor tipuri diferite de argumente.
Spre exemplu n programul de mai sus putem da o a doua definire a funciei constructor
angajat naintea definirii funciei membr afiare care solicit utilizatorului s introduc o
valoare a argumentului salariu dac aceasta nu este precizat n program, n timp ce prima
definire implic specificarea n program a valorilor celor 4 argumente: nume, varsta, marca,
salariu.

A doua definire are forma:


angajat :: angajat (char* nume, int varsta, long marca)
{
strcpy (angajat :: nume,nume)
angajat :: varsta = varsta;
angajat :: marca=marca;
do{
cout <<Introdu un salariu pt. << nume << mai mic dect 3000000.0;
cin >> angajat :: salariu;
}
while (salariu>= 3000000.0)
}
n programul principal totul este identic ca mai sus, afar de lucr3, unde instruciunea
este:
angajat lucr3 (Marian P., 43, 1317);
La compilare i rulare se cere introducerea unei valori pentru salariul lucrtorului 3 dup
care execuia continua cu afiarea datelor pentru cei trei angajai.
Constructor de copiere
Acest constructor se folosete n C + + pentru a declara un obiect de tip clas i pentru a
transfera un obiect ca argument sau ca rezultat al unei funcii nsoite de o atribuire
respectiv de iniializarea obiectului cu datele altui obiect de acelai tip.
Dac un astfel de constructor de copiere nu este declarat ntr-o anumit clas, compilatorul
genereaz automat unul care iniializeaz datele unui nou obiect cu valorile
corespunztoare dintr-un obiect specificat prin copiere membru cu membru ca la
atribuirea standard.
Pentru a declara un constructor de copiere pentru clasa nume_clasa trebuie s specificm
un argument unic de tip referin la un obiect de acelai tip nume_clasa sub forma:
nume_clasa (const nume_clasa & nume_obiect);
unde modificatorul const asigur c obiectul de intrare nu poate fi modificat.
Constructorul de copiere acioneaz ca orice apel de funcie obinuit.
Exemplu: Aici clasa dublet conine declaraiile unui constructor prestabilit i a unuia de
copiere care este apelat de trei ori:

Un constructor de copiere poate promova mai multe argumente, dar cele suplimentare
trebuie s fie cu valoare implicit pentru a permite copierea automata a obiectelor la apelul
funciei sau la ntoarcerea din funcie.
Constructorul de copiere generat implicit de compilator copiaz doar datele membre n cazul
unor structuri dinamice i de aceea se recomand declararea de utilizator a constructorului de
copiere pentru clasele care se refer la acest tip de structuri de date.
Destructori

Destructorii sunt funcii speciale ale unei clase cu efect complementar


constructorului. Ele sunt automat aplelate pentru distrugerea obiectelor unei
clase la sfritul programului.
Destructorii au acelai nume cu cel al clasei de care aparin, precedati ns de caracterul ~.
Fiecare clas are cel mult un destructor. Dac acesta lipsete, compilatorul genereaz automat
unul cu efect nul.
Funciile destructor nu primesc argumente. Se declar sub forma:
class nume_clasa
{
public:
nume_clasa( )
................
~ nume_clasa( )
. . . . . . . . . .. . . . . .

constructor prestabilit
ali constructori
destructor
alte funcii membre

};
Funcia destructor nu ntoarce nici un tip de date, nici chiar tipul void. Destructorii sunt utili
mai ales pentru obiectele create prin alocarea dinamic a memoriei.
Exemplu :

Un program ce are clasa angajat n care este definit destructorul ~angajat.

# include <iostream.h>
# include <conio.h>
# include <string.h>
class angajat
{
public:
declararea funciei constructor
angajat(char*, int, long, float)
~angajat( );
declararea funciei destructor
void afisare (void);
fct. membru
private:
char nume [50];
int varsta;
long marca;
float salariu; definireafuncieiconstructor
angajat :: angajat (char* nume, int varsta,
long marca, float salariu)
{
strcpy(angajat :: nume,nume);
angajat :: varsta = varsta;
angajat :: marca = marca;
angajat :: salariu =salariu;
}

angajat :: ~angajat( )
definire funciei
{
destructor
cout<<Se distruge obiectul pentru angajatul
<<nume<<endl;
}
void angajat :: afisare(void) definirea funciei
{
membru
cout<<Nume:<<nume<<endl;
cout<<Varsta:<<varsta<<endl;
cout<<Marca:<<marca<<endl;
cout<<Salariu<<salariu<<endl;
}
void main ( )
{
clrscr( );
angajat lucr(B.Pop,90,2051,2000000.0);
cout<<Date angajat:<<endl;
lucr.afisare( );
}

Dup compilare i rulare pe ecran apare:


Date angajat:
Nume: B. Pop
Varsta: 90

10

Marca: 2051
Salariu: 2000000.0
Se distruge obiectul pentru angajatul B.Pop

Membri statici ai unei clase

Datele i funciile unei clase declarate cu cuvntul cheie static se numesc membri statici.

Date membre statice


Fiecare obiect dintr-o clas are o mulime de date membre. Cele nestatice exist n
copii distincte n fiecare obiect ce le conine. Cele statice exist ntr-o singura copie comun
tuturor obiectelor ce le conin, deci unei date membre statice i se rezerv o singur zon de
memorie comun tuturor instanelor clasei. Acestea se declar n cadrul clasei sub forma:
private ;
public;
static tip nume_data;
Dup declararea clasei orice dat membru static trebuie declarat ca variabil global n
exteriorul clasei sub forma:
tip_data nume_clasa::nume_data_membru;
Obligatoriu datele membre statice trebuie iniializate n afara declaraiei clasei.
Datele membre statice exist separat de obiectele clasei, dar orice modificare a unei date
membre este sesizat de toate obiectele clasei ce o conin.
Datele membere statice pot fi accesate nainte de crearea obiectelor clasei. Accesarea
lor din interiorul funciilor membre ale clasei respective se face la fel ca i pentru datele
membre nestatice.
Exemplu :
Program ce are clasa stoc n care membrul pret este declarat static. El este
acelai pentru cele dou obiecte ale clasei prim i secund. Modificarea valorii membrului pret
afecteaz instanele celor dou obiecte. Valorile celorlalte date membre ale obiectelor nu se
modific.
# include <iostream.h>
# include <string.h>
# include <conio.h>
class stoc
{
private :
declararea membrului
static int pret;
static
pret

char denumire[50];
char producator[50];
int cantitate;
public:
stoc(char*, char*, int);
void afisare ( );
void val (int);
};
declararea membrului static pret ca

int stoc :: pret;


variabil global
void stoc :: val (int prt)
{
pret = prt;
iniializarea membrului static
}
stoc :: stoc (char* den, char* prod,
int cant);
{
strcpy (stoc :: den, denumire);
strcpy (stoc :: prod, producator);
stoc :: cant = cantitate;
}
void stoc :: afisare ( )
{
cout<<Denumire:<<denumire<<endl;
cout<<Producator:<<producator<<endl;
11

cout<<Cantitate:<<cantitate<<buc<<en prim.val(100);
dl;
cout<<Oferta iniial:<<endl;
cout<<Pret unitar:<<pret<<u.m.<<endl; prim.afisare( );
}
secund.afisare( );
void main ( )
cout<<endl<<Oferta finala:<<endl;
{
prim.val(90);
clrscr ( );
prim.afisare( );
stoc prim (Produs1, Firma A, 200);
secund.afisare( );
stoc secund (Produs2, Firma B, 300);
}
Dup rulare pe ecran apar afiate: Oferta iniial:
Denumire: Produs1
Producator: Firma A
Cantitate: 200 buc.
Pret unitar: 100 u.m.
Denumire: Produs2
Producator: Firma B
Cantitate: 300 buc.
Pret unitar: 100 u.m.
Oferta finala:
Denumire: Produs1
Producator: Firma A
Cantitate: 200 buc.
Pret unitar: 90 u.m.
Denumire: Produs2
Producator: Firma B
Cantitate: 300 buc.
Pret unitar: 90 u.m.
Orice dat membru declarat ca public i static se poate folosi n program chiar dac
n program nu exist nici un obiect al clasei.
Pentru accesarea unui astfel de membru se folosete operatorul de rezoluie global
sub forma:
nume_clasa :: nume_membru
Ex:
# include<iostream.h>
int stoc :: pret;
declararea membrului stoc pret ca
# include<conio.h>
void main ( )
variabil global
class stoc
{
{
clrscr ( );
public:
stoc :: pret = 100;
static int pret;
cout<<Pretul unitar iniial a fost:<<stoc :: pret <<
private:
u.m.<<endl;
char denumire [50];
stoc :: pret = 90;
char producator [50];
cout<<Pret unitar final este:<<stoc :: pret<<u.m;
int cantitate;
}
};
Aici se acceseaz membrul pret al clasei stoc fr s existe un obiect al clasei stoc.
Observaie: Prin folosirea datelor membre statice:
- reducem numarul variabilelor globale din program;
- urmrim numarul instanelor unei clase;
- controlm accesul;
- alocm un bloc de memorie special pentru diferite obiecte ale unei clase.

12

Funcii membre statice


Putem defini funcii membre statice ca i date membre statice. Ele fac operaii care nu sunt
asociate unor obiecte individuale, ci asociate ntregii clase care le conin.
O funcie membru static i public poate fi apelat i cnd nu exist nici un obiect al
clasei respective.
Pentru apelare folosim operatorul de rezoluie global ::.
Aceste funcii nu primesc implicit adresa unui obiect.
Spre deosebire de funciile membre nestatice ale unei clase, cele statice nu au pointerul
this, deci ele nu pot accesa direct dect alte elemente statice ale clasei respective (nu pot
accesa elementele nestatice ale clasei!).
Se definesc ca funcii membre statice ntr-o clas acele funcii de uz general care sunt
folosite de mai multe clase, evitnd definirea lor ca funcii de sine statatoare.
Ex.1:
class clasa
{
private:
static int i;
..........
public:
declararea funciei membre statice
static void f(int);
..........
};
definirea datei membre statice
int clasa :: i=5;
void clasa :: f(int i)
{
definirea funciei membre statice
ii;
accesarea direct a unui membru static

...........

Ex.2:
class cls
{
public:
int vect [15];
static int prim ( );
};
int cls :: prim ( )
{
return vect [0];
}
n acest caz compilatorul va semnala
eroare la ncercarea funciei membr static
prim de a accesa membrul nestatic vect.

Funcii prietene

C + + permite accesul la datele membre private ale unei clase nu numai funciilor membre ale
clasei respective, ci i altor funcii membre clasei numite funcii prietene. Ele pot fi
independente sau membre altei clase.
Declararea unei funcii prietene independente se face n interiorul clasei precednd
prototipul funciei de cuvntul cheie friend astfel:
class nume_clasa
{
public:
friend tip_rez nume_fct (<argumente>);
Indiferent de poziia prototipului, funciile prietene sunt publice . O astfel de funcie nu poate
ntoarce o referin la clasa prieten.
O funcie prieten poate accesa membri privai ai clasei direct prin operatorul ..

13

Ex.: Programul declar calsa comp i n ea funcia prieten independent: coincid(), care
ntoarce o valoare nenul dac punctele primite ca argumente sunt identice i nul n caz
contrar.
# include <iostream.h>
# include <conio.h>
class comp
{
int x,y;
public:
declararea constructorlui
comp (int,int);
~ comp ( );
declararea
destructorului

void afisare ( );
decl. funciei membru
friend int coincid (comp&, comp&);
}; declararea funciei prietene independente
comp::comp(int a,int b)
{x=a; y=b;afisare( );
definirea
.
constructorului
}
comp::~comp( )
definirea destructorului
{}

void comp::afisare ( )
definirea funciei
{
membru
cout <<x=<<x<<;y=<<y<<endl;
}
definirea funciei prietene

int coincid (comp & p1,comp & p2)


{
if (p1.x == p2.x && p1.y == p2.y)
return 1;
else return 0;
}
void main ( )
{
clrscr ( );
cout <<coordonatele punctului p1 sunt:;
comp p1(2,3);
cout <<coordonatele punctului p2 sunt:;
comp p2(2,4);
cout <<rezultat:<<endl;
if (coincid(p1,p2))
cout <<Punctele p1 i p2 coincid:<<endl;
else cout<<Punctele p1 i p2 sunt diferite;
}

Dup rulare pe ecarn apare:


coordonatele punctului p1 sunt: x=2; y=3
coordonatele punctului p2 sunt: x=2; y=4
Rezultat:
Punctele p1 i p2 sunt diferite.
O funcie prieten poate opera asupra unui obiect transferat ca argument. Ea folosete
numele obiectului i un operator de rezoluie pentru a referi date sau funcii membre ale
clasei.
Dac un program conine o funcie membr a unei clase care este prieten altei clase se
impun:
- declararea corespunztoare a funciilor prietene
- o anumit ordine n definiia claselor.
Declararea funciilor prietene ce aparin unei clase se face sub forma:
class nume_cls2
{
public:
.........

14

unde

friend nume_cls1 :: nume_fct (<argumente>);


}
nume_cls1= numele clasei n care este funcia
nume_cls2 = numele clasei cu care funcia este prieten.

Definiiila celor dou clase trebuie s respecte o ordine prestabilit. Pentru aceasta
trebuie specificat un identificator nume_cls1 sub forma: class nume_cls1. Se definete apoi
clasa nume_cls2. ntre acestea se d compilatorului indicaia privind o revenire ulterioar la
definirea clasei nume_clas1. Altfel definiia clasei nume_cls2 ar face referire la clasa
nume_cls1, nerecunoscut pentru compilator i aceasta ar da eroare.
Exemplu: Aici funcia f( ) clasei A i este prieten clasei B
class A;
class B
{

class A
{

definirea incompleta a clasei A


definirea clasei B

definirea clasei A

..........

..........

friend void B :: f(A, . . . . );


};
void B :: f(A obiect-A, . . . . )
{
...........
definirea funciei prietene
}

void f(A, . . . . )
...........
};

Folosirea funciilor prietene:


-

reprezint o metod de control a accesului la membrii unei clase


ofer o metod simpla de acces limitat din anumite funcii la datele unei clase
funcia care n lista de argumente are cel puin dou argumente din aceeai clas i
care acceseaz argumente privai nu poate fi dect prieten.

Clase prietene
Clasa B este prieten clasei A dac toate funciile membre clasei B pot accesa direct
membri privai ai clasei A.
Pentru a defini clasa B prieten clasei A se introduce ntre membri publici ai clasei A o
instruciune care s conin cuvntul friend urmat de numele clasei B sub forma:
class B;
class A
{
public:
..........
Relatia friend nu este nici reflexiv, nici
friend class B;
tranzitiv.
..........
De regul clasele prietene n C + + sunt
};
independente, n sensul ca nici o clas nu
class B
mostenete membrii celeilalte clase.
{. . . . . . . . };
Exemplu: Aici clasa specificare este prieten clasei material. Programul modific una din
caracteristicile unui material i anume funcie modif( ) a clasei specificare modific data
membr cant care reprezint cantitatea disponibila a materialului. Obiectul material este
15

transmis funciei modif( ) prin adres. Pentru a accesa membrul respectiv funcia folosete un
pointer.
# include <iostream.h>
# include <string.h>
# include <conio.h>
class specificare;
class material
{
public:
material(char*, char*, char*);
void afisare(void);
friend specificare;
}
void material :: afisare(void)
{
cout<<Denumire:<<den<<endl;
cout<<Producator:<<prod<<endl;
cout<<Cantitate:<<cant<<endl;
}
class specificare
{
public:
void modif(material*, char*);
char* atrib(material);
};
void specificare ::modif(material*
material1, char* cant1)
{
strcpy(material1 cant, cant1);
}

private:
char den [30];
char prod [30];
char cant [20];
};
material :: (char* den, char* prod, char*cant)
{
strcpy(material :: den, den);
strcpy(material :: prod, prod);
strcpy(material :: cant, cant);
char* specificare :: atrib(material material1)
{
static char cant [20];
strcpy (cant, material1.cant);
return (cant);
}
void main ( )
{
clrscr( );
cout<<Situaia iniial:<<endl;
material car(Inox,Cos Pitesti,5t);
specificare actual;
car.afisare ( );
actual.modif(&car,3t);
cout<<endl<<Situaia actuala:<<endl;
car. afisare ( );
}

Dup compilare i rulare pe ecran apare:


Situaia iniial:
Denumire: Inox
Producator: Cos Pitesti
Cantitate: 5t
Situaia actuala:
Denumire: Inox
Producator: Cos Pitesti
Cantitate: 3t
Supradefinirea operatorilor

Definirea unei clase ntr-un program reprezint definirea unui nou tip de date. Folosind
operatori standard putem defini diferite operaii cu obiectele clasei. Aceti operatori se obin
prin supradefinirea celor existeni adica prin modificarea semnificaiei lor.
Rolul supradefinirii operatorilor este creterea lizibilitii programului exprimnd operaii cu
obiectele claselor definite de utilizator sub o form cat mai sugestiv.

16

Supradefinirea unui operator ntr-o clas se face prin specificarea unei funcii care
implementeaz operaia corespunztoare operatorului respectiv. Aceast funcie este ulterior
apelat atunci cnd clasa folosete operatorul supradefinit.
Declararea funciei folosete cuvntul cheie operator sub forma:
tip_rez operator simbol_operator (<argumente>);
La supradefinirea operatorilor trebuie respectate regulile:
- simbol_operator = orice simbol de operator din C + + mai puin urmtorii patru:
. (operator de membru al clasei)
.* (operator de pointer la membru)
:: (operator de rezoluie global)
?: (operator de expresie condiional)
- nu se poate extinde setul de operatori C + + prin desemnarea de noi simboluri
(caractere sau seturi de caractere).
- aritatea unui operator nu se poate modifica.
- prioritatea i asociativitatea operatorilor supradefinii se pstreaz; se poate modifica
doar prin folosirea parantezelor.
La supradefinirea unui operator pentru o clas, semnificaia lui este modificat doar n clasa
respectiv, pentru restul variabilelor din program operatorul pstrndu-i semnificaia curent.
Funciile operator care supradefinesc operatorii unei clase se definesc:
- sau ca funcii prietene
- sau ca funcii membre ale clasei respective.

Funcii operator prietene


Prototipul funciei operator prietene apare n cadrul declaraiei clasei fiind precedat de
cuvntul cheie friend. Aceast funcie are acces la toate datele private ale clasei.
Exemplu: Aici implementm operatorul unar minus, operatorul binar plus i nmulirea cu un
scalar, ca funcii prietene clasei coord, care se refer la coordonatele punctelor din plan.
Prototipurile celor trei funcii operator sunt incluse n declaraia clasei i definiiile lor sunt
plasate n afara clasei.
# include <iostream.h>
# include <conio.h>
class coord
{
private:
double x; double y;
public:
constructor
coord (double x0=0, double y0=0)
{x=x0; y=y0;}
void afisare ( )
fct. membru
{
cout <<x=<<x;
cout <<, y=<<y<<endl;
} declararea funcieiilor operator
friend coord operator (coord);
friend coord operator + (coord, coord);
friend coord operator * (int, coord);

};
coord operator - (coord a)
{
def. fct.
coord c;
operator minus
c.x = -a.x;
c.x = -a.y;
return c;
}
coord operator + (coord a, coord b)
{
def. fct.
coord c;
operator plus
c.x = a.x + b.x;
c.y = a.y + b.y;
return c;
}
coord operator * (int k, coord a)
{
def. fct. operator
17

coord c;
nmulire cu scalar
c.x = k * a.x ;
c.y = k * a.y ;
return c;
}
void main ( )
{
clrscr ( );
cout <<Date de intrare:<<endl;
coord p1(1,1); p1.afisare( );
coord p2(2,4); p2.afisare( );
coord p3(3,0); p3.afisare( );

coord r1, r2, r3, r4;


cout <<Rezultate:<<endl;
r1 =- p1;
r1.afisare ( );
r2 = p1 + p2;
r2.afisare ( );
r3 = p1 + p3 +r2;
r3.afisare ( );
r4 = - 5 * p1;
r4.afisare ( );
}

18

Dup compilare i rulare pe ecran apar:


Date de intrare:
x = 1, y = 1
x = 2, y = 4
x = 3, y = 0
Rezultate:
x = - 1, y = - 1
x = 3, y = 5
x = 7, y = 6
x = -5, y = - 5
Funcii operator membre

O funcie operator membr unei clase are unul din operanzi this iar ceilali operanzi,
dac exist sunt transmii ca argumente. Astfel implicit funcia primete adresa
obiectului pentru care este apelat.
Exemplu: Relum exemplul de mai sus pentru implementarea celor trei operatori ca
funcii membre ale clasei coord.
o Se nlocuiesc cele trei instruciuni friend care declar funciile operator
prietene respective cu urmatoarele instruciuni care declar funciile operator
membre:
coord operator ( );
coord operator + (coord);
coord operator * (int);
n definiiile celor trei funcii se nlocuiesc instruciunile subliniate mai sus
respectiv cu cte una din urmatoarele:
coord coord :: operator ( )
coord coord :: operator + (coord b)
coord coord :: operator * (int k)
o n rest totul este nemodificat, excepie referirea la primul argument al
funciilor care acum se face prin referirea direct a acestora i astfel programul
va afia aceleai rezultate ca i cel de mai sus.
Directive de preprocesare
Preprocesarea este prima etap a compilarii unui fiier surs i este realizat de
un program special numit preprocesor care este diferit de compilator. El este automat
apelat de compilator pentru a executa anumite comenzi ce exist n fiierul surs,
comenzi numite directive de preprocesare i precedate de #.

Directiva #include
Insereaz n programul surs curent coninutul fiierului indicat de
directiv. Cu aceasta putem modulariza scrierea programelor. Aceast
directiv are 3 sintaxe:
# include <fiier>
# include fiier
# include nume

fiierul de aici se numete fiier antet


acesta se folosete cnd fiierul antet se afla n directorul curent
nume este numele unei macrocomenzi

19

Fiierele antet sunt fiiere ASCII stocate n subdirectorul INCLUDE al directorului


ce conine compilatorul C + + .
Exemplu fiierul antet iostream.h ofer funcii de bibliotec pentru operaiile de I/E n
flux.

Orice program C++ ncepe cu una sau mai multe directive # include.
Directiva #define
Pentru definirea constantelor sau a pseudofunciilor (numite i macrodefiniii
cu argumente) sub forma:
#define macro text
#define macro valoare
#define nume (lista_program) expresie
unde: macro este identificator
text = secvena de caractere
valoare = valoare numeric
nume = numele pseudofunciei
expresie = expresia pseudofunciei
La procesare, orice apariie a identificatorului macro se nlocuiete cu definiia
sa.
Exemplu:
#define EPS 0.001
#define PI 3.1415
Observaie: Pe o linie de cod nu pot exista mai multe directive #define.
Macrodefiniiile cu parametri permit definirea pseudofunciilor care sunt mai
rapide dect funciile obinuite dar ocup mai multa memorie.O pseudofuncie
accept ca argument un parametru i nlocuiete orice apariie n program a acelui
parametru prin valoarea furnizat la apelul pseudofunciei respective.
Exemplu:

#define PATRAT (x) ((x)*(x))


#define CUB (x)
(PATRAT (x)*(x))
Aceste dou pseudodefiniii calculeaz x2 respectiv x3, pentru x furnizat la apel.
Directiva #define se poate folosi i pentru:
- nlocuirea cuvintelor rezervate sau a simbolurilor cu ali identificatori definii
de utilizator.
- crearea de identificatori pentru tipuri de date definite de utilizator cu ajutorul
tipurilor standard.
- prescurtarea unor comenzi.
Directiva #undef
Este opus directivei #define permind anularea definiiei curente a unui
identificator, dac acesta nu mai este necesar.
Are sintaxa:
#undef macro
Cu ea eliberm spaiul de memorie ocupat de macrodefiniia anulat i putem reutiliza
numele identificatorului acesteia ntr-o alta directiv #define.
Ex.: #undef EPS
#undef PATRAT
Directive condiionale

20

Acestea sunt #if, #else, #elif, #endif, #ifdef, #ifndef, n care


primele 4 directive controleaz compilarea unor instruciuni n anumite
condiii i au sintaxele:
# if cond1
secv1
[#elif cond2
secv2
........
[#elif condn

secvn]
.......
[#else
secv0]
# endif

Aici
secv1 este o secvena de directive de compilare care se execut cind cond1 este
indeplinita i analog pentru celelalte;
secv0 este secvena de directive de compilare care se execut cind nici una din
condiiile cond1, . . . . , condn nu este indeplinita.
Ex.: # if VAR = = 1
# define ALPHA char
# elif VAR = = 2
# define BETA boolean
# else
# define GAMA float
# endif
Directiva #ifdef compileaz o linie de cod dac un anumit identificator a fost definit
anterior iar #ifndef dac identificatorul nu a fost definit anterior.
Acestea au sintaxele:
# ifdef identificator
secv1
# endif

# ifndef identificator
secv2
#endif

unde secv1 = secvena de directive de compilare care se execut dac identificator a


fost definit anterior.
secv2 = secvena de directive de compilare care se execut dac identificator nu
a fost definit anterior.

21

Exemplu:

# ifdef MAXIM
# define ALPHA char
# endif
# ifndef MAXIM
# define BETA boolean
# endif

Directiva # error
Genereaz un mesaj de eroare. Are sintaxa: # error text_mesaj_eroare.
Aceasta semnaleaz incompatibilitatea versiunilor unui program sau erori de sintax
cauzate de omiterea sau folosirea incorect a anumitor caractere ca: paranteze, acolade, punct
i virgula etc.
Exemplu:

Error directive: cannot find command procesor


Error syntax.CPP4: undefined symbol quotes n funcion main ( )

Ultima eroare de sintax se refer la linia a 4-a a fiierului surs i indic


neincluderea unui mesaj ntre ghilimele.
Directiva #line
Aceasta permite precizarea numarului liniei curente compilate ntr-un program.
Are sintaxa: # line numar [nume_fiier]

Directiva specific numarul liniei din fiierul cod surs original. Cu ea


putem realiza referine ncruciate sau identific poziia din codul surs unde sau produs erori.

22