Sunteți pe pagina 1din 260

CLUJ-NAPOCA

2001

[10lliLJ w&cD [3 [1[3

© ~O©9c{?
·~[3~lJ[g3(lD n~©[3~&lJ@wO
VOLUMUL II

Reeditare

Autor:

CUPRINS
20.

A confruntatcu originalul Irina Mitrov

LIMBAJUL C++ CA EXTENSIE A LIMBAJULUI C


Comentariu . . . . . . . . . . . . Definitia unei functii . . . . . . . Antetul si prototipul unei functii . Exercitii . Corpul unei functii . . . . . . Tipuri pre definite in C si C++ Constante caracter Exercitii . Operatori . Operatorul de rezolutie . Operatorul adresa (&) . Operatorul de alocare dinarnica a memoriei (new) Operatorul de dezalocare a memoriei (delete) . Apel prin referinta (call by reference) . Exercitii . Functii care retumeaza date de tip referinta Exercitii . Modificatori . . . . . . . . . Modificatorul const ... .. Modificatorii near, far ~i huge Cuvintul cheie void Structuri . Reuniune . Tipul enumerare . . Supraincarcarea functiilor Exercitii ... Functii inline . Exercitii ...

7
7 8
8

20.1. 20.2. 20.2.1. 20.2.2. 20.3.

11
13 14

2004.
20.5. 20.5.1. 20.5.2. 20.5.3. 20.5.4. 20.6. 20.7. 20.8. 20.8.1. 20.8.2. 20.9. 20.10. 20.11. 20.12. 20.13. 20.14.

15
15 16 16 17 18 20 21 22 29 31 33 33 36 36 38 39 40 41 43 54 57

Editura Albastra Director editura Smaranda Oervesteanu Coordonator serie Codruta Poenaru Coperta Liviu Dervesteanu Tiraj: .1000 exemplars Tiparif EDITURA ALBASTRA comanda 143/2001 Teate drepturile aceslei edilii sunt rezervate

21.

PROGRAMAREA PRIN ABSTRACTIZAREA DATELOR


Exercitii .

60
71

22.
22.1. 22.2. 22.3.

CLASE ....
Definitia claselor . Obiecte . Domeniul unui J1l1me.

75
86

88
91 3

S.c. Casa

de Editura Albastra s.r.1.

22A.
~-).

77 ~

22.6.

22.7. 22.:-\.
22.9. 22.10.

Vizibilitatc Durnta de \'I<I\a a datclor Alocarca si dczalocarca obicctclor lnitializare Constructor Destructor Excrcitii Fu netic prictcn (Friend function) Excrcitii .

94 94
.
95

28. 29.
29.1. 29.2. 29.3. 29.4. 29.5.

PROGRAiVIAREA ORIENTATA SPRE OBIECTE . CLASE DERIVATE


Exercitii

324

96 97 105 106 137


140

51 CLASE DE BAZA
.

335
337 342 356 357 35:-\ 361 394 397
405

Rclatia dintrc constructorii si destructorii clasclor de baza si ai clasei derivate

Conversii

23.
23.1.

SlJPRAINCARCAREA
Exercitii .
opcratorilor Supraincarcarca

OPERATORILOR
new si delete

143
149 177
185 193 198 .

Rcdefinirea datclor mcmbru ale unci clase de baza intr-o clasa derivata . Supraincarcarea functiilor membru ale unei clase de baza intr-o clasa derivata

23.2.
233. 23.4. 23.5.

Exercitii Supraincarcarca operatorului == . Excrcitii . Supraincarcarca opcratorului [] (opcratorul de indcxare)


Exercitii . Supraincllrcarea opcrurorului Exercitii . .

Exercitii ... Clase virtuale . Exercitii ...

0 (opcratorul
.

de apel functic)

Supraincarcarca operatorului -> . . .

205 207 21:-\ 225 232

30.
30.1.

FUNCTn
Exercitii Exercitii ... ...

VIRTUALE

Clase abstracte

416 441 449

24.
24.1. 24.2.
24.3.

CONVERsn
Conversia Exercitii. Conversia

.
. in date de tip abstract. . intr-un tip predefinit .

235
240 246 265 267 278 282

31.
31.1.

INTRARI/IE5IRI
Intrari/Iesiri standard. Iesire standard

......
'

459
461

date lor de tipuri predcfiuitc

31.l.1.
31.1.1.1. 31.1.1.2.

460

Exercitii
Conversia Exercitii

dintr-un tip abstract . . . . . . . . . . . ..


dintr-un tip abstract

Exercitii

..

.
.

intr-un alt tip abstract.

Manipulatori . Exercitii ... Iesire neformatata

...........

25. 26.

MODIF1CATORUL CONST PENTRU OBIECTE 51 FUNCTll MEMBRU .. OPERA TORll DE DEREFERENTIERE A POINTERILOR SPRE MEMBRII CLASELOR (.* 51 ->*)
Excrcitii ..

3l.1.1.3. Supraincarcarea operatorului « pentru i~~'ir;de 'obi~~t~ 31.1.2. Intrare standard .. .. ..


31.1.2.1. 31.1.2.2. Exercitii . Intrari neformatate .................... Supramcarcarea operatorului » pentru intrari de obiecte Exercitii . Formatarea in memorie Prelucrarea fisierelor .

467 468 469 470 471


472

296

476 477 480 481


497

298
301

3l.2.
31.3.

Excrcitii

499 505

27.

CONCLUZlI ASUPRA PROGRAMARU ABSTRACTIZAREA DATELOR

PRIN .

BIBLIOGRAFIE 305

518

20. LIMBAJUL C++ CA EXTENSIE A LIMBAJULUI C


in 1141 B. Stroustrup arata ca limbajul C++ cste proiectat in asa fel incit: - sa fie un C mai bun; sa permita stilul de programme prin abstracrizarca datelor; sft permita stilul de programme orientat spre obiccte, In aceeasi carte, Stroustrup afirma ca C++ este un "C mai bun" deoarcce furnizeaza un suport mai bun pentru stilurile de prograrnare suportatc de limbajul
C.

Amintim cit limbajul C permitc utilizatorului sa foloseasca stilur ilc de program are incetatenite sub denurnirile de "program are procedurald" (vczi 4.14) si "program are modulara" (vezi capitolul 7). Ambele stiluri sint suponate mai bine de limbajul C++ pe baza introducerii unor extensii la facilitatile existente in limbajul C. Limbajul C devine un subset al limbajului C++ (adesea se obisnuieste s{tse spuna ca C++ este un superset al limbajuluiC). Aceasta inseamna ca un program scris in C este in acelasi timp si un program scris in C++. In linii mari, acest lucru este adevarat. Cornpatibilitatea nu este asigurata 100% dar cazurile de incompatibilitate sint neesentiale ~i pot f user eliminate Ia prograrne concrete. In eapitolul de fala se tree in revista cxtensiilc mai importante ale constructiilor din C introduse in limbajul C++. Cu altc cuvinte, in acest capitol se discuta aspectele care eonduc la afirmatia lui B. Stroustrup ca lirnbajul CI·+ cstc un C mai bun. Celelalte facilitati oferite de limbajul C++ (programarea prin abstractizarea date lor si orientata spre obiecte) VOl' f abordatc in alte capitole. In incheiere, plastic vorbind, putem afirma ell limbajul C++ este un "C incrernentat" 5i intelegern prin accasta cit pc de 0 parte estc un "C rnai bun", fiind o extensie a Iimbajului C, iar pe de alta parte perrnitc stiluri de programme impracticabile in C: - programarea prin abstractizarea datclor programarea oricntata spre obiccte.

20.1. Comentariu
Cornentariile sint explicatii pcntru programatori. Ele pot f introdusc in mice punet in care este legala apariria unui caracrer alb.-· in limbajul C, 0i deci ~i in C++, corncnrariilc sc includ intre 1* (rnceputul 7

eOlllenUlriului) rnultc nnduri.

~i */ (sfirsitul

comenturiului).

Corncntariilc

pot fi sense

pc mai

. in afara de accasta posibilitate, in limbajul C++ exista ~i varianta de a sene corncntarii pc un singur rind. Un astfel de comentariu inccpe ell secventa:
//

Spre deosebire de limbajul pa!~:nctril()r formali. Exemple: 1.


Boolean v_calend

C, in limbajul

C++ se pot face inilializ<lri

ale

(int zi,int

luna,int

an '" 1994)

In accst cxemplu,

parametrul

formal an estc initializat


b=360,

cu valoarea

1994.

si sc termina

. Comentariile de acest fcl insotesc, de obicei, cite 0 mstructiune sau 0 componcnta a unci instructiuni care necesita explicatii pentru ~rogram~to.n ... ' Comcntariile din antctul unei functii se scriu adesea pc mai rnulte linii ~I din aceasta cauza cle se insercaza mai simplu folosind convcntia din limbajul C. Exemplu:
if (b
&&

la sfirsitul

rindului.

2.

double

aria(double double

r,double a=O,double pi=3.14159265358979)

Parametrii

formali

initializati

se numesc

E!!.!:5!.!'.!!:!i!"i_i

impJ.!!:.U!.:

z i· < 29) II an bisect -> b= I; altfcl b=O

2i++;

in compunerca
ASCII.

unui comcntariu sint eliminate

sc pot util-za oricc caractcrc la compilarc.

ale codului

La apelul functijlor, Ijnui parametru in-PJi.<?i.!.£9ate s~:i core,~p.\I!:9a sc~!_~lli1 rarametl1l efectiv, In cazul in care unui parametru implicit nu-i corespunde, la apel un parametru efectiv, parametrul formal respectiv ia ca valoare valoarea sa initiala. Aceasta se mai numeste va/oare 'implicit!} a pararnetrului respectiv. Daca la un apel, unui parametru implicit Ii corespunde un pararnetru efectiv, atunei parametrului formal respectiv i se atribuie in mod obisnuit valoarea parametrului efectiv care ii corespunde. Cu alte cuvinte, in accst caz se neglijeaza valoarca implicita a parametrului formal, De exernplu, apelul functiei v_ calend avind antctul de mai sus:
i

*'

Comcntariile

din programc

v_calend(28,2);

20.2. Oefinitia unei functii


Definitia
et.

implica formali: din antet urrnat de corpul d

lansarea,

functiei

v_calend

pentru

urmatoarele

valori

ale parametrilor

unci functii in lirnbajul C++ sc cornpune

zi = 28, luna = 2, an = 1994. Pcntru an s-a utilizat valoarea


i

o functie

poate fi apelata daca este prcccdata de definitia sau

e prototipu ei.

I.

implicita,

In schimb apelul:

v_calend(31,3,1995);

20.2.1. Antetul ~i prototipul unei functli


functie in mod implicit este globala. Ea poatc fi lo~alizat~1 mtr-un fisicr SlIrS[1folosind cuvintul cheie static la inceputul antetului ei. In aces! caz, se spline

lanseaza functia v_calend cu valorile:


Zl

31, luna

3, an=

1995.

In acest caz, valoarea irnplicita a fost neglijata.


La ·~lizare~ral1:!.ctrilor iIl12Ii~l~i exist0_,,()~liln~t!~_~.J~JI_~t~!!,[j __ u_l?g;;:i_tj9 c acestora si anume,ei trebuie ~e ultiJ11~ozitii in lista declaratiilor din an tcturfunci[e'Cne.i£utiil(ffi~mesteca Iicl!._£ar;J11etri'care--i1 u siritTl{itla liza(C------yny;ml)aj'eTecpotdefmr{~!:lctIL~;~~~1·~i~if~I?lI:~£-_~~i~:!~:!.~. in acest caz,lista declaratiilor parametrilor formali contine numai dcclaratiile parametrilor care sint prezenti la orice ape! al functiei. Acestia sint asa numitii £aran!:f!.!!iJlcc§.i ai functiei spre deosebire de ceilalti care se numesc l:!.E!.ametri variabili. Parametrii ficsi preced pe cei variabili, Prczenta parametrilor variabili sc";;ldTcfi, in antetul functiei.prin trei puncte care se scriu dupa ultimul pararnetru

ca functia cste statica. o functie poate sa returneze (intoarca) sau nu

. valoare la rev:l1Irea din ea.

Tipul valorii returnate de functie se indica in antetulfunc\:eL In cazul in care functia l1U returneaz~i (intoarcc) 0 valoare, in locul tipului elm antetul Cl se folo~este cuvintul cheie void. Antctul unei functii in limbajele rip numeilista sau C ~iC++ are forrnatul:

~iC++-s-e

declaratiilor

parametrilorfomiali) paramclri/orjiml1a/i)
D',lC',"1

fix a I tunctiei. static til) nutne (lista dcclaratiilor functia


Illl

. . Dcclmatiile de paramctn . sint separate pnn vlrgu I"a. paramctri. ,~tlll\ci lista din parantezelc rotunde estc vida.

arc

ExempJu:
Fie antetuJ:
void vf(int n,double x, ... J

Din antet rezulta ca functia are doi parametri ficsi: 11 $i x, precum ~i alti paramctri al carer nurnar (ii tip llU cste in prealabil preeizat ~i difera de In apella apel. Functiile cu un numar variabil de paramerri se definesc folosind nistc macroun specials care permit accesul Ia pammetri variabili, Aceste macrouri sint definite in fisierul ~{q!!!RJl: De obicei, fllnctiile cu un nurnar variabil de parametri sint functii de biblioteca. Excmple de astfel de functii din biblioteca sistemului sint funqiilc printf ~i scant: Acestea au fiecare un singur parametru fix ;;i anunic parametrul care dcfine~tc formate Ie de conversie si cventualele texte eonstantc care intervin in operatiile de intrare/ie;;ire initiate prin apelullor. Antetul unci functii poatc fi mai general dccit eel indicat rnai sus. Astfel, in limbajului Turbo C++, antctul unci functii are urmatoarea structuni generala:
cazul

activcaza conventia din C pcntru apelul. fU~lq~~i ModIlICdtOlUI I cdecl ificau .. '1 '. nlog' modificatoru I !NI.IUI l id ctivcaza convcnna tim Pascal , respective. n moe HI, '., .. I" 'I implicita in lipsa accsror pentru apelul functiei respective. COnV~n\ld ue dPC , l, ' I arc. . lri rnod modificatori.este . cca ti·fi rita prin optiunile de compiapelurile ell, . ,..... '. f1 teaza functiilor, In mo I· f .. If' far SI llIge 111 uen crz.c , • . Moe I leatoru. nee,. '.. I I· I Ic 111 '111(~rieeurent si anumc modclcle III1Y, implicit ci se dcfinesc pnn mote u (C c , nodclelc ~1edillm si large implica I small.~i compac~ i:~pliea mOd;I~~e::t~I~11~~[~;1~~dificatorul huge. ' . t1 w moddlea.ton. .f , I.<lrmodelul g .• p. , I . fi . il ofera functiile de gesnunc I d utilizarc 'I modificatoi II U1 ClI '. If' ~Jn a ecranuluitvezi ~,' ,,'1 I . ar, grafica exemp u .c .. capite u.'. 19) Accstea toate au in antct modificatoru '. . lica arx 1 .: si pointen de tIP fat . deoarcce imp rca ape,ull '". '. fi obtinut scriind punct si virgula clUI);!. 0 Prototipul unci functii pOd:e, 1 r' .: i respective, fie se obtine din ante! constructie care, fie coincide Cll :'l11tctu. uncne .
._, • .? ..< •

eliminind nurnele parametnl~r form alt/' ; Tli antet se indica in excrnplul Astfcl, prototipul functiei v.r« l em,l a e,:! c mai sus, se poate scrie in urrnatoarele forme.
Boolean
. .en v_ca 1 d(int

I de

zi,int

luna,int

an=1994);

speczjicator_de _ clasa tip mo(iLjicatori num« (Iista declaratii for parametrilor formaliy Speciiicalorul de clasa, daca este prczcnt, cste euvintul 'chcie static SHU extern. Cuvintul eheic E':1~i(._~<::_llt~liz<;'I~~lpelltl·lIQU{)_e<_l_~i2:'!)fl.llletia in fi~ierlll in care este definita. Cuvintul cheie extern indica faptul ca functia este globaln. In mOo'-In1pliclio flll1ctie se eonsiden) ca cste globala ~i de accea specincntorul extern, de obicei, nu se utilizeaza. Tipul din anret definesre tipul datci rcturnarc de functic, Daca Iunctin returneazn un alt tipdecit ecl indicat in antetul ei, atunci valoarea respecnvs este converrim automat spre tipul indicat in anter, inainte de a reveni in punetul de dupa ape!. Daca tipul nu este prezent in antetul functici, atunci se considera ca functia returneaza 0 valoare de tip into Cu reate acestca se recomandz ca tipul S11 lie prezent totdeauna. S-a constarar ca omiterca tipu lui din antetul functiilor conduce la erori, deoarcee acesta se ornite si cind trebuie sa fie prezent (adiea atunci cind este diferit de int) ~i 0 astfel de eroare nu poate fi depistata de compilator, Moditieatorii care pot apare intre tip si nume sint specifici diferitelor implement!iri ale limbajului C++. In cazul lil11bajului Turbo C++ cci mai importanti modifieatori sint: cdecl, pascal, near, far ~i huge Primii doi stabilesc conventii de transfer a parametrilor ~i de apel a Iuncriilor. Ei se folosesc cind se utilizeazn module sense in mai rnulte limbaje de programare. 10

sau

Boolean

. . . __ . v_calend (lnt, a n t., In t -1 994 J' ,

;t in

. Prima forma clarifica scnsul pararnctn '1Of ~l de accea ea este sugcstiva comparatic eu cea de a doua. ... .r , ' c Pcntru exemp 1 1') se pot utiliza urrnatoarele protoupun: u ~"
double aria(double ~ double r,double a = O,double b pi = 3.14159265358979);

360,

sau
cloublp
aIld ....ClOl __ s double (. lblE'
>

double

= a,double = 360, = 3.14159265358979);

Exercitii:
20.1

. eiteste un intreg scris in baza de nurnerane b . '. I' t'i I memorcaza in zona sprc care spre trpu In ~... . . .. ., f rctiei. Baza implicita a intregului este zece, UI • ds . tilneste sfirsitul de fisier si UI1U zero <lca se 111 • •

.,.... ti e care Sa se sene 0 functi c (2<=b<= 10) il converteste . ._'., . ,I pointeaza parametrul n a Functia returneaza valoarea in eaz contrar.

FUNCTIA BXX1
1* . citcstc un intreg scris in baza b dill intcrvalul
int bint(int *n,int b=10) .
?

[Z, I OJ, - convcrtcstc numarul citit in binar de tip 1I1t; . , . . astrcaza numarul convcrtit in zona ~prc care pOl!1t~aza n; . ;'ctllrncaza 0 la sfirsitul de fisicr; altfcl rcturncaza I,

*1
(

long s;

11

int c,siqn; char e r ll

'ISl~

reia

ci t i re.a ce r ac t.e rel.or

intregului\n

ll ;

mai n t i nt. arqe,ehar *argv[]) 1* - citcstc 0 succesiunc de numcrc scrisc in baza b si Ie afiscaza in sistcmul de numcratic baza 10; - dupa ultimul numar sc tastcaza sfirsitul de fisicr: 2 <= b <= 10.

eu

for (; ; ) ( printf('tastati earaeterele intregului sign = 1; while((e getehar(11 ==" II c== ; II sail peste caractere albc i£(e == "I( Iinumarncgativ s i qn -1; c ~ getchar ( I; II sail peste minus
e l.s e

= '); '\t'

II

*1
e '\n'l int b,lng,n;

if (e = '+' I e = getchar (I; II sail peste plus if(c == EOF) return 0; if(!(c >c= '0' && e < 'O'+b)l( II nu s-a citit a cifra din intcrvallil [O,b) printE('se cer cifre din intervalul [O,%d)\n',b); p r i n t f (er) ; f flush (s tdin); II sc videaza buferul de la intrarca standard continuei for(c';=O;c
s

if(argc != 2)( printf("baza linia exit(1); Ing strlen(argv[l]); if (lng < 1 I I Ing printf("argument argv[l]) ; exit (1);
}

de numeratie nu este de eomanda\n");

argument

in

> 2) ( in

linia

de eomanda

eronat:

%s\n",

>= '0'
s*b+C-~IOfi

&& C < 'O'+b;){

if (s > 327671 ( printf(!!valoarea absoluta a numarului\ citit depaseste 32767\n'); pr i n t.f (erl ; fflush (stdin) ; break; c = getchar(); if (s > 32767) continue; * n =. sign * s ; return 1i
) }

if(argv[l][O] < '0' II argv[l] [0] > '9'){ printf("argumentul din linia de comanda este un intreg: %s\n', argv[l]); exi t (1) ; if(lng =='2 && argv[l] [1] != '0'1{ printf(i'baza de numeratie eronata: exit(l);

nu\

%s\n",argv[l]);

If se reia citirea intrcgului

b a toi (argv [1] ); 1/ convcrsia bazci in binar H(b<21Ib>10){ printf("baza de numeratie eronata: exit(l) ; for(;;) ( if(b == 10) Ing = bint(&n); else Ing = bint(&n,b); if(1ng) printf("%d\n",n); else break;
}
}

%s\n",argv[l]);

20.2

Sa se scrie un program care citeste 0 succesiune de numere separate prin caractere albe ~iafiseaza fiecare numar pc cite 0 linie. Numerclc cititc sint scrise in sistemul de numeratic cu baza b (2 <= b <= 10). Dupa ultimul numar se tasteaza sfirsitul de fisier, Numerele se afiseaza in sistemul de numeratie eu baza 10. Baza b este argumentul programului din linia de comanda, BXX2

20.2.2. Corpul unei functil


Corpu/ unci functii este 0 instructiune compusa. In limbajul C, 0 instructiune compusa este 0 succesiune de instructiuni care poate fi precedata de 0 succesiune de declaratii, succesiuni care sint incluse intre acolade. In particular, 0 instructiune compusa se poate reduce la 0 pereche de acolade. Acest lucru este adevarat si in limbajul C++. in plus, in limbajul C++ nu este necesar ca intr-o ~~!_t~!~~_~!~1pu~!ec!~E~1!.i.!~J!.~prec<::_ad~-in~~E_,!ctiu~~--------13

PROGRAMUL
#include #include #inc1ude #include

<stdio.h> <stdlib.h> <string.h> 'BXXl.CPP·

12

Exemplu:
for(int ;i<10;i++){ ... )

con~~!~~:~il~~~~ d~~l:r~r~~t~l~tC~~JlCi~luIu(i/i)r. Ac.eas.t.i\ declaratie estc valabila in .t" I" ' .' oeu UJ mstrucnunn cornpuse) care contine I!1S rucnunearor respectiva. . /.1) dee:~~~~~lr~'~rd~~i,\ratiilorl in oric.e punct al corpului unei functii perrnite sa • .• . c 1a lee oca e atune: cind avem nevoie de ele In felul a· ' " elimina situatiile in care se declara variabile 10 'I I. . . ~e~std se l care apoi ramin neutilizate. ca e a inceputul corpului funcriei

Poinlcrii pot f sprc 0 data sal! spre 0 functic. Tipul pointer tip *, spre 0 d~lla, sc rcprczinta pe 16 bi\i pcntru rnodelcle de memoric tiny, small ~i lIledilllll.I'Clltru restulmodelelor, datele de tip pointer se reprezinta pe 32 de biti. Datclc de tipfloat asigura 0 prccizie de 6-7 cifre, cele de tip double 0 precizie de 15 cifre, iar ccle de tip long double 0 precizie de maximum 19 eifre.

20.4. Constante caracter


In limbajulC, 0 constanta caracter arc tipul into Ea se reprczinta printr-un caraeter imprimabil inc1us mtrc caractere apostrof sau printr-o secventa escape (vezi 1.6.3.). in limbajul CH 0 astfcl de constanUl caracter are tipul char. In afara de acestc constante, in limbajul C++ se admit ~i eonstante care au tipul into Ele se reprczinta Exernple: pe doi octeti.

20.3. Tipuri predefinite in C si C++


chcie Dimensiune in hiti 8 signed char unsigned char 8 8 16 16 16 16 Interval

caracter

[-128,127J [-128,127J [0,255J [-32768,32767J

'a'

Constant~\ caractcr pastrata in C++ pe un octet. sizeof: ( 'a') are ca valoarc pc I; are tipul char. Constanta caraclcr pilstrat£l pc doi octcti. Octctul mai putin semnificativ pilstreazil codul ASCII a, iar eel rnai scmnifieativ, codul Ascn al lui h.
_ sizeof ( 'ab' ) arc valoarca 2; are tipul int.

<II lui

r -32768,32767J
[-32768,32767J [O,65535J [-2147483648,2147483647J

'abc'

Emare. _ Constanta

caracter nu poate avca decit eel mult 2 caractcrc.

Excrcitii: 20.3 Sa se scrie un program care afiscaza dimensiunile in octet! ale constantclor caracter 'a' si 'ab', prccum ~ivalorile octetilor pe care se rcprczinta accstea. PROGRAMUL BXX3

[1.7* 10**(-308),

1.7* I O**308J

#include

<stdio.h>

16 sal! 32 16 32

main! ) 1* _ afiscaza di111CIlsiuIliic in octcti ale constantclor 'a' si 'ab'; _ afiscaza valorilc octctilor pc care sc rcprczinta cclc doua constantc */ printf("dim lui 'a' %d\n",sizeof 'a'); printf("dim lui 'ab' %d\n",sizeof 'ab'); printf("codul lui 'a' ~. %d\n", 'a'); printf("octetul ma putin semnificativ a lui 'ab' & 0377); printf("octetul mai ('ab' » 8) semnificativ 03 7 7) ; a lui 'ab'

caractcr.

'ab'

%d\n",

%d\n",

&

IS

14

\
20.5. Operatori
Operatorii utilizati in limbajul C pot fi utilizati si in limbajul C++ ~i au acclcasi prioritati.\ii asociativit~~e. '1' . Ii lirnbajul Tabela eu pnonta\!lc OpCIaton 01 (111 I . 3.2.16. 1",I\a' extindem In paragraful de limbajului C++. C este datil in paragraful noi, specifici

20.5.2. Operatorul adresa (&)


In limbajul C operatorul variabilc. Astfcl, constructia: Scnume dcfineste adrcsa de inccput a zonei de mcmorie alocata pentru nume. In limbajul C++ accst operator are ~i 0 alta utilizare :;;i anume accca de a introduce lipu/ reB,!_in{cL_ DaC[1 tipul pointer sc introduce prin consrructia: tip * tipul refcr!!1tft ~.s.l!!.~!:,()!!,llE~J)I·i_I~.: adresa se utilizcaza pentru a defini adresa unei

tabcla respecliv[l cu operatori

20.5.1. Operatorul de rezolutie


Acest operator ~~!!!its:.accesul la o<i_~!~,gloQaJ~r.~c,l,~fl.I}!t~.s.'Lloe_al~l. I se E notcaza prin :: , Fie variabila i definita ca globala:
int ii

!' 1;/;&-\ '~ ... --->.-,

si functia/in
void

care variabila i se rcdcclara ca ~i locala:

f( ... )

Tipul re&~Ec:"'e.!:.:!:.~ sinol!i.l_1!l?P~_I~ll!!1~.2.si<:.2~fil'!itc. De asernenca, dalele d~..':I:_c~~! ..!ip'.p()tfi.f~12§i~£J?2.12.tl.'!l..ilrc~lli!:~l':1?!?!~~LJ?Ei!2.Eef:Cxin\<\ by (call reference) . Avind in vedere aceasta utilizare noua a operatorului &, se obisnuieste ca acesta sa mai fie numit :;;ioperator de referentiere. Operatorul unar * utilizat la declararea pointerilor are in expresii un efect invers cclui de .referentiere si de aceca el sc mai numeste operator de dereferentiere. • Constructia tip & se utilizcaza in dcclaratii de forma: tip &nume; Mcntionam ca pozitia opcratorului & in dcclaratia adica declaratia de rnai sus poate fi sensa ca mai jos: de mai sus este variabila,

char

i;

in aceasta situatie, 0 expresie de forma: 10 variabilei scrisa in corpul functiei j; atribuie va Ioarea
i=10;

locale i declarat£l in

tip & mane; sau tip& nume; Ultima 1'01'111[\ este cea mai utilizata, Numele decl(irat in acest fel se spune ca este 0 reierin(ci. 6-viirG5Irre7crTilfif':"c -poa ini tJaIT2:ilTli' -,refI11ITCaa s numele unei
____ " ...~...,~"'*"""",_._,

corppu:n~~:~ti~;ir~:~~~~i~t~'ila globaHt i, in corpul functieif e.s~~necesar ca i sa fie precedaUl de operatorul de rozolutic. ClI alto cuvinte, cxpresld.

.x-t
c

::i=lO;

va '~~;~~~'4~~~:;~(;I;~~·~(~::~;I(lr~~~;~~:{~t.~111~1;(inl[t, adica me acccasi prioritatc


Cll

te' altc·vaniiblTe:· .._·_····..···__.·..·.-.. .


__ ....

-'''-'w .•

.....-~...

II

dec Iararea

Cll

*"

operatorii:

Exemplu: si -> amintita mal


. " . SUS,VOl11

()

[J .

Deci, in tabela operatorilor operatorul de rezolutie (i.).

complete prima linie

Cll

:i.nt i; :i.nt& j"i;

y'ari a ~i1~lj_,~.s,~ e S!ll()llim a ell. \,a riilb il.<l_ §l~E~p~~e_,:i.n i. t a,.':I:_ce I a.§ij!.~Ie.g~ De excmplu, daca atribuim lui i 0 valoare:
i

1234;

17 16

atunci 'iij are (refera) aceeasi

valoare. caruia avem acccs la

Variabila j de mai sus, estc un alt nume cu ajutorul intregul pastrat in zona de memorie alocata lui i.

pastreaza
pint"

intregul

J 00 in zona respectiva,
,

..

Aceeasi . alocare se obtinc, in limbajul C, folosind functia malloc ca mal .lOS:


(int *)malloc(sizeo (int));

De accea, expresiile:
i*7+3

j*7+3

i_nt& i = *new int; Prin intermediul acestci declarati i (dcfinitii) se aloca in memoria heap 0 zona de mernorie in care se pot pastra date de tip int, Numele i permite refcrirea la intregul pastrat in zona respectiva, Expresia de atribuire:
i

au aceeasi valoare, De asemenea, atribuirea:


j,,12345

100

pastreai[\'lntreglll

100 in zona rcspcctiva.

Zonele de memorie alocate cu ajutorul operatorului In acest scop se utilizeaza 0 expresie de forma: alocata pentru i.

new pot fi initializate.

pastreaza intregul Declaratia:


int & j=i;

12345 in zona de memorie

new .~~_<_, ~..~,_~ tip(expresie) _ unde: til) expresie


Exemple:

c"_'~' .. -, ,_, '.-'-« _ •.

- Este numele

unui tip. initializcaza zona de mcmorie

trebuie interpretata ca fiind proeedeul prin care j sc defineste a fi un nume sinonim pentru i. Acest mod de intcrpretare a declaratiei de mai sus difera de sensul obisnuit al initializarilor care se fac prin declaratii, Variabilele referinta se utilizeaza memorie alocate dinamic in memoria frecvent pentru heap. • a avea acces la zonele . de

Este 0 expresie a carci valoare alocata prin operatorulnew.

1.

double pdouble

*pdouble;

new double(3.14159265);

20.5.3. Operatorul de alocare dlnarnlca a memoriei (new)


In limbajul C se pot aloca zone de rncmoric in memoria heap folosind functii de biblioteca, Astfel de functii sint, de exemplu, functiile malloc si calloc (vczi

8.8).

Accasta instructiune realizeaza urmatoarele: aloca in memoria heap 0 zona de mcmorie in care se pastrcaza valoarea 3.14159265 In (lotanta dubla precizie; adresa de inceput a acestei zone de rnernorie sc atribuie variabilei

pdouble.
double& pi " *new double(3.14 59265);

In afara acestor functii, limbajul C++ permite alocari in zona heap prin intermediul operatorului new. Acesta este unar si are acceasi priori tate ea si ceilalti operatollUllliri-. --_ '. Qp<::l'at{)rlll_r!.011'~E.~,~~!_ va!.Q~~e..adresa .. ~,jnceE~lt a ..2onei .. e memorie alocata d d !1~_,~~~1?I:i'l_Jl(~(lpS'\1]. zero. (pointerul nUl) in cazl~j il;'c~lrc l~llse pmltcfl~~e alocarea, Q£~~aI1dul operatoruluinew in cea mai simpla :r. (predefinit sau definit de utilizator). Exemple: forma, este numele unui .

Prin accasta declaratie se rczerva, in memoria heap. 0 zona de mcmorie in care se pastreaza valoarea 3.14159265 in flotanta dubla prccizie. Data respectiva se poate referi Cll ajutorul numelui pi. De exemplu, pi poate fi utilizat in mod obisnuit in cxpresii de forma:
pi*r*r sin(pi/2) x*180/pi

etc. alta utilizare importanta este aceea de alocare memoria heap, pentru tablouri. In accst seep, utilizam 0 expresie de forma:
_l_ICW

I.

int *pint; pint" new int;

a unci zone de memorie,

in

Prin intermediul acestei expresii, se aloca in memoria memorie in care se pot pastra date de tip int. Adresa
*pint

heap,

zona de

de inceput a zonei alocate


" 100;

se atribuie pointerului

pint. Expresia:

tip[eXJ!1 __ - Este () expresie de til) intreg. 19

unde: exp

18

Prin accasta constructic


e.lp*sizcof(tfp) octcti,

sc rczerva,

111

memoria

heap,

zona de mcrnorie de

Valoarca exprcsiei de mai sus, este adresa de lnceput a zonci de mernorie rczcrvata prin operatorllll1Clv.

Exemplu:
c1uuhlc

La IIti Ii~~_gE!.t9IL.!l.U.Ut!'l~LC:.,.t::cS!£, .. n}J?()r,t."!DL~.Qintqlll.l'!;_t::!\It::_'it::_.!ll2.Uca } sit a ibtt 0 ,:,:~I.9arc_ b.ti:~S.§LE~.l£~ult~1!_~L~JLS.~Eii..PE£~htEi.!~_~9.Pc-~:!?_~!.1_11,1_!/_e.1~ 0 Daca operatorul delete se aplica la un pointer nenul a carui valoare nu a tost obtinuta en rczultat al aplicarii opcratorului new, atunci efectul aplicarii lui delete este irnprcvizibil,

*tilb;

int tab

m,ni

20.6. Apel prin referinta (call by reference)


In limbajul C apelul se face prin valoare (call by value). Aeesta devine prin referinta cind paramctrul efectiv cste un nume de tablou (vezi 4.15.), De asemcnca, apclul prin refcrinta se po ate realiza Cll ajutorul pointerilor (vezi 8.2). 1n capitolul 8 sint date 0 serie de exercitii care utilizeaza pointerii pentru a realiza
apelul prin referinta (ex. 8.1,8.2,8.3,8.6,8.7).

new douhle[m*nl;

Accasta instructiunc rczcrva in memoria heap 0 zona de m1'n*sizcof(douhlc) octcti. Adrcsa de inceput a acestci zone de mcmoric se atribuic pointcrului tab. Elcmcntelc unci astfel de zone de mcrnorie nu pot fi intializatc decit numai prin sccvcnte de program corcspunzatoarc. De cxemplu, pcntru a anula ccle m*11 clemente de tip double rczcrvatc ca mai sus, putcm folosi instructiuncarz» de mai JOS:
for ( i; i < rn* n; i ,.) + tab

r i )= 0 . 0 ;

20.5.4. Operatorul de dezalocare a memoriei (delete)


delete.

In limbajul C++ se pot utiliza toate facilitatile amintite mai sus ell privirc la ape lui functiilor, in plus, s-a introdus apelul prin referinta. Acesta sc realizeaza prin intermediul parametrilor de tip referinta. Exemplul devenit deja clasie pcntru explicarca apelului prin referinta estc cel al functiei de permutare a valorilor a doua variabile. Fie Iunctia perm definita ca mai jos:
void
{

o zona

de rncmoric alocata prin operatorul

new sc elibercaza

prin operatorul

perrn(int x,int

y)

int t; t
}

TEc;) fJ cstc un pointer spre tip: lip *p;


~l

x; x

y; Y

t;

Accasta p
=

functie

nu arc mel un efect asupra

parametrilor

cfcctivi

de la

new tip;
Cll

atunci zona din memoria heap alocata


construcua: delete De asemcnea, opcrarorul delete

ajutorul lui new se elibcreaza

folosind

apelurile ei. Intr-adevar,


int a,b;
perm (a, b) ;

tic apelul:

se utilizeaza

pentru

a dczaloca

tablourile

alocate prin new.


Fie alocarca:
11.1)

*p c= new tljJ[expresie];
II) losind () constructie

Accasta zona sc elibcrcaza delete lcxprcsiej


It {

de forma:

p;

i,a ,e',He defineste clemcntelor tabloului nu este totdeauna ncccsara la dczalocarc, Mai tirziu, vom revcni asupra operatorilor l1ew S;idelete si vom indica situatia cind cste ncccsara prczcnta dimensiunii tabloului In dezalocarea lui.

M;~ti~;~~f;~~-~~;;;;I;~~,

nurnarul

Apel111 fiind prin valoare, se atribuie parametrilor formali X si y valorile lui a si respcctiv b. Functia permuta valorile parametrilor formali x si y dar aceasta permutare nu are nici un cfect asupra parametrilor efcctivi a si b. Pcntru ca functia sa permute valorile parametrilor efectivi este nccesar sa se realizeze apelul ambilor parametri prin referinta. tn limbajul C (~i deci ~iin iimbajul C++) este posibil sti rcalizam acest lucru folosind pointerii, ea mai jos:
void pperm(
{

int *x,int

*y)

int t;

20

21

::.*x;

*x

*Yi

*y =

t;

in acest caz, functia pperm se apeleaza astfel:


int a,h; pperm(&a,&h) ;

Prin ~cest apel se atribuie pointerilor x si y adresele pararnetri lor a si respectiv b. Funcyapp:rm.nu pe~uta.valorile pointerilor x si j: ci valorile intregilor spre care pomteaza cei doi pomten, adica chiar valorile lui a si b. . In liI_TIbajulCt+ se poate defini functia de permutare cu parametri formali de tip referinta:
void
{

In cazul functiei din exercitiul 6.3, numarul citit se atribuie variabilei globale in cxcrcitiul 8.2., pastrcaza nurnarul citit in zona de memorie spre care pointeaza pararnetrul formal x de tip pointer. .. ClI alte cuvinte, aceste functii sint 3 variante pentru a citi un intreg de tip II1t dupa ce, in prealabil, ele afiseaza un sir de caractere. Functia definita in cxercitiul 6.3. estc varianta care utilizeaza 0 variabild globala, cea din exercitiul 8.2. este varianta cu pointer, iar functia definita mai jos estc varianta cn pararnetru de tip referinta (apel prin refcrinta).

v int. Functia dcfinita

FUNCTIA BXX4
int rcit_int(char text[] ,int& x) /* _ afiscaza sirul de caractcrc sprc care pointcaza text; _ citcstc un intrcg si-I pastrcaza in zona de mcmoric alocata paramctrului corcspunzator lui x; rcturncaza: 0- la intilnirca 1- altfcl. */
{

rperm(int&

x,int&

y)

cfcctiv

int t : t
}

x; x

y; y = t;

sfirsitului

de fisicr;

Functia rperm se apeleaza astfel:


int a,h; rperm (a ,h) ;

char

t[255];

. In acest_ caz. x ~i y sint sinonime cu variabilele a $i respectiv b. Aceasta msearnna ca x ~l y acceseaza aceleasi date din memorie ca si a si b. De aceea p.ennutarea valorilor referite de x si y inseamna permutarea v,;lorilor referite de ; $1 b. . Comp.arind functiile perm ~i rperm observarn ca de se apeleaza la fel si smgura dlfere~ta dintre ele consta in modul de declarare al parametrilor formali. In cazul functiei perm parametrii formali sint date de tip int, iar in cazul functiei rperm acestia sint ref~.!inte la_dat~~~_tipint. . Exercitii: 20.4 Sa s.escrie 0 functie care afiseaza caracterele unui tab lou ~i citeste un intreg de tip tnt. Functia are doi parametri: text: - Tablou unidimensional de tip caracter 5i care are aceeasi utilizare ca in exercitiul 6.3. - Parametru de tip referinta la intregi de tip into Numarul citit se pastreaza in zona de memorie alocata parametrului efectiv corespunzator lui X.

for (; ;) ( printf(text) ; if(gets(t)==O) return 0; if(sscanf(t,"%d",&x)==l) return


)

1;

Ohservatie: Functia de
int
ni

fata se apelcaza prin apeluri de forma:


... )

if(rcit_int("n=",n)){ else // tastat EOF s-a

Parametrul 20.5

x este sinonim cu n si de aceea la apelul functici sscanf. cxprcsia care citeste un intrcg de tip int care apartine unui

.)<

&x inseamna &17. S:t sc scrie 0 functie interval dat.

x:

Aceasta functie este analogs cu functia definita in exercitiul 8.3. Ea foloseste un parametm de tip referinta in locul parametrului de tip pointer pint al functiei din exercitiul amintit mai sus. FUNCTIA BXX5
int rcit_int lim(char text[],int Ln f i nt; sup,int
i

Functia rcturneaza valoarea zero la intilnirea sfirsitului de fisicr 5i unu in caz contrar. Aceasta functie este analoga cu functiile definite in exercitiile 6.3 si 8.2.
22

& rin t

23

1*

afiscaza simi de caracicrc sprc care pointcaza text; citcstc lin illlrcg de lip inr cc apartiuc inicrvalului [inf.sup] si-] pastrcaza rncmoric aiocuta parumctrului cfcctiv corcspunzator lui rint; rcturncaza: 0- la intilnirca I - altfc! sfirsitulu: de fisicr;

ill zona de

II validate data calcndaristica if: (v_oa lerid (1'2 i, rl una ,ran l) r ot urn .. pri,t1tf("'data calendarist,ica este eronata\n p rin t f (IISE~ r o i.a citirea da t.o i ca lerida r is t j.c e vr:')
ll );

*1 for (;;)( (rcit_.int(text,rint)==O) return if(rint >= inf&&rint <= sup) return printf('intregul tastat nu apartine printf (' [%d, %d] \n', inf, sup) ; printf('se reia citirea\n');
j }

20.7
0; Ils-ainlilnitEOF 1; intervalului:');

Sa sc modifice functia din cxcrcitiul Si l , inlocuind pararnctrii de tip pointer eu parametrii de tip rcfcrinta.

FUNCTIA BXX7
void rluna_si zlua(lnt ZZ,lnt an,int & zi, inti luna) 1* dctcrmina luna 51 ziua din luna; zz - cstc ziua din an; an cstc anul calcndaristic: zi - rcfcrinta la zona in care sc pastrcaza ziu» din luna; luna - rcfcrinta la zona in carl' sc pastrcaza luna. *1
{

20.6

Sa sc scrie 0 functie care citeste 0 data calcndaristica cornpusa din zi, luna ~ian. Functia valideaza data calcndaristica respective. 8.4. Deosebirea 8.4. sint de tip

Accasta functie este analoga cu functia dcfinita in cxcrcitiul dintrc ele consta in accca ca parametrii functiei din cxcrcitiul pointer, tar eCI din exercitiul de fata sin! de tip referinra. FUNCTIA BXX6

int bisect = an %4==0&.&an%100 Ilan%400==0; int ii extern int nrzilell; [or (i ,1; 2i luna z zsn rz i.Le 1+ (i==2&.&bisect); j ++) [i zz -= (nr'Zile[i]+(i==2&&bisect));

int rcit_data_calend(int& rzi,int& rluna,int& ran) 1* - citcstc data calcndarisnca, 0 valideaza si 0 pastrcaza in zonclc dc mcrnoric alocatc parumctrilor cfcctivi de la apcl; - rcrurucaza: () - la inulnirca sfirsitului de fisicr: I - altfcl. *1
(

i;

20.8

Sa sc scric un program care citcstc calcndaristica pentru ziua urmatoare.

datil calcndaristica

~i afiscaza data

tatic char ziual] static char lunal] s ta t.I.c char ani] static char erl]

ziua: "; "luna:" ;


II

Ilan: II;

Accst program cste analog cu cele definite in excrcitiilc 6.9. $i 8.5. Programul de fata foloseste functii care utilizcaza pararnetri de tip rcfcrinta pentru intcrfata in locul variabilclor globale sau al pararnctrilor de tip pointer. PROGRAMUL BXX8

's-a tastat

BOF';

for (; ;)( II se citesrc ziua, luna sianul if(rcit_int_lim(ziua.l,31.rzi)==O) printf("%s\n",er) ; return 0;

if (rcit_int._lim (luna, 1,12, rluna) ==0) ( printt('%s\n',er) ; return 0; if(rcit_int_lim(an,1600,4900,ran)==0) printf('%s\n: ',er); return 0; (

~include #include 'include #include #include #include Irinclude .include

<stdio.h> <stdlib.h> 'bxx4.cpp' "bxxS.cpp" "bvi5. cpp" 'bvi6.cpp' "bxx6.cpp" 'bxx7.cpp'

functia rcit _int functia rcitjnt lim functia v calend functia zi-din-un 1/ functia rcit rlata calcnd 1/ functiarlunasizioa

II II /1 II

int nrzilel] main () /* citcstc aliscaza

= [O,]1,28,31,30,]l,]O,31,31,30,Jl,30,31};

data calcndaristica, dara calcndnrisrica

0 validcaza si in caz ca cstc corccta, a zilci urmatoarc *1

24

25

tnt

zZ,ll,aa;
data calcndarisricu

i=nrlin*nrcol; if(i <, max) break;


print.[("produ:;uJ.
mAll 't,(J

d(milscst

/1 citcstc si validcaza

printf("se exit(ll;
din anul urrnator
j wh i Le (1);

r eiau citiril

r» llIilx,'j:ti\n",i,llh"'); lui m si n\n");

f(rcit_data_ca1end(zz,11,aa)==01 if(zz==31&&11==121 {
/* 31 dcccmbric; ziua urmatoarc z2=1; II I ianuarie

cstc 1 ianuaric

*1

1* sc eitcse ccle m=n clemente ale matricci i f (ndc i t ( 1, dma tI' = i 1 {

rastatc pc linii *1

11=1 ; aa++; else

II anulurrnator

printf("nu exit (1. 1;


i
i

s-au

tastat

%d elemente\n",il;

II se detennina ziua urmatoare r1una_s i_2 iu a (2i_dino_an (2Z , 11, aa 1+ 1,aa, 2 Z , III ; data calcndaristica a zilei urmatoarc
.

return

II afiscaza )

printf("ziua:%d\tluna:%d\tan:%d\n",zz,11,aal;

20.10 Sa sc sene un program care citcste elernentele de tip double ale doua matricc a ~ib, calculeaza prcdusul lor si-l afi~eazil.
Acest program este analog cu eel din exercitiul in cazul programului de sc Ioloscsc functii locul functiilor 8.7.
Cll

20.9 Sa se serie 0 functie care citeste: valoarea variabilei m de tip int; valoarea variabilei JJ de tip int; m*n numerc care reprezinta elementele unci matrice de ordinul m*n. Functia de fa ttl este analoga ell functia definita in cxercitiul 8.6. Ea foloseste parametri de tip referinta in locul paramerrilor de tip pointer. . FUNCTIA BXX9
int rdcitmat(double
1*
0 0 0

pararnetri

de tip refcrinta

in

eu parametri

de tip pointer.

PROGRAMUL BXX10
Hinclude #include #include Hinclude Hinclude Ilinclude II .nc i 1ude <stdio.h> <stdlib.h> <conio.h> "bxx4.cpp" "bxx5.cpp" "biv.37.cpp" "bxx9. cpp"

dmat[],int

max,int&

nrlin,i~t&

nrcoll
dmat prin liniarizarc;

eitcstc pc m numar de linii; n numar de coloanc; m*n nurncrc de tip double pc care Ie pasrrcaza in matricca rcturncaza valoarca m+n: valoarca lui m sc pastrcaza in zona refercntiata de nrlin: valoarca lui n sc pastrcaza in zona rctcrcntiata de nrcol.
0

Ilre;1 int Ilrcii inrIim /Indeil II rrlcitmat

Iidefifj(~AX 900 M rna (I 1* citcslc clcmcntclc in


afiscaza
.i.n t.

mntricca

a dona m.uricc, cnlculcava si produs, cite 4 clemente pc 0 linic *1

*1
{

int i· char t [255]; char err] = "s-a tastat do {

int int

.i, j , k; m/n,p,s,r/q; mTl,np;

EOF\n";

double

a [MAX] ,b[11AX] ,c[I,II\X);

II secitesc valorile lui si n 111 II citcstc pc m if (rcit_int_lirn( "numarul

printf (erl; exit(1.I;

de linii=", 1. ,max,nrlinl ==0) {

/1 citestc matricca a rnn=rdcitmat(a,MAX,m,nl; /1 citcstc matricca b np=rdcitmat(b,MAX,p,s)


.i f t n l r p ) { p r i.nt.f (Ilnuma:.Lul

;
colo(:1fu::.lor

II citcste pe

matricei

a:.:::%d\n",n);

11

if(rcit_int_lim("numarul printf (erl ; exit(ll;

de coloane=",l,max,nrcoll==OI

printf("difera de liniilor printf("matricei b=%d\n",pl; "xi t (11 ;

"I;

26

27

if Sc' calculc.rza produsul c a*h lo: t i ; i <m. i ,t- +) {


C] :.:. i'~ !\ •.
;

re t.u r n Pi

}ell':E? return
)

(); 111111 s-a [lUIIiI rczcrvn zona in memoria heap

;j

,)

lr I o . 0; [orlk=O;k<n;k++)
c[rl I kl'b[k'",jl;

20.12

S~lsc scric un program care circstc () succcsiunc


eel mai marc.

de cuvintc si-] afiscaza

pc

Accst program cstc analog cu eel din cxercitiul 8.16. in cazul de falil, sc utilizeaza operatorul delete pcntru a clibcra 0 zona de memorie din zona heap
sprc dcosebirc functia free.
procius\n
li );

de programul

din excrcitiul

8, I 6. care utilizeaza

in acest scop

;/ ,iliscaza

l'Ic;Il1CIlICle matricci

produs

IJ'(J

f ("

n\n\L\t
i++)
;

matr,ic>?a
{

k r• for (.i.-;::c;Oi)<rn; p ~;:_i Af ortj

PROGRAMUL

BXX12

~include <stdio.h>
,'kdJe%8q

O;j

;jl+)(

in tr ivc l
[[ljMe:])(

",i.,j,c[p+jl);

ftinclude <string.h> tlinclucle "bxxll. c pp " liclefineMAX


100

Illlmcl11sir

il «Iisc,va 4 clemente pc lIll rind print ("\n"); k I I; 1IIIIIIIl'Iralilliik (k=


print

main () I"~citestc 0 succcsiunc de cuvinic si-! ufiscavn pc eel mai marc "I
(

3) (
("

ri oria
;

rr

t.a

ta

a contlrlUa\n");

gecch{)

char cuvcrt[MAX+l]; char *cuvmax=O; /1 pointeaza

spre cuviruul

rnaxim

k= 1.;

rilllf("\n");

20.1 I Sa sc scrie

0 functie care pastrcaza un sir de caracterc inrr-o zona de mcrnortc alocata in memoria heal) Cll ajutorul opcratorului new. Functia rcturncaza adrcsa dcinccput a zouci in care sc pastrcaza siru] de caractcre suu zero (pointcrul nul), in cazul ill care Ill! sc poatc rczcrva zona respective in memoria heap,

while (ac arif("%100s" ,cuvcrt) ! ,cEOF) if (cuvmax« = CI) II prima cit ire cuvrna x- nrnerns i. r' I cuvc r t.) ; else if (strcmp(cuvcrt,cuvmax) >0) { 1* cuvintul citit cstc mai marc dccit cel din memoria heap si sprc carc pointcaza cuvmax */ delete cuvmax; II sc clibcrcaza zona din memoria II sc pasrrcaza cuvintul citit curcnt in memoria heap
cuvmax::::nmemsir(cuvcrt) ;

heap

printf("cel mai mare cuvint p r i n t f ("~;s\n",cuvmax ) ;


}

este\n");

Accasta Iunctic cstc analoga ell functia din cxcrcitiul 8.15. Accasta utilizcaza Iunctia malloc pcntru a aloca zona de mcmoric heap. FUNCTIA BXX11
(char
Ili\strc;lza ill memoria heap sin!! de caractcrc sprc care pointcaza s

din urma

20.7. Functii care returneaza date de tip referinta


in limbajul C++, 0 functie po ate rcturna 0 referinta oarccare. In acest caz, tip din antetul unci functii arc forma: tip&
la
0

datil de un tip

*/

if

((

)( +1 J ) * p arc ca valoarc adrcsa de inccput a zonci de rncmoric memoria heap si c.uc arc sulcrus)« I octcti *1 ,; t repy (p, ); II copicrca xirului ill mc nuuia heap

char[str

(s)

rcvcrvata

in

Exemplu:
typedef: struet double x;

28

29

double y; ) CONPLEX; COMPLEX Z; double& double& re im retreal (z) ; retimag(z) ;

typedef struct COHPLEX z : c1oul)le [[IDdu"1 i double arg; } NRC;

Functiilc
imaginarii
(

retreal si retimag rcturncaza refcrinta la partca rcala 5i rcspcctiv a numilrului complex z. Ele se definesc ca mai jos:
retreal(COMPLEX&
C.Xi

cca

5i declaratia:
NEe nrc;

double& .return double&


(

c)

Pentru a ne referi la componentele


calificat:
nrc. z. x

x si yale

datei nrc se utilizcaza

numcle

pcntru partca rcala

retimag(COMPLEX&
C,Yi

c) nrc. z.

return

y pcntru partca imaginara,

rcturl'!eaz,lorefcrint<l poatc f apclata atit in dreapta semnului ~l cit sijll~sti]1ga.Un a~tfel de ape I este un operand atit /valuecii-ii I:~;;I/{~;(v~~i 8.7.). De exemplu, functiile retreat si retimag pot fi utilizate numarul complex z din exemplul de mai sus, scriind:
retreal(z) retimag(z)
1;

o funqiccarc

De cxernplu:
nrc.z.x nrc.z.y
:=

3i

4;

pentru a initializa

.. '.. definesc partilc reala $i respectiv nnagmara a compone ntei z a datei structurate " nrc. Acclasi lucru sc rcalizcaza folosind urrnatoarclc atribuiri:
nrc.retreal(nrc.z) nrc.retimag(nrc.z)

-3;

Prima instruc(iune
z. x
1;

are acelasi efect cu atribuirea:

3; = 4;

sal! daca considcram dcclararia:


CONPLEX& rc

iar cea de a doua, cu atribuirea:


z. y 3;

nrc.z;

atunci acclcasi atribuiri pot fi sense astfel:


nrc.retreal(rc) nrc.retimag(rc)
c

Evident, atribuirile de forma z.x = ... ;;i z.y = ... sint operatii simple care nu sc justifica a f inlocuite prin atribuiri in care se apelcaza functiile retreal si retimag. Astfel de apeluri se utilizeaza in cazul in care functiile apelate reprezinta procese de calcul mai cornplexe. Apelurile functiilor care returncaza referinta, fiind operanzi de tip lvalue, lor Ii sc pot aplica opcratorii de incrementarc si dccrcrncntare Astfc], instrllC\illnilc:

3; 4;

Exercltii: 20.13 Sa se scrie 0 functic care calcu Icaza rcturneaza a rcfcrinta la el. ell cca dcfinita
1110 d u I II I

unui numar 10.1.

complex

~l

~i

---------"--.
retreal(z)++;

++retreal!z);

Accasta functie cstc analogs FUNCTIA BXX13

in cxcrcitiul

double& rrnodul(COMPLEX& z). /* calculcaza modulul numarului complex static return

SI

rcturncaza

_ . , . 1*/ () rcfcrinta 1.1 c

--Ill prlncipiu,

sint corecte ~icle incrcmenteaza partca reala a lui z, ~relull!nci care retumeaza 0 referinra trebuie considerat ca ~~L~ll_ll1ar reprezenta Ul1l1ume. De exemplu, este echivalent CLl numclc calificat z.x. Fie tipul:

double c; c=sqrt(z.x*z.x+z.y*z.y);

20.14

Sfl se serie 0 functie care calculcaza

argumcntul

unui numar complex ~i


31

30

rcturncazn

rcfcrinta la cl, in cxcrciiiul 10.2.

# inc lude
#include

ACeaSUI Iunctic cstc ill1;dog<\ ell ccn dcfinita FUNCTIA BXX14


doubJ r ar ICOMPLE:X8, z)

"bxx13. cpp" "bxx14 .. cpp"

II rmodul Ilrarg

main( ) 1* citcstc numcrc cornplcxc si Ie afiscaza imprcuna ell modulul si argumcntul ficcaruia *1
{

calculcaza

argumcntul a;

numarului

complex

si rcturncaza

o rcfcrinra

la cl *1

COMPLEX complex;

tic double
,I (2.;"

while
0) r e t.u r n a"O.l); }
}

(scanf printf

if I z . y
e 1 sell

0 && Z.y 0)

p r int f ( "a+ ib=%'1+ i * (%'1) vn " ,complex. r a r q t cornp Lex j ) ;

%If'', &complex. x , &complex. y) ==2) ( x , complex. y) ; ("modul=%'1\ tar'1=%'1\n", rmodu I (complex) r

( ''%If

if I .x >0) return
y=O si x ,,0 return a::f:iI; iI .x == 0) i Iz.. y> 0) return

a=O.O;

ro t.ur n a='PI/2;

13*

)/2;

20.8. Modificatori
Modificatorii sint cuvinte cheie care se utilizeaza in declaratii sau definitii de variabilc si functii. Cei mai folositi modificatori utilizati la definirea functiilor sint: cdccl, pascal, near, far si huge. Sensul acestor rnodificatori este amintit in paragraful 20.2. In acest paragraf amintim modificatorii utilizati mai frecvent in legatura variabilele, Acestia sint: const, near, far si huge. cu

II x !. () si y !== 0 a~:at"iJn(z.y/z.x) ;

i ( .x
e,l

<: 0) /1 x < () si y ~= 0 r c t urn a=a+PI;

it (
x

.y

<

0)

Ilx > 0 xi y < () a::::2*PI+i:'li

return

0 si Y > 0 r oturn a;

Observatic: Variabi laa a fost dcclarata statica din cauza ca functia rcturncaza 0 referinta la ca (se utilizcaza instruqiunea return a;). . Dac:I variabila a ar f fost autornatica, ell s-ar f alocat pc stiva, in accst caz () rcfcrinta la ea nu arc sens, dcoarcce la revcnirea din Iunctic se face curatirca stivci :;;idcci variabila a este dczalocata, . . 20.15 Sa se scric un program care citcste numere cornplcxc ~iIe afiscaza imprcuna cu modulul :;;1 argumcntul ficcaruia, BXX15

20.8.1. Modificatorul const


in principiu, modificatorul const se utilizeaza in definitii sau declaratii pentru a defini date constante, Cu v in tu 1 ch e ie c(ll1sttre~_lli~_c:gI1si_d~!~J_(;~_l!1()9:ifi(;~_!!El!!~n e ida te .res tringin d J110dul de'=!_t_iljL:,:!re<lLqatc:i_I.9_~J.~_c:tb'(;,__ - -----.--.. --Deobjeei, cuvintul const precede, in declaratie, tipul datei. Exemple: 1. 2. 3.
const const const int int versiune pi [] xcif = 3; = 3.14159265358979; {'a','b','c','d','e','f'}; double

PROGRAMUL

1ude <stdio.h> Ninclude <math.h> ffdefine


t y})(~(l(.:f

PI

.14159265358979 t

s true doub l o x; double" y;

Datele declarate (defu:!i~)_jl_l_~(;~g__f(;l_~~_pot _ _ fi_l~dificate atribtlu:icte ... fo!:rna: ---.-.~--,versiune = 4; pi = 3.14159; xcif[O] = 'A';

di~_0Lj~ci

)Cot1PLEX;

32

33

?jn!~eron(jlC ... l_lltr~odeclar'lti(;JclcfiI}itic) Sl!11Iletlpul. In


const an 1995;

JOs:

..in care scutilizcaza.Ill()dilic(lt,QruL~:.c~rl:~/ '-sc ponte ..tiplllJI1I. Astfcl, constanta declar:lt;;'ca;ll:ii

De exernplu,
COflst

fie declararia:
*COI1St atr'ibut "IBM PC";

cllar

are tipuI int .

~.1 c

o construcne

Modificatorul

CO/1.1'/ are utilizari importantc de forma:

mai ales in legatura

CLl

pointerii.

In aces! caz, atribut cste llI1 pointer constant sprc un sir constant de caractcrc. Amintim ca rnodificatorul COliS! se utilizeaza frecvent In dcclarurca paramctrilor formal: de tip pointer pcnrru a intcrzice functiilor respective modificarca datelor spre care pointeaza paramcrrii rcspectivi. Astfel de pararnetri se intilnesc, de cxemplu, la functiile de prelucrarc a sirurilor de caractcrc:
unsigned strlen(canst char 's); char *strcpy(char *dest, canst char'sllrsa);

~efinC9tc un pointer spre 0 data constanid. De exemplu, Rc'c!eclaratia:


const char "sir

etc. Functia strlen nu poate modifica data sprc care pointcaza s. In mod analog, functia strcpy nu poate modifica data spre care pointeaza sursa. Modificatorul const poate fi urilizat si pcntru a proteja 0 data returnata de 0 functie. De exemplu, functia de mai jos retumcaza un pointer sprc un sir constant, care nu po ate f rnodificat in mod accidental (direct).
const char "denlun(int i) /* rcturncaza UI1 pointer la dcnurnirca lunii a i-a */
(

"abc";

Prin aceasta declaratie atribuirile de forma: '*sir=


* (sir+1)
'A';

sir devine

un pointer

spre un sir constant.

Deci

~ 'B'

etc.

sint eronate. o constructie

de forma:

*const IIIlme == ....


defincste

jJointerconsta!l!spreo data care nu este constant~\. De exemplu, fie declaratiile: . " ~ "' ~ -~- -LIn

static const char *tdl[J = {liluna ile9a1a .i.ariue ri.e :' return (i. < 1 II i > 12) " tdl [0]
HI 01 I' ••

IIdecembrie

ll

: tdl[ i J ;

char "canst psiI' = "abc"; char +'·s; const char *sir = nsir";

Protectia datelor obtinuta cu ajutorul modificatorilor canst nu este totala. Intr-adevar, daca vorn considera declarariile de mai jos:
const char char
*Si

Atunci,
sir

atribuire de forma:

*sir

:::: !!abe'!;

este corecta, dar:


psir ::; S

atunci
S

atribuire de forma:

:::: sir

nu este acceptata deoarece psir estc un pointer constant.


*psir
" (p

in schimb, auibuirilc:

'A' 'B'

si.rrj)

esrc cronata dcoarece sir ~i s smt pointeri de tiplll:i.di{erite: sir estc un pointer sprc 0 daHl cOllstanic;de tipcaracter, spre 0 data de tip caracter. . .. . Tn schimb, 0 atribuire de forma:
s = (char ")sir

iars este un pointer

"(psir+2)

'C'

sint corecte. Este posibiI sa se defineasca un pointer constant spre acest scop se utilizeaza 0 declaratie (dcfinitie) de forma: const --34
.._"-"_'"-"',,

dat,1_constant[1. in

tip *const nume = ... ;


.._

este corecta, In continuare s pointeaza spre acecasi data ca si sir. Cum s nu a fost declarat cu ajutorul modificatorului const, rezulta atribuirile de mai jos sint Icgale:
*s :::: A! i
!

ca

*(s+l)='B';

35

*(s+)=

C';

In fclul acesta, data "abc", protcjata cu ajutorul modificatorului COilS I, a putut fi rnodificata eu ajutorul pointerului s. 0 modificare de accst fcl sc spune ca este o modificare indirecta. Modificatorul cons! nu pcrrnite modificarea directd a datei, adica modificari de forma:
*sir * (s
* (sir+2)
1)

utilizare a lui void este in legatura cu [unqiile revenirea din ele:----·---void numet ...)

care nuretumeaz~ ()valoare la .------.. --..- -... - -.. ---.-.----

In fclul acesta, modificatorul canst protejeaza modificari dirccte care pot survcni in urma unor erori.

datclc

irnpotriva

unor

Tot in antetul unci functii se poate utiliza cuvintul void intre parantezele care urmeaza dupa numele functiei, In acest caz, voi~il~ic~J~J2l~II'?fi_LI!I1~Ji~_t:!_u_rc a E'l:~'lll1etri. Utilizarea lui void pentru a indica absenta parametrilor nu este obligatorie. In schimb, este obligatoriu ca void sa apara inaintea numelui functiei cind aceasta nu returneaza 0 valoare, Aceleasi rcguli se aplica si la prototipul functiilor. Exemple: 1.
void f (void) ;

20.8.2. Modificatorii near, far ~i huge


Acesti modificatori sint spccifici limbajului TURBO C++. Ei dau posibilitatea utilizatorului de a defini explicit dimcnsiunea pointerilor: 16 sau 32 biti. in cazul limbajului C, modelul mcmorici (tiny, small, ...) determine formatul intern al poinlerilor. In C++ sc pot folosi dcclararii de forma: tip modificator "nume;
unde: 2.

Functiajnu
void 9 () ;

are parametri si nu returneaza ;;i nu returneaza

valoare, valoare.

Functia g nu are parametri

o alta utilizare a euvintului universal:


void *

cheie void estc aceea de a defini un tip pointer

modificator

- Estc unul din cuvintele chcie: near.far sau huge.

Un pointer spre void nu arc tipul precizat, VI~J1?~nte!·"rir<:_ul'lJip"pre.<::i'2:l..lt_scIJg'1Jel..ltribui .cli.reetuI1"l!ipointersprc. Fie de(Iara\iile: .----~ tip *p; void *pv; unde: tip in acest caz,
pv = p;
0

void:

Modificaiorul near spccifica faptul ca pointcrul sc rcprezinta pc 16 biti. Ceilalti modificatori forteaza reprezentarea pointcrilor pc 32 de biti. Utilizarca accstor modi fica tori poate conduce, uneori, la economic de memorie ~i de limp calculator evitind lucrul cu pointerii pc 32 de biti cind acesta nu este nccesar. Difercnta dintre modificatoriire- si huge se manifcsta la calculelc ell operanzi de tip pointer. Operatiile eu pointeri de tip far pot conduce uneori la rezultate eronate sprc deosebirc de celc realizate asupra pointerilor de tip huge, operatii care se cfcctueaza totdcauna corect, dar sint rnai costisitoarc in tirnp. Acesti modificatori nu sint necesari pentru programc de dimensiuni relativ mici si care nu utilizeaza volume mari de date. Programcle din volumul de rata se incadrcaza in aceasta categoric si de aceca nu vom utiliza acesti modificatori in exercitiile care urmeaza. o exceptio de la aceasta regula 0 constituie functiile standard pentru gestiunea grafica a ecranului care implies modificatorulja-.

- Este diferit de void. atribuirc de forma:

este corecta. In schimb, atribuirea


P

inversa, adica:

pV;

cste eronata. Astfel de atribuiri


JOs:
p

se pot realiza numai folosind conversii

explicite,

ca mai

(tip*)pv.

20.9. Cuvintul cheie void


Cuvintul cheic void arc difcritc utilizari in functic de context. 0 prima
pv++ pvpv+n

36

37

pv-n

sint eronare. Pentru a putea face operatii cu astfel de pointeri este nccesar sa se foloseasca conversii explicite:
(int *) pv +n (double *)pv-n

De ascmcnca, 0 tunctic ponte rcturna la () struct ura:


.. __ ,_"._ ~. ,__ "' .. " u_."_·".

strllcttlt:,l,unl1_ointer
"

sprc

struciura

S;IU

· __.··_·_·_·_·_··_· .."•..._.,-, .. ",,,_.,,--,»

numc g 1( ." ) { ." }

nume *g2( nume& g3( de

)1 ){

_ returneaza I _ retumcaza } _ returncaza

() data de tip numc; un pointer sprc 0 data de tip numc: 0 refcrinta la 0 data de tip numc.

etc. in general, se vor evita astfel de operatii deoarece ele pot conduce la erori.

Structurile Fie:
nurne

atribui direct una altcia.

al, c:l2 i

20.10. Structuri
In limbajul Cs+ se pot defini tipuri noi folosind declaratia struct ca in limbajul C(vezi capitolul 10). De asemenea, se pot atribui nurne Ia tipuri predefinite sau definite de utilizator folosind constructia typedef. Pentru tipurilc definite cu ajutorul lui struct putcm defini date ca mai jos: struct nume { }; struct num e numel,nume2, ...; In limbajul c++ nu mai este necesara utilizarea structurilor nume J, nume2, ... , de tipui nume: Deci, vorn scrie mai simplu: nume nume l , nume2, ... ; unde: nume - Este tipul utilizator sus. definit printr-o constructie struct ca rnai lui struct la dcclararea

Atunci atribuirca:
a 1 ::: a2

este legala.

20.11. Reuniune
In limbajul CH, l~l\a de limbajul C, r(;~nlitlnilel)()tQ __ il:iJi<lJlzate. Ini\iaJ_i~.a:-e~l se_p_oate reaijza-m:;n~ai prima componenta a ei.

Exemplu:
union { doublo pi; :tnt char c;
} Ll

(.Hl

In fe lu 1 acesta, iE._U~..'~j.':lL5=:+:_~.,_11l11E.~i .es!e ..11C_C;eSa.racl(;!1_lll!li:r:C:il: ..tiput:i12.!: ~_!ruclUJ:(lt~_((I_efj 11 it~~_aj_l1_t_~~~II_luis trl1ct)p~ n intermed iu 1 const:r:1IC!ie_i typed!;_: In limbajul C++ 0 structura poate fi transferata direct prin parametri. Astfel, daca avem declaratia: struct nume { }; atunci datele de tip nume pot fi transferatc prin parametri in 3 moduri: direct: tip fl (nume par) { } pointer spre structura: tip f2(nume "par) { } referinta la structura: tip f3(nume& par) { }

union D ternative int ii float f; double cl;


c har C;

1;

In continuare
alterna,tiv(:;

se pot declara, dcfini, date de tip alternative ca rnai jos:


z ona Lv zona z :

o alta facilitate cxistcnta in C++ este posibiIitatea de alltili2:~lE~_unillni anonime ca._~L~()mpoll~11tcitltr~ostructllr[l. Aceastapci:ii;Tic-acceslil rnai simplu Elcornponentele structurii.
Exemplu:
struct 'tnt tip; union {

38

39

int i; float f; double d;


);

20.13. Supraincarcarea

functiilor

}a;

In limbajul C, functiile utilizate intr-un program au nume distincte. j~11illl.~aj~]._S::...:~:~.~:_:~s tii_..Eosi~Ui!~1~~~£'l.t\~12~lii.sEf~!:it.E;__~~ __ .'lilJ_::i_~!1_~ICelas i
a structurii

Rcuniunca, componenta referim ca mai jos: a.i = 1234; a.f'= 3.14159; a.d=3.14159265;

a, este anonima,

La cornponentele

ei ne

mane. "'-5~obicei, functiile "inrudite" potfi denumite £rintr-ul1 acelasi nume. Cazuri Ie ccYe"~11an~:ecve'i1te(!e-fuiieti lell- 'acefa~ln-urrieslntfliilc~Ill e care realizeaza acelasi proces de ealcul dar asupra unor date de tipuri diferite. De exernplu, in Iimbajul C exista functii, in biblioteca sistemului, cu nume distincte pentru calculul valorii absolute:

abs labs labs C. Cu toatc

- Pentru calculul valorii absolute a unci date de tip into


Pcntru calculul - Pentru calculul valorii absolute valorii absolute a unei date de tip a unci date de tip

20.12. Tipul enumerate


in limbajul C++, tipul enumerate se definestc ca in limbajul acestea exista uncle difcrcntc. Difcrcnta cscntiala consta in aceca ca in linlbajul valorilor care sc atribuie unci date de tip cnumcrarc, De enumerate se pot atribuinumai.enul11eratorii (componcntclc) Exemplu: Fie dcclarati ilc:
CnUITl Sdpt, {:1 uni
I

long. double.

Aceste functii au urmatoarele


int abs (int) ; long Lal» ( l.onq ) ; double fabs (double)

prototipuri:

Prirnele

UOU[1

protoiipuri

se afla in fisicrul

stdlib.h, iar eel de al treilea in

fisierul math.h.
In limbajul C++, aceste functii pot fi numite cu un acelasi nume. In acest caz, ele se disting prin tipul parametrului. Astfel, in limbajul este posibil sa definim accste 3 functii ea,mai jos: I.
int long abs(int abs(long n) n) n) return return return n
<

C++

ma rt. i mi e r cu r i j 0 .1 vi nor .i
I I I

.~;

,i. mba t.a , dumi.ni oa } ,.

(~nurn s ap t. z iua ,

0 ? -n
?

: n: } : n; ) } <n : n;

Expresiile

de mai jos sint legale:


&& ziua
<= vineri)

2.
3.

n < 01 ? -n n < 0.0

ziua :;: ineri; v if(ziua >= luni II zi lucraroarc else II zi de odihna

double

abs(doub1e

La un apel de forma:

x
de forma:

= abs(expresie);

in C++,
ziua

expresie

~.~t~eE21l.aUl,desi conform declaratiei Enumeratorii sint de tip int.

de mai sus,

marti arc

valoarea

2. datelor de

Ca si in cazul structurilor, cuvintul enum fi omis la declararea tip enumerare. Astfel, ziua se poate declara mai simplu scriind:
sapt ziuai

compilatorul C++ apclcaza una din cele 3 flll1c\ii (lbs definitc rnai susv tinind seama de tipllTri~ii:;1111etl:llflltCfecilv:-~!dicTd e'e:~Pf:~sTe'd;ntrc-p~lraritezc: tfCl~exp';~';'ie~r~'tipulil:II,'atu;{~i se apeleaza functia definita la punctul 1, daca expresie are tipul long, atunei se apeleaza functia definita la punctul 2, iar dad! expresie are tipul double, atunci se apeleaza functia de la punctul 3. In felul acesta, numele abs reprezinta 3 functii pc care compilatorul le poate distinge, la apel, dupa tipul parametrului efectiv. Se obisnuieste sa se spuna ca cele 3 functii supraincarca numeleabs. De asernenea, se spune ca numele ~bs-Csic-slljjrai;;cal-:catTover[(;a?j. *- In general, unnumc se spune. ca daca eleste un nume ~l]_p~n!ll1 n1~i lYlllltG:iuA~!ii '-._....-...........--.--.---.-.--.---...---

d;;:c~

As

~~stcs[;pi-:dii;carcat
vom spunc ca

Dcsprc (Functions

functiilc cu overloading).

acelasi

nume

sint

supraincarcate

40

41

La ora actuala exista incetatenit in limba romana si alti terrneni pentru supraincarcare, ca de exemplu, suprapunere, redefinire sal! supradefinire. In accasta carte adoptam termenul de supraincarcare. Ocondilieesenliala pentru supraincarcarca funcriilor est~ __;(Lc;les;\ aib~. c l?E_c>.!()~ip_lll·~_t{(t~~C~~. contrar, compi][ltorlll nu poate face distinctie, intre ele, ji1ca~ la apelul lor. In principiu, numarul si tipul pararnetrilor efcctivi fumizcaza un criteriu de selectie al functiilor supraincarcate. A vind in vedcre acest fapt, rezulta ca la apelul functiilor supraincarcate, de obicei, nu se mai aplica regula sirnpla de conversii a tipurilor pararnetrilor efectivi spre tipurile pararnetrilor formali corespunzatori, regula utilizata in limbajul C. in acest caz, se pot aplica convcrsii daca Ill! exisra coincidenta intre tipurile parametrilor efectivi si cei formali cu care sc corespund. In limbajul Cf+ sc incearca selectarea acelei functii pentru care exista coincidenta intre numarul si tipul parametrilor efcctivi (de la apel) ~i al parametrilor formali ai functiei supraincarcate. In cazul in care nu sepoate stab iIi o astfel de coincidenta.xe fac si in acestc;azconversii alcpal:~l:ri~jl:i1()I'~.cf~(;!.iYL Aceste conversii pot sa I1u"fie unice si de aceea sint nccesare rcguli suplimentare. De exemplu, reluind apelul de mai sus: x = abs(expresie); unde expresie are tipul float, se observa ca nu se realizeaza 'coincidenta cu tipul parametrului formal al nici uneia din functiile care supraincarca numele abs. De aceea, in acest caz, se va face 0 conversie a valorii expresiei de la apel, Sin! posibilc 3 conversii:
floa t > int float -> long float -> double
-r

cauta

functie admitind

conversii

nu numai pentru tipuri predetinitc

ci si

pcntru cclc definite

de utilizaror.

in cazul in care nu sc poatc sclccta 0 functic unica parcurgind in ordinc pasi] de mai sus, cOJ11pilatorul C++ scmnalcaza eroarc.. .. _ _" Mai tirziu, se va rcveni asupra problernei apelurilor functiilor 111 lcgatura cu conversia Exercitii: 20.16 Sa se supraincarce nurnele modul cu functii de calcul a valori i absolute pentru nurnere mtregi ~i neintregi, iar pentru numere complexe se va calcula modulul, FI:;iIERUL BXX16
int modu I (int return
i)

darelor de tip utilizator.

II rcturncaza -i : i;

valoarca absoluta

a lui i

<0?

long modu 1 ( long n) II rcturncaza


{

valoarca

absoluta

a lui n

return

n < 0 ? -n : n; d) II rcturncaza

double
(

modu l (double

valoarca absoluta a lui d

return

d < 0 ? -d : d;

typedef struct double x; double y; ) COMPLEX; double


(

In principiu, se aleg conversii care S,1l1l1 conduca la pierderea de inforrnatie. De aceea.in cazul de fata, sint excluse primele doua conversii. La un apel, selectia functiei se realizeaza in mai multi J.!a~ si in ordinea de mai jos: 1. 2. Sc cauta 0 corespondenta exacta ;;i se apeleaza functia respectiva daca ea exisra. Daca nu se poate detennina 0 functie cu coincidenta exacta, atunci se cauta una pc baza efectuarii de convcrsii predefinitc (pentru tipuri predefinite) care nu conduc 1a pierderi de informatie, adica se fac conversii lara trunchieri, Daca nu se poate dctermina 0 functie conform punctelor precedente, atunci se incearca selectarea unci functi: folosind conversii pcntru tipuri predefinite care pot sa conduca la trunchieri (de excrnplu, date de tip double se convertcsc in date de tip float, long sau int). Daca in pasii precedent: nu se poate determina functia de apelat, atunci sc

modul (COMPLEX sqrt(z.x

z ) II rcturncaza

modulul

lui z

return

* z.x+z.y

* z.y);
ld) II rcturncaza valoarca absoluta a lui lei

long double
{

modu l (long double : Id;

return

ld < 0 ? -ld

20.17

3.

Sa se defineasca functii supraincarcate numere $i siruri de caractere.

cu numele ajiseaza, care sa afiseze

Functiile au unul sau mai multi parametri. Primul paramctru defineste numarulde afisat, Parametrul al doilea, daca este prezent, define)te dimensiunca minima a cinrpului in care se afiseaza data. Data se nfiseaza cad rata 111 dreapta ~l 43

4.

42

eventual cstc prcccdata de spatii, Pararucrrul al trcilca, daca cstc prczcnt, indica nurnarul de zccimalc In cazul nurnerelor ncintrcgi sau numarul de caracterc in cazul in care sc afiscaza siruri de
caractcrc,

egala ell cimp si ell prccizia

dcfinita

de prccizic

*/

char *sir, *sirl, *sir2,*sir3;


sirl format("%",cimp) ; sir2 fonnat (si r I "."); sir3 format(sir2,precizie); sir = format(sir3, "Lg"); printf(sir,lf); delete sir; delete sirl; delete sir2; delete sir3;
}

FI$IERUL BXX17
char
';I.

orma

t t

(const

., furma

cha_1:' *s1, i n t: c imp ) i char *sl,const c~lar * s2) ;

void afic;Eeaza (int i, int cimp=5) /* afiscazu valoarca lui i in cimpul de dimcnsiunc
{

minima

cgala ell cimp */

char

'f,

i r. *sirl;
f.orma t; ("%"
I

c irnp i:

format ( f(sir,i); sir; s irI :

, "d");

void afiseaza(COMPLEX z,int cimp lS,int precizie 6) /* afiscaza 11111l1arulcomplex z in cirnpul cimp si cu precizia dcfinita de prccizic */
(

char char
sir

*sir; *sirl,·sir2;
::: format("%",cJ.mp) :::: f o r me t
i

void liseaza (long l,int cimp = 10) /* af"\s<..';tl.avaloarca lui! in cimpul de dimcnsiunc minima
(

s i.r l,

cgula

ell

cimp */

t s i ri

vv vl :

char sir]

s ir . *sir1; forrnat.(" lI,cimr»; t (sirl, "Ldvj . ( i r. l : ir : irl;

ro rma

delete sir; sir = format(sirl,precizie); delete sirl; sir2 = f orrna t.j s i r ,"g "); delete sir; •

sirl:::: format("Partea

reala

void ,:tt: (dolJble c1, int; cirnp =: 15/ int 1* afiscaz,a valoarca lui d 1Ileimpul de dirncnsiunc minima cgala cu cimp si ell prccizic dcfinua de prccizic */

preci

ie

6)

sir = format(sirl,'Partea delete sir1; sir1 = format(sir,sir2); printf(sirl,z.x,z.y); delete sir; delete s i rL: delete sir2;

:::: II,sir2); imkginara =

");

Lr,*sirl,*sir2,*

ir3;

sirl format (" ",cimp) ; sir2 tormat(sir1, "."); s1r.'3 format(sir2,precizie); sir f:onnat(sir3, "g"); p r i.nrf(sir,d); delete sir; de1ete s i.r I i delete sir2; do l.ere sir] i

void afiseaza (const char *s, int cirnp = 70, int p rec i z i e /* afiscaza sirul de caractcrc sprc care pointcaza s intr-un cimp de lungimc minima cgala ell valoarca lui cirnp si ell prccizia cgala ell prccizic */ char *sir,*sirl,*sir2,*sir3;

70)

void fiseaza(long double If,int cimp :::: 1S/int /* afisca/a vuloarca lui If ill cimpul de dimcnsiunc minima

precizi.e

6)
}

sirl fo rrna ("% ",c imp) ; t sir2 format (sirl, "."); sir3 ~ format(sir2,precizie); sir = format(sir3, "s'); printf (sir,s); delete sir; delete sirl; delete sir2; delete sir3;

44

45

char *format(const char *s,int n) /* - coustruicstc lin sir prin concatcnarca caractcrclor sprc care poinlcaza s ell cclc rczultatc prin convcrsia lui n in zccimal: - sirul rczulrar sc pastrcaza in memoria heap. */ char zona [10] ;

afiseaza(modul(i)); afiseaza(cont,50) ; qet.ch() ; afiseaza("Alt inl if(( get.e-hl)I /1 sfirsit for pcnrru int char long .i n t. n:c;_l
Ollg

raspunde 'D' && c'

elJ

'el')

0 sau N "); break;

itoa(n,zona,lO) ; return format(s,zonal;

[1

"\nlongcc";

char *format(const char *sl,const char *s2) /* construicstc un sir prin concatcnarca sirului sprc care poinrcaza s2 la sfirsitul sirului sprc care pointcaza sl */ char *mem;

for (;;) for (;;) a iseaza(intreg_long,10); iflgets(t)== 01 exit(l); Lf(sscanf(t,"%Id",&ll == 1) break; fiseaza (Hnu s-"a tastat un .i n treq vn" 10) ; afiseaza("se reia citirea intregilor\n");
I

mem = new char[strlen(sl)+strlen(s2)+1]; strcpy(mem, sl); strcat(mem,s2) ; return mem;

20.18 Sa se scrie un program care afiseaza modulele nurnerelor citite de la intrarea standard. PROGRAMUL BXX18
#include #include #include #include #include .include #include <stdio.h> <stdlib.h> <conio.h> <string.h> <math.h> ·BXX16.CPP· ·BXX17.CPp"

afiseaza("\n\n\t tip long\n\n",lO); afiseaza(modul(I)) ; afiseaza(cont,50) ; geteh (); afiseazal"Alt long ? Se raspunde eu D sau N "I; if((c geteh()1 'D' &&e != 'd'l break; // sl'irsit for pcntru long char flotant_simplu[] = "\nflotant simpla precizie="; char reI[] = "se reia citirea numarului\n"; float f : char er I] "nu s-a tastat uri numa r vnv. for (;;) for (;; I afiseaza(flotant_sin~lu,lOI; if(gets(tl 0) "xit(l); if(sscanf(t,"%f",&f) == 1) break; afiseaza(er,10); afiseaza(rel,lOI;
=C'

// functiilc /1 functiilc

supraincarcatc supraincarcatc

rnodul afiscaza

main( ) 1* afiscaza modulclc


{

numcrclor

cititc de la intrarca standard

*1

int char char char char

i;
c;
con t I] ="\n

afifiEoi'lZa("\n\n\t tip float


e ti seaz a Imodu Lt t j ) ;

\n\n",lO);

intre9_int t[255];

Actionati 0 tasta [] = "\nint=";

pentru

a continua\n";

for (;;) for (; ; I afiseaza(intreg_int,strlen(intreg_int)) ; if(gets(t)==O) exit(l); if(sscanf(t, "%d",&i)==l) break; afiseaza("nu s-a tastat un intreg',10); afiseaza("se reia eitirea intregilor\n"); afiseaza('\n\n\t\t tip int\n\n",lO);

afiseaza(cont,50); getch() ; afiseaza("Alt float? if((c=getch()1 '= 'D' // sfirsi! for pcnrru float char flotant_dublu[] double (1;

Se raspunde eu D sau N "I; && e!= 'd') break;

"\nflotant

dubla

precizie=';

for (;;) ( for I; ; I( afiseaza(flot.ant._,dublu, 101; Lf:(gets(t) == 0) ex it t L) :

46

47

if: (sseanf (t, "%1£", &d) ==1) afis(;~(1zti(er/l0) ; fi;"caza (r-ol 10); ,

break;
)

if ((c q e t.c t ) ) h } II sfirsit 1'01' pcntru complex

'=

'D'

&&. c

'=

'd')

break;

a iseaza("\n\n\t tip doub1e\n\n",lO); a[iscaza(modu1(d) ,25,16); afiscaza(cont,50); '1etch(); iseaza("Alt double? Se raspunde eu 0 saIl N "); ((ccc'1ctch()) '= 'D' && c '= "d") break; II srirsil for pcntru double char [lotant_lun'1[J 10n'1 double Id; "\nflotant
Luno

Obscrvatii:
I. Functiile supraincarcatc utilizatc in acest program sint:

afiseaza; - format;
-- modulo

Ele sc selecteaza prin coincidcnta intre tipurile parametrilor efectivi si formal: care sc corespund prin pozitie, exccptind apelul functici niodul
pentru tipuljloat cind se face
0

conversie

spre double.

for (; ;) ( for (;;) afiseaza(flotant_lun'1,lO); i. (gets(t) === 0) exit(l); if(sscanf(t, "%Lf",&ld) == afiseaza(er,lO); a iseaza(rel,lO);

2.

Un ape! de forma:
afiseaza(sir) ;

1) break;

afiseaza("\n\n\t tip 10n'1 double\n\n",10); afiseaza(modul(ld) ,30,20); afiseaza(cont,50); gctch() ; af iseaza ("AI t long double? Se raspunde eu D sau N "); if((c='1'~tch()) '= 'D' && c != 'd') break; Iisfirsil for pcruru long double char n_conlplex[] COMPLEX complex;

unde sir este un pointer spre un sir de caractere, afiseaza sirul respectiv intr-un cimp de minimum 70 de caractere. Aceasta deoarece parametrul implicit cimp al functiei afiseaza arc valoarea 70. In cazul in care sirul care se afiscaza arc mai purine caractere, el sc afiscaza cadrat ill dreapta in cimpul respectiv. Daca sirul continc mai mult de 70 de caractere, atunei numai primele 70 se VOl' afisa, deoarcce parametrul implicit precizie arc valoarea 70. Un apel de forma: atribuie parametrului cimp valoarea 10. In acest caz, sirurile de caractere eare contin mai putin de 10 caractere se afiseaza intr-un cimp de 10 caractere si cadrat in dreapta. Sirurile cu peste 10 earaetere,
afiseaza(£ir,10);

"\ncomplex

Partea

reala=";

for (;;) for (;;) afiseaza (n_complex, 10); it(gets(t) == 0) exit(1); if (sseanf (t, "%If'', &compl(ex.x) afiseaza (et', 10) i afiseaza(rel,10); continue;

caractere cite intra in compunerea


Paramctrul implieit peste 70 de caracterc caractere vor f afisatc. 20.19

dar care I1U depasesc 70, se afiscaza pe atitea lor. precizie, nefiind definit in apelul de mai sus, sirurile eu se afiseaza trunchiat ~l anume numai prirnele 70 de numelc putere si care ridica la putere

1)

Sa se scrie functii eare supraincarca numerc de diferite tipuri.

afi_seaza("\nPartea imagirlara=",lO); if(qcts(t) ==, 0) exi t f 'l ) . if(sscanf(t, ''%If'',&eomplex.y) == afiseaza(er,lO); afiseaza(rel,10);

FI~IERUL BXX19
1)

break;

int putere(int a,int II ridica pc a la putcrca b


(

b)

afiseaza("\n\n\t tip complex\n\n",lO); afisE?aza (modul (complex), 25, 16); afiscaza(cont,50); getch (); afised,za(ltAlt. comp lox ? Sf~ r a spuride cu D sau

int c; int i; if(a == 0) return 0; if(b < 0) return 0; forti = 1,c l;i <= b;i++)

II);

48

49

ai

int c;

c;
(;; )

return

long putere(long a,int II ridica pc a la putcrca b


(

b)

long Cj int ii if(a == 0) return if(b<O) return for(i 1,e l;i return Ci 0; 0; <= b;i++)

tor (; ; ) p rin t.f (baza); printf (" int=") ; iflgets(t) 0) if(sscanf(t,"96d",&i) printf(erint) ;

exitll); == 1) break;

"=

a;

for ( ; ; ) p ri.n t f (exp) ; p ri.n t f (" int=") ; if(Cjets(t) == 0) cx itt lj : i Isscanf(t, "%d",&j) == 1) print! (erint); ~ltere(i,j); = %d\t j printf("Alt int""int ifllc = Cjl~tch()) II Sfirsit int**int
prj.ntf("i Lonq u;

break;

double putere(double II ridica pc a la putcrca b


(

a,int

'b)

int

double c; int i,ji if(a


j

%d\t i**j %d\nl',i,j,k); ? Sa raspunde en D sau N \n"); 'D' && c '= 'd') brceak;

==

=b<

for(i return

0) return 0.0; 0 ? --b : b; II j '" abstb) = l,e:::: 1.0; i <= j;i+:) b < 0 ? 1.0/e : c;

c *- a;

for (; ; ) for (; ;) t.f p ri.n t f (" lonCjo,") ; H(<:fets(l) == 0) ex i.t Lll : U(sseanf(t,"%ld",&u) 1) break; prinrf ("nil ':;'-a t:astat un In t.roq de
pri
n (ba z a ) ;

double putere(double II ridica pc a la putcrca b


(

a,double

b)

return

pow(a,b);
for

tip

lonq\n");

20.20

Sa sc scrie un program care citeste siruri de perechi de numere de forma (x,y) si afiseaza, pcntru fiecare pereche, valoarea lui x la putcrea y, Nurnerele x si y sint de diferite tipuri,

(; ; ) pri n r.f (axp);

PROGRAMUL
#include #include #include #include #include main ( )

BXX20

printf ("int="); if (Cjets It) == 0) exit if(sscanflt,"%d",&j) p r i n t f (erint) ;


)

(1);
==

1)

bn~ak;

<stdio.h> <stdlib.h> <math.h> <conio.h> "BXX19.CPP"

10nCj m = putere(u,j); printf("u = %ld\t j print ("Alt long*"int if( (c = Cjeteh())' II Sfirsit long**int float char f; ern [1

%d\t u**j %ld\n",u,j,m); ell D sail N \n"); ? Sa raspunde break; 'D' && c '= 'd')

1* citcstc pcrcchi de numcrc de forma (a.b) si afiscaza


(

pc a la b *1

IINu s-'a tastat

un numar\n'l;

char char
char

t; [2S~)J; baza[) QXp[]

"baza\n";
::::"nu s~a tastat un intreg\nl!i

::;;: uexponent\niJ;

char erint[} int i,j;

for (; . ) { for (;; ) p rint.f Lba z a ) ; printf("float="); if(Cjets(t) == 0)

ex i t t Ll :

50

51

pt

IsseanfIL,"% int.f (ent);

",&f)

I.)

break; double 9 putere(d,h); printf("d %g\t h %g\t d**h = %g\n",d,h,g); printf("Alt double""double ? Se raspunde eu D saD N \n"); if«(e = getcil()) != '0' && e != "d ") break; II Sfirsil doublc"'*doublc

s , ;')
pt

tnt f (
f ("
0)

ex i t

(l)

if(sscanf(t,"%d",&j) i n rf (e.cint);
f
-1

==])

break;

float long

Ic0XP;

double

Id;

q
(U

pu t.

(f flotlt~*kint

); 1id\t ? f*'j ',;g\n",[,j,q); cu D sau N xn") i "c l") Se ra spund« H,

r n rtt"f

in: if
((e

cjE,teh())

'[)'

c'

break;

II Sfltsil Iloal''''inl d; lor ( ; ; ) foe ( ; ; ) in t t t ba z a l :


print::.f
t

for (; ;) for (; ;) p r i n tf (baz a l : printf("long double="); if(gets( ) == 0) exit(I); if(sseanf(t, "%Lf",&ld) p r i.nt.f (ern);' for (; ;) { printf (oxp ) ; printf{"float='l); if(gets(t) == 0) exit(1); if(sscanf(t,"%f",&fexp) p r i.n tf (ern);

1) break;

("double:::!!)
0)

(qelcs(t) iC(sscan (t,'''t I) Lin t, f ((~ r n) ;


I;; ) Ill: j

exit(l); ",&d)

1)

break;

1)

break;

pri

lexp)

;
")
;

f I"

it {(lets It) illsscanflt: in tf (er


C;-~

) exit(l); ','<'d) == I;
(d, -j) ;

J)

bron k :

double p = puterelld,fexp); printf("ld %Lf\t fexp = %f\t Id*'fexp = %g\n",ld.fexp,p); printf I "Alt long double"float eu D sau N \n"); ifllc qetehl))!= 'D' && e' II Sfirsi: long doublc**lloat float q,r;

Se raspunde
"d ")

break;

(("d
print f ("AIL

put.(·~r(:;

j double"'.*int

%g\t

%d\t
'D'

d**j
'se

1:;g\n ,cl,j,e);
H

ra spundc 'el')

eu

D sau

N \n");

.i f t t «: CJeteh()) II Srirsit doublc"'*int double h;


I;;) I

&& c'

break;

for I ; ; ) p r i n t f (baza); inr.f ("doul)le-· II) i j[lgc~tslt) 0) exitll); iflsscan£lt," If",&d) c,= pri n t f lent!;
I;; I p ri n t f (cxp ) ; .in rf I "d()ubl(~=")

for ( ; ; ) for I;;) printf (baza); printf("float="); i Igets(t) == 0) ox i t t l j , if(sseanflt, "%f",&q) == 1) break; printf lern); for (; ; ) printf (oxp ) ; printfl"float=") ; if(getslt) == 0) ex i.t t L) . if(sseanf(t, "%f",&r) == 1) printf (ern);

1)

break;

break;

if(qetslt)
.il(sscanf(t,"

; OJ exit(l); H",&hl ="

I)

break;

prin t.f (o r n l :

double s = putere(q,r); printf("q %CJ\t r = %g\t q*"r = %g\n".q,r,s);_ print£("Alt float""float ? Se raspunde eu D sau if( (e getc:hl))!= 'D' && c! "d ") break;

N \n");

52

53

} II Sfirsil l1oat**tloat
)

11/.1111('(('/,('2,

...

,en)

Ohservatii: 1. in acest program se utilizcaza tipuri predefinite:


Rezulrat inl long double double returnar

functia putere supraincarcata


baza int long double double cxponcntul int int int double

Cll

urmatoarcle

untie: ei,e2, ... .cn


0"

- Sint pararnetrii

efectivi

ai apclului.

2. 3.
4.

2.

Functia putere se apeleaza cu parametri efectivi de diferite tipuri predcfinite, dupa cum urrneaza:
a. b. c. d.
c.

f. g.

plilere(int,int) plilere(long,int) plltere(float,int) plilere(doublc,int) plilere(douhle,double) plilere(long double,nOll!) plIlere(floa!,float)

Funcriile putere supraincarcare


La punctul a b c d c Se selecteaza

se selecteaza

astfel:

functia de la punctul

Apclul rnacroului sc inlocuicste cu text dupa cc, in prealabil, pararnctrii formali pi, i 1,2, ... ,n s-au inlocuit, in tcxtul /1'.11, Cll paramctrii cfectivi corespunzatori ei, i = 1,2, ... .n. Aceasta inlocuire a apclului macroului se numeste expandare. Expandarea macrourilor difera de modul in care se realizcaza apelul functiilor obisnuite. 'La apclul unci funciii obisnuitc nu se substituie apelul functici prin corpul ci, ci se realizeaza un salt la zona de memorie in care se pastreaza corpul functiei respective. La tcrrninarea executiei functiei se revine in punctul imediat urmator apelului. Un apel de aceasta forma, numit si apel cu revenire, implica diferite operatii suplimentare. In cazul in care functia este foarte simpla (2- 3 instructiuni), operatiile implicate de apel si revcnire pot fi rnai costisitoare decit cele implicate de functia insasi. De aceca, in astfel de situatii, ar f util ca apelul functiilor sa se rcalizeze la fcl ca apelul de macro, adica prin expandare (inlocuirea apclului prin corpul functiei) Acest lucru esje posibil daca antetul functiei este precedat de cuvintul.c:heie il1lin~~ 0 asrfel de functie se numeste functie inline. Exemplu: Pcntru culculul jos:
#definc,
MflX(x,Y) (x) <
(y)

1: sclcctarc prin coincidcnja; 2: sclcctarc prin coincidcntn, sclcctarc prin convcrsic: baza de tip.Jlo{/{ sc convcrtcstc spre tipu] double; sclcctarc pnn coincidcnta: sclcctarc prin coincidcnta; sclcctarc prin convcrsic: baza de tip long double sc convertcstc spre double 5i cxponcntul de tip/loal spre double; . 4: selcctarc prin convcrsia ambilor pararnctri din/loaf sprc double, 3: 3: 4: 4:

maximului

dintre doua 1111111ere ponte dcfini sc


'!
(y) :

macroul

de mui

(x)

Fie secvcnta
Lnt. a/b,(:,~; c

pcntru apclut macroului

MzvX:

20.14. Functf inline


In paragraful 15.1. s-a ararat posibilitatea de definite a macrourilor in li~n~ajul C. Aceasta facilitate este prezenta ~i in limbajul C++, dar utilizarea este diminuata prin prezenta functiilor inline. Amintim ca un macro se defineste printr-o construe tic de forma: #detine l1ume(pl,p2, ,pn) text apar in textul de Parametrii p l , p2, , pn, numiti parametrii forrnali, substitutie text. Un macro poate fi apelat prin constructii de forma: 54

MflX(a+b,a-b);

La prcproccsarc,
c = (a+b)
<

sc substituic
(a-b) ? (a-b)

apclul macroului
: (a+b);

prin textul sau ;;i sc obtine:

Calculul
in lino

maxirnului se poate realiza folosind functia inline de rnai jos:


.int; rnax(int

x,int

y)

( re

r.u r n x

<y

?y

: x:

lnstruciiunca
c

de atribuirc

de mai sus se scric:

max(a+b,0-b};

In aces! cuz, apclu] functiei max se schirnba la cornpilarc prin corpul ci. Se obisnuicste sa sc spuna CLI apclul functici se rcalizcaza prin expand area ei. In fclul acosta se climina opcratiilc spccificc de la apclul ~i rcvcnirca din funcriilc
obisnuirc.

55

Functiilc in line au uncle avantaje fata de macrouri, Astfcl, la expandarea unui macro nu se tine selima de tipul parametrilor. De accea, nu sc rcalizcaza nici un control aSllpra tipurilor parametrilor cfectivi sau conversii ale valorilor acestora sprc tipurilc paramctrilor formali. La apclul unui macro, paramctrii formali se substituic in textul dill corpul macroului prin parametrii efectivi corespunzatori. Accasta substirutie se realizcaza inlocuind Lin sir de caractere (nurnele pararnctrului formal) printr-un alt sir de caractere care dcfincstc paramctrul cfcctiv corespunzator. De aici rezulta $i un alt dezavantaj al macrourilor ~i anume acela al efectelor secundare, care in cazul macrourilor sint mult mai greu de pus in cvidcnta dccit in cazul functiilor. Efectelc secundare sau colaterale apar la calculul cxpresiilor care contin operanzi ale carer valori se schirnba la evaluarea lor. Astfel de cfectc sc intilnesc mai aIes la utilizarea, in exprcsii, a operatorilor de incrcmcntare si
dccrcmentarc.

c = max(el,e2);

De cxcmplu,
c

atribuirea:
astfel:
(b++) ? (b++) : (a++);

MAX(a++,b++);

sc expandcaza

~ (a++) <

A vind in vedere avantajele functiilor inline fata de macrouri, rezulta interesul scazut in utilizarca macrourilor in limbajul C++. Constructia itdefine in limbajul C++ sc utilizcaza frecvent in lcgatura Cll compilarca conditionata, precum ;;i in cazul functiilor de biblioteca utilizate atit in programc C cit si in programe C++. Functiile inline se vor utiliza totusi cu precautie, deoarece ele sint avantajoase numai ci'nd sint simple. 0 functie in/inc ce continc l11aLl11l1}t_cl~_:3_i~s_tl:tI3i_l1_~ "'poate deveni ineficienta deoarece expand area ei in program in locul apelurilor sale poatc conduce la 0 crestere substantiala a dimensiunii programului. Functiilc inline au anumite dezavantaje fa\el de functiile obisnuite. Astfcl, aces te fu ;lC\i i 1!t,J EO t.n._~::;!~I~_~_~~i_~.~E<?U}_d_~QI!i.\s:.iii.I.l~iJi~_~!t;:.~~ltE:ll.D:_§m_g_ur modul alpr()gr:':llmijLli, -- De asemenea, c.Q!:EllL~l~ei fU!~lLU./'l~i~~_!_l~I_E?a _.~..9Eli _§E_C::::'~_llJ(;.S.iC.li_<;_~ Ie ne (secvente introduse prin instructiunile while.forsi do-while). Atril)_l1_t.~ILil1li./'l~_~st~~1_~glija~ ~.atre_C_~Epi~~!~r in c_~~ul_i~_~ar~_fl1_l1_~lia de__ ~~ l?oate fi tr~ltat~~'l.'!.tl~l:(;:. . .. --Dc-c;Zc;ilplu, daca 0 functie CLiatributul inline coutine 0 instructiune ciclica, atunei atributul inline va fi neglijat si functia respectiva va fi tratata in mod obisnuit. Cornpilatorul cmite un mesaj de avertismcnt (warnings) corespunzator. Exercitii: 20.21 Sa sc scric
afiseaza,
lilt

Efcctul acestei instructiuni este diferit de eel al instructiunii functia inlinc max in loculmacroului MAX:
C ~-;::; max(a,+-!",b++)

obtinute

apclind

pcntru fiecare pereche,

program care citestc un sir de perechi de numere intregi si maximul dintre cle.

de increrncntarca

Accst ape! atribuie lui e maximul dintre a ;;1b, functia max nefiind influcntata valorilor lui a si b. Valoarea lui C ll1 urrna apclului macroului MAX cstc influcntata de cfcctclc sccundare rczultate din incrementarea valorilor variabilelor a si b. Mentionarn ca efectcle sccundare pot fi prezente si in cazul functiilor, dar in acest caz ele pot fi controlate mai user. De cxemplu, apelul functiei max in instructiunca de mai jos:
c

PROGRAMUL
#include inline return

BXX21

<stdio.h> int rnax t i nt. x, int x < Y ? Y : x;


y)

/*rcturncazamaximuidilllrcxsiy*/

max(b+a++,2*a++);

ma in I )

/* citcstc un sir de pcrcchi de intregi si afiscaza, pentru ficcarc pcrcc he, maxirnul
(

dintrc clc */

atribuie lui C 0 valoare care poate s(\ fie diferita pentru implernentari diferite ale limbajului C++. Nu exista 0 regula pentru ordinea de evaluare a parametrilor cfcctivi si din aceasta cauza nu putem sti daca evaluarea expresiei:
2*a++

int a,b; while(scanf("%d %d", &a,&b) == 2 ) printf("a=%d\tb=%d\tmax(a,b)=%d\n",a,b,max

(a,b));

sc rcalizcaza inainte sau dupa cvaluarca exprcsici b+a++. De accea, se recomanda evitarca apelurilor de acest tip prin introducerea atribuiri prcalabile pentru paramctri efectivi cu efecte secundare:
e1 E:2
b+a++'; 2ka+'+i

unor

20.22 Sa se serie un program care citeste un sir de perechi de intregi si afiseaza, pentru fiecare pereche, maximul dintre valorile lor absolute.

56

57

PROGRAMUL 8XX22
#include in1ine return <stdio.h>
v.iloarca absolutu a lu: x */

inline double maxabsldouble i* rcturncaza maxirnul vulorilor absolute double double return z
u

x, double y) ale lui x si Y */

int. abs r i nt; x ) /* rcturucaza x< 0 ? -x: x;

abs (x l : abs Iy) ; :z ;

z<u?u

in11ne int maxabs(int /* rcturncaza maxirnul valorilor


(

x, int y) absolute ale lui x si y */

int 7= abs (x); int u= abs (y) ; return z<u?u z;

main I) /* _ citcstc un sir de pcrcchi de intrcg: si afiscaza, maximul dintrc valorile . citcstc lIll sir de pereehi lor absolute; de numcrc si afiscaza,

_ I pcntru ficcarc pcrcc ic, pcntru ... ficcarc pcrcchc, maximul . dintr c

valorilc lor absolute.


int a,b;

*/

main () /* citcstc un sir de pcrcchi de intrcgi si afiseaza, pcntru maxirnul dintrc valorilc lor absolute */ int a,b;

ficcarc pcreehc,

printf I" sirul de perechi de numere intregi \n"); while (scanfl"%d %d",&a,&b) 2). ... . tfl"~,-~d\tb-%d\tmaxabs(a,b)=%d\n",a,b,maxabsla,b)), pr.ln~_
(.-0 --

while (scanf("%d %d",&a,&b)== 2) printf("a=%d\tb=%d\tmaxabs(a,b)=%d\n",a,b,maxabs(a,b));

double

c,d;

20.23 Sa se scrie un program care citeste un sir de perechi de intregi si afiseaza, pentru fiecare pereche, maximul dintre valorile lor absolute, apoi realizeaza acelasi lucru pentru perechi de numere. Pentru a termina sirul de perechi de nurnere intrcgi se va tasta un caracter oarecare care nl! intra in compunerea unui inrrcg (de excmplu 0 litera). PROGRAMUL 8XX23
#inc1ude in1ine return <stdio.h> valoarca absoluta lui x */ a

f f us h t s t d i n l : //vide:Jzazona<ieinlrare de perechi de numere\n"); pr ntf("sirul %It·,, s.c , &d) =2) wh Le (scanf ("golf printf("c=%f\td=%f\tmaxabslc,d)=%f\n",

,d,maxabs(c,d))

int abs (int x) /* rcturneaza x< 0 ? -x: x;

in1ine return

double

abs (double -x : x

x ) /* rctumcaza

valoarca

absolura a Illi x */

x < 0.0 ?

inline

1* rcturneaza
(

int maxabs(int maximul valorilor

x, int y) absolute ale lui x si y */

int z = abs(x); return

int u = abs(y);

z < u ? u : z;

58

59

21. PROGRAMAREA PRIN ABSTRACTIZAREA DATELOR


Am vazut ca limbajul C, si dcci si limbajul C++, suporta stilurile de programare procedurald si programare modulara. Prcgramarca procedural a (vczi paragraful 4.14.) arc la baza utilizarca proccdurilor a caror cchivalcnt in limbajele C si C++ sint functiilc. Programarea procedurala este eel mai vechi stil de programarc. Mai tirziu, pe masura ce complcxitatea programelor a crescut, a aparut ideca de a descompune problemele in subprobleme rnai simple care la rindul lor pot fi descornpusc in altele rnai simple si asa mai departe. In fclul acosta se ajunge la 0 descompunere arboresccnta a problcmei date in subprobleme mai simple. Prcgramarea subproblernelor devine 0 problema mai simpla ~i fiecare subproblema are 0 anumita independenta fata de celelalte subproblcme. De asemenca, interfata ei eu celclalte subproblernc cste limitata si bine prccizata prin procesul de descornpuncre a problcmei initialc, De obicei, prograrnarca unci subproblerne, cornponenta a dcscompuncrii arboresccntc a problemei initialc, conduce la realizarca unui numar relativ mic de functii, Accste functii pot prclucra in comun anumitc date. Uncle dintre de sint indepcndcnte de functii lc rcalizate pcntru alte subproblerne componcnte ale descompunerii arboresccnte. Altcle realizcaza chiar intcrfata eu subproblcmclc invccinatc. Dcsprc funqiiIcobtillute in urrna .. proiSramilrii unci sul)probJell1.e~ sc obi~nuie~te sa se spuna ca sint inrudite. De obicei, accste functii, imprcuna cu date·(c pe care lc prelucreaza, se pastrcaza intr-un fisicr 0i se cornpileaza

in capitolul 7 se da un exemplu de modul prin care se implementcaza 0 stiva pentru numere intregi. In capitolul respectiv, stiva este implementata printr-un tablou cu ajutorul dcclaratiei:
s t.a i c into stack[MAX]; t

un de MAX este 0 constanta simbolica definita in prealabil si care stabilcste dimcnsiunea maxima a stivei. Nurncrele de tip int puse pc stiva sint pastratc ca clemente ale tabloului stack si cle ocupa zona:
stack[O],stack[l], ... ,stack[next~l]

Elementul staek[O] se afla la baza stivei, iar stack[next-l] se afla in virful ei. Variabila next defineste at it pozitia virfului stivei (elementul staek[next-l)), cit ;;1elementul liber al tabloului de eel mai mie indice. Initial next arc valoarea zero, deoarece stiva fiind vida, stackj O] este elcmcntul liber de cel mai mic indice. Variabila next se declara astfel:
static int next

Oi

In felul acesta, cele doua date (stack si next) utilizate pentru a implement a stiva pentru gcstionarea numcrelor de tip in! sint ascunsc in modul, avind clasa de mernorie static. Gestiunea lor ~e face prin functii globale accesibile din orice modul al programului. Astfel, push pop top clear empty jill!

ip exercitiul

7.1. s-au definit functiile:


de tip in! din virful stivei. de tip int aflat in virful stivei.

- Pune in virful stivei VI1numar de tip into


- Scoatc numarul - Perrnite acces la nurnarul

- Videaza stiva. - Returneaza valoarea contrar,


- Returneaza contrar. valoarea

independent. o colcctie dc functii inrudite,. inlpreun~i cu datclcpccarc


com~ullforin-eitzit p;·illtr~llnprogram

in fclul acesta, problema din module. Programarea modulara are la baza claborarca programelor pc module. Q.par(e din datcle utilizate in cornun de functiilc nlodulului,~it.u~chiar toate datele modulului, nu sint necesare in alte module. Aceste date pot fi protejate sau cum se mai spune,gscU/1Se_ill1I1odul. ··Li-l;~bajul C si deci si C+-f, permite ascunderea datelor in modul folosind date alcatuit care au clasa de memoric

lll1iilOdlil.

IcpreIuc;rca;;:il in initiala se rcalizeaza

daca stiva

este vida si zero in caz


si zero in caz

daca stiva este plina

static (vezi paragraful 5.2.). Mai mult decit atit, Pl)!_!}~decl~l~t_!e?Lf~ll!.?\iile?a~tatice~i atuncicl~_\f_or fi ascunse__ill}110dlll (nu pot fi apclatc din afara modulului), Ascundcrca functiilor in

111()dt.iTse

face pentru

accle functii

care

nu se utilizcaza pcrrnitc

la rcalizarca protcjarca

interfetci datclor si

modulului cu cclclalte module. Ascundcrea datclor si functiilor

in module

prcintimpina

utilizarca

cronata

a Iunctiilor.

Datele stack si next fiind ascunse in modul, utilizatorul nu arc acces direct la ele din alte module. De aceea, ele nu pot fi deteriorate accidental. Utilizatorul are acces numai la elementul din virful stivei. Acesta poate fi scos din stiva (functia pop) sau poate fi folosit lasindu-l pe stiva (functia top). De asemcnea, utilizatorul poate pune un nurnar pe stiva numai in pozitia urrnatoare ce1ci corespunzatoare elementului din virful ei (funetiapush). Mcntionam ca stiva implementata in acest fcl nu este chiar 0 stiva veritabild, deoarece stiva, prin natura ei, estc 0 structura dinamica, In cazul de fat a , este rezervata 0 zona fixa pentru stiva deoarece tablourile din limbajul C nu sint dina mice. In capitolul lIse da 0 implemcntare pentru stivc cu ajutorul listclor simplu

60

61

~nlantuite. Acestea sint structuri de date dinamice ceea ce perrnite ca si stivele implernentate cu ajutorul lor sa fie de natura dinarnica, in acest caz, un clement al stivei este 0 data de un tip definit de utilizator si anume: . typedef struct tnod ( declaratii struct tnod *urm; )TNOD; .In acela~i capitol, pentru gestiunea listelor simplu inlantuite s-au folosit variabilele globale prim si ultim care se dcfinesc ca fiind pointeri spre tipul TNOD. La implementare.a stivelor pr~~1tr-o lista simplu inlantuita, operatiile push ~i. pop se definesc cu ajutorul functiilor iniprim si spn (vezi paragraful 11.1.3.1. si
respectiv 11.1.4.1.). . Vidarea in 11.1.5.

datclor

de tip stiva, Tipul utilizator folosit in limbajul C nu stabilcstc niei 0 lcgatura intre rcprezentarca datelor de un anumit tip ~i opcratiile exccutabile asupra datelor de tipul respcctiv. De cxemplu, in paragraful I CU., se definestc tipul utilizator COMPLEX ca rnai jos:
typedef s t ruc t; { double real; double irnag; }COMPLEX;

Prin aceasta dcclaratie se defineste reprezentarea datclor de tip COMPLEX ~i anU111e, 0 astfcl de data este 0 pereche ordonata de numere, fiecare de tip double. Sc pot declarn date de tip COMPLEX ea si date de tip int, long sau orice alt tip predefinit. De exemplu, folosind declaratia:
COMPLEX
z;

stivei (operatia

clear) se realizeaza

folosind

functia sterglist definita


.

In mod analog, se pot defini simplu si alte functii pentru a rcaliza accesul la elementul din virful stivei (corcspondentul pentru top) sau a stabili starea stivci (vida sau nu- corespondentul pentru empty) etc. Functiile de gestiune a stivei pot f rescrise in asa fel inert sa nu fie nevoie decit de variabila prim. Se po ate realiza si in aeest eaz un rnodul cu ajutorul caruia sa se ascunda dat~le. de irnplementare ale stivei. In aeest seop nu avem decit sa dcclaram variabila prim ca statica: static TNOD "print; . . Initial, variabila prim arc valoarea zero (pointerul nul). Aceasta deoarece 111I\lal suva este vida. Stivele implem~ntate ca mai sus nu sint convenabile daca intr-un program este nevoie sa se foloseasca, in acelasi limp, mai multc stive pcntru elate de acelasi tip. Intr-un program se pot defini ~i utiliza oricite date pentru tipuri prcdefinite, De exemplu, putem defini date de tip int prin declaratii de forma: int I1wnc_1,l1ume_2, ... ,nume_n; Cu. astfel de ~jate se pot realiza diferite operatii predefinirc, cum sin! cele patru operant, operatn de comparatie, operatii logice etc. In cazul tipurilor de0nite de utilizator se defineste modul de reprezentare al datelo_r, ~ar n.u ~l o?era\1I1e care se realizeaza asupra datelor respective. De aiei rezulta sirnplitatea III prelucrarea datelor de tipuri predefinite in comparatie eu tratarea date lor ale carer tipuri sint definite de utilizator. Pentru a putea _utiliza simplu, intr-un program, mai multe stive pentru date de un acelasi tip, ar f necesar sa putem defini tipuI stivd, intelegind prin aceasta ca se definesc atit reprezentarea datelor de tip stiva cit si operatiile adrnise asupra 62

insearnna ca z este 0 data care sc compunc Accasta dcclaratie cstc analoga eu declaratia:
int ii

din doua numcrc

de tip double.

prin care se stabilcstc


operatiile

ca i este 0 datil de tip into Cum tipul in! are predefinitc :ji asupra datelor de acest tip, rezulta ca declaratia de mai sus, precizeaza atit reprezentarea lui i (reprczentarea in binar prin complement rata de 2 pc 16 biti) cit ~i opcratiilc posibile asupra lui i. De cxemplu, cxprcsiilc de mai jos sint
i+l0 i/123
:1.++

corecte:

etc. in cazul eomponentele z.real z.imag datei z, cstc prccizata sale: numai reprezcntarca a lui a lui
Z. Z.

lui - ;>1 acccsul

la

Acces la prima components

Acces Ia a doua components

La definirea tipului COMPLEX nu sc precizeaza nimic asupra opcratiilor adrnisibile pentru datele de acest tip. Otilizatorul poate defini astfel de operatii prin intcrmediul functiilor. De cxernplu, pentru adunarea numerelor complexe se ponte defini functia:
void
{
C

adcornplex(COMPLEX

*a,COMPLEX

*b,COMPLEX*c)

-> real -> :i.mag

a -> real + b -> real; a -> imag + b -> imag;

63

In fclul acosta, daca u,v,w sint dcclarate


COMPLEXu,V,W;

ca mai jos:

opcratii asupra datelor structurii, De excmplu, functia de prototip:

int
atunci apclul:
adcomplex(&u,&V,&w) ;

pcitcomplcx(complcx

*a);

care

citeste

pointcaza
egaI cu suma

partea rcala ~i cea imaginara a nurnarului complex, spre care a, ponte fi definite si utilizata pentru numere de tip cornplex.desi ea nu

rcalizcaza rcspcctiva,
If.]

suma dintre numercle complexe u si v, iar w devine ceca ce in notatie maternatica se serie astfcl:

a fast enumerata in dcclaratia struct de mai sus. Datele de tip complex se definesc in mod obisnuit:
complex z:

u+v

in mod analog,
numerc complexe

prin intermcdiul functiilor, se pot rcaliza ~i alte operatii (vezi cxcrcitiilc 10.1,10.2,10.12,10.13,10.14,10.15,10.16,

cu
~l

Aceasta

inscamna

ca

este

data care are doua componente:

real imag
de tip double. Funcriile mernbru care sint foarte simple pot fi definite in cadrul declaratiei struct inlocuind prototipul prin antetul si corpul functici respective. De cxemplu, prototipul:

10.17).
Prin rcalizarea aces tor functii nu se prccizeaza ca ele definesc opcratiile asupra datclor de tip COMPLEX ~i ca alte opcratii sint interzise. Un prim pas, in incercarea dc a apropia modul de tratare al tipurilor utilizator de eel al tipurilor predefinite, a fost acela ~I<:_'~Q1'~ciza, 1a definirea tip_ului utilizator, 11U numai rcprczcntarca datclor tipului rcspcctiv, ci ~ijlltlciiilecare dcfincsc operatii eu datclc detipul respectiv. . _ . - Acest lucru obtinut sin'lplu prirlenumerarca rcspectiveimpreunacu ~efinil~e.arepn.:ielltii.riiclatclor.

S~;l

prototipurilor Iunctiilc

functiilor ..- .. ,

double
din dcfinitia modul:
double

modul(); tipului complex


modul () .( return

De cxcmplu,
operatiile

pcntru tipul complex putcrn cnumcra cu datele de tip complex, ca mai jos:
II rcprczcntarca tipului

care rcalizcaza

de mai sus, poatc


sqrt (re,al * real+

fi inlocuit

cu definitia
}

functiei

struct complex double real; double irnaq;

imaq* imaq);

II tunctiilc prin care se rcalizcaza opcrauilc asupra numcrclor cornplcxc double modul (); Ill1lodulul numarului complex double a r q () ; II argumcntul numarului complex void neq ( ) ; II real = -rcal si imag = .. imag II real = a.rcal+b.rcal; imag = a.imag+b.imag void adcomplex(complex a,complex II real = a.rcal-b.rcal; imag = a.imag-b.imag void sccornplex (complex a complex
I

TI;tn tc[1orurd~Cl[1l:'111C; :1:i,~;{cT(feci diicas lll( f()artcsill1j) r

1110~;~~~;fi~f/~11:~1~~~~\«ftqf.¥'~tlif;f~~{t~1l2~6~~~).0D~~~c~ef~~;1·~~v~~~}{-~j~~~~

"-Func\liie ii.lelTIbrl;:"dai~:;ii~ "il1 declai',lliei struct, se pot expanda inline daca sc declara explicit acest lucru, Deci, functia modul de rnai sus, poate fi definite! inline in afara dcclaratiei struct daca se dcclara explicit ca fiind 0 funciie

aram

Ie:'" ..' . .." .'.,_.... ".-..-..

J~

in line.
b);

b);

};
':I

II sfirsit struct complex CnUI11Cratc

l;Ul~~J~ilc

ca
facilitati

complex, deosebite

sc numcsc

functii

membru. Prin

Functia mcmbru arg cste destul de cornplexa (are peste 3 instructiuni) si de accea ea nu va f cxpandata inline. Deci, pentru ea se indica prototipul in declaratia tipului complex si se dcfineste in afara declaratiei respective ca 0 lunctie obisnuita. functie nlcll1brucare se defineste in afara declaratiei tipului a .carui membru cste, se'C3:i1 fl'dl eLl litlll1dc"i{puTlICii!Il;"111termedi"tif 0pc;'at()ruluidcrezo Ill\lC;( :). ~tfcl:numeIe dii'ia11tet C\.l:··_ .. ·· ..··_-'_· ...... - .... - ..... _-_

Ti,ric\rc'j

sc inloculc;t'c
arg
it

aceasta

nu

se realizeaza

dcoarece

cnumerarea

nume _tip: .nume ..functie _lI1embru

functiilor

membru

indica, pentru programator,

doar faptul ca functiilc respective


respective.

De cxcmplu,
antetul:
double

functia

mcmbru
() { .,.

tipului

complex,

definit

mat sus, arc

sint strins legate de datclc componcntc

ale srructurii

Programutorul
64

ponte dcfini Iunctii suplimcntarc

care sa rcalizezc

~I

alte

complc x : : iHq

65

Aceasta conventie se aplica si pcntru functiile inline care sin! definite in afara definitici tipului pentru care elc sint functii membru , De cxemplu, functia tnodul se ponte defini ca functie in/inc in afara definirici tipului complex astfel:
.i n l i ne complex: :modul () ( return s q rt. (real*real+irnag*irnag); }

uncle tipul COMPLEX typedcf srruct


x; y;

sc dcfincste

astfcl:

double double

Accesul la cornponenrele date ale unui tip, numite ~idate membru ale tipului respcctiv, se realizeaza in mod obisnuit folosind operatorii punct (.) si sageata (-». Fie, de exernplu, declaratiile:
complex complex

} COMPLEX; Tipul COMPLEX definit in acest fcl, nu are functii mcmbru, Daca se foloseste declaratia:
COMPLEX a;

z:
*Pi

atunci pcntru caiculul


dmodul (&a)

modulului

numarului

complex

it

se va utiliza apclul:

La datcle membru ale lui z ne rcferim prin nume calificate:


z.real z . imag.

in mod analog, la datele mernbru ale nurnarului p nc referim prin:


p ->

complex

spre care pointcaza

real

Parametrul formal z al functici dmodul este COMPLEX pentru care se calculeaza modulul. EI pentru a avca acces la cornponcntele parametrului In cazul apclului unci functii mcmbru cxista paramctru. Numclc lui cste this. El arc dcclaratia implicira: tip * const this;

un pointer vsprc data cle tip se utilizeaza in corpul functiei de la apel. .. in mod implicit un astfcl de

si
p -> irnag.

In continuare, ne intereseaza ape lui functiilor membru. functie mernbru se poate apela numai pentru 0 data de tipul pentru carefunc\i~l~e~p'~cii\l~leSte

unde:

tip

. Este tipu! pentru care functia apclata este lui this sc dcfincstc
apclul: la ficcarc ape! al functici daca sc foloscste

functie

membru.

inen15il.l.-

. ......

..'

. . .... _-

.....

..

Valoarca •

mcmbru

astfel:

apclul unci astfel de functii se folosesc acecasi operatori ca in cazul datclor membru, adica punctul si sageata, Astfel, pentru calculul modulului numarului z , declarat ca mai sus, sc va utiliza apelul:
Z.

numedata .nume_limctie( ...) atunci this arc ca valoarc adrcsa datei numedata; • daca se foloscste apclul: pointer -> nutnc _lilllctie( ...) atunei this arc aceeasi valoarc
Cit

modul ()

In mod analog, pentru a calcula pointeaza » se va utiliza apelul:


p ->

modulul

nurnarului

complex

spre care

si pointer. datci.

rnodul()

Din aceste apeluri se vede ca in cazul functiilor membru nu cste nevoie de un parametru pcntru a ave a acces la data curenta prelucrata de functia apelata. In cazul functiilor obisnuite, functia arc acces la data respcctiva daca aceasta se transfera printr-un pararnetru sau este 0 data globala, De exemplu, functia dmodul pentru calculul modulului unui numar de tip COMPLI:.:X a fost definita in exercitiul 10.1, ca mai jos:
double
(

Pointerul this se aplica in mod implicit la componentele Astfcl, daca considcrarn apclul:
z .modul ()

atunci this arc valoarca implicira adresa lui z , adica &2. Tn cazul functiei modul, this se utilizeaza in mod implicit. De aceea expresia:
real*real+irnag*irnag

dmodul(COMPLEX*z) s qr t; ( z -> x*z


->

in mod implicit se aplica la componentele


cxprcsia rcspcctiva
._>

datei spre care poinrcaza


->

this, adica

se interprcteaza
->

astfel:
iInag'kthis
->

return

x+z

->

y*z

->y);

this

real_*this

[·(!al·j·this

imag

66

67

Se obscrva ca utilizarea implicita a pointerului {his simplifica mult dcfinirca functi ilor 111el11 bru, Pointerul this poate f utilizat in mod explicit, de catrc prograrnator, in functiilc mernbru, daca cste nevoie S[I se faca refcrirc la data sprc care pointcaza {his. Functiilc mcmbru pot fi enumerate si pcntru tipurilc utilizator introduse prin lillian. Acestca au acelcasi facilitati ca ~i in cazul tipurilor definite eu struct. Din cclc de mai sus, rczulta c[lt_PuriJs. . .ge._clate prczinta dOU[1aspecte: unul legat de reprczenlarca dale/or, ceca cc inscarnna ca tipul cstc 0 multimc de date care au aceca(ii rcprezentarc, iar celalalt aspect cstc legat de (jPf!.!:q_(ji{c: care sc definesc asupra multimii respective. Tipurile de date definite in acest fcl se numesc I!puri abstracte de date. DJ:l.t:I.tile<l~!T(.lcteg£9'lte-'1l:l.ca ~ic:of!1£~)nc.l:t(;.,\titi'!l~~li·~~ii~~~iiT D~'aceea, tipurile abstracto pol fi considerate ca 0 gcneralizare a tipului utilizator la dcfinirea caruia sc au in vederc nurnai componentelc data. Un tip estc considcrat de B. Stroustrup ca 0 reprezcntarc concreta a unui concept. Dc cxcrnplu, tipulJZoat din limbajcle C'sau C++ defincstc 0 subrnultime a multimii numcre lor rationale asupra carora sint definite difcrite operatii ca: ad un are, scadcrc, inmultire etc. De obicei, mice problema utilizcaza atit conccpte carora lc corcspund tipuri predefinite in lirnbajele de prcgrarnare cit si conccptc carora nu Ie corespund astfel de tipuri. Un cxernplu simplu este conceptul de stiva pentru care, de obicci, nu exista un tip predefinit in limbajele de programare. Pentru astfcl de conceptc, utilizatorul unneaza sa dcfineasca tipuri noi, Acest lucru se poate rcaliza numai in parte in limbajul C cu ajutorul tipurilor definite de utilizator, dcoarccc nu se precizcaza operatiile cu astfcl de tipuri, ct numai reprezentarea lor. Asa cum s-a aratat mai sus, tipul definit de utilizator ponte Ii extins in limbajul C-H asa incit odata cu dcfinirca reprezcntarii datclor unui tip sa se enumere, SaU chiar defineasca, functiile cu ajutorul carora se rcalizeaza operatiile cu date Ie respective. Cu toate acestea, tipurile definite in acest fel nu reprezinta suficient de bine conccptul pcntru care s-au definit. Principalul ncajuns rczulta din faptul C,I tipurilc introdusc in accst fcl nu definesc 0 lcgatura strinsa intre datcle mernbru ~i functiilc membru. Astfel, date lc unui astfcl de tip pot f acccsatc si prclucratc ~ide altc functii dccit ccle prccizatc la definirca tipului prin struct sau union. Accasta inscamna C[I la compilarc nu se pot stabili controale in legatura cu utilizarea datelor de tipul rcspectiv in diferite functii, De aceca, utilizarea eronata a date lor, de astfcl de tipuri, de obicei nu poatc fi PUS,I in cvidenta prin compilare. Sc obisnuicstc sa sc spuna ca datcle de accst fcl 11U sill I protejate. Amintirn ca programarca modulara pcrmitc 0 anumita protectie a datclor prin ascunderca lor in modul, Accasta idee a condus la notiunca de clasa in limbajul C++. De data accasta

se incearca ascunderca datclor la definire'lJi.I?ului abstract. Astfel, datelc membru (0 parte s-;~~'j;;to t,J1;t~)lJ2n~E2_tii<ilej)1121:iL~l~~G~c_£~-i1J.U~_~1.£.p';:illJ~~£1~S! l!l!_sin t fUI1c;tii_Jl1f!l.~E~I.illc;t e ip~~I.l:lLl:C;.s_p~_c_tiy· O-c-"Zlscmenea, 0 J?arl e din fun c.iElc;.!~!c;~~J2!'pgJ,nj.iS]c;_£ro tsi.~lt~I~12.C.12~1!l.!lt!l ape late decit nurnai de catre functii membrualetjn1l1l!iX9speQtiY, --Prote~tiilc-de ,;~-cstf~i-~--;:~";;li~~~;~<i-~~l claselor ~i ele se definesc ~j~torul folosind modlficatoj] le »rotectie. Acestia sint trci: E.riv~!£e2..£!'!'!_£I!~te,cI_~ijZ[!b..{{~::. Modificatorul iublic aplicat la 0 data sau functie mernbru face ca, com pon en ta respect ivtl S{~"fI.£121:~.L£iLR2:<ol.tc;Ji uti li;?;~ltAFIE~re~!riC:1E.in pro,gr.am. Primii do~ modificatori ~~Je 'ijJJ.?!.~!..:~:teG:) asigu:a rn:?lC;.Eti~,~!~:t~L~~ functiei membru. Efectul fiecaruia, din acesti mOOtficaton, va fi explicat mal tirzil~.-Tnm~l~~~·ntul de fata amintim ca modificatorii se seriu urmati de doua puncte ( private: - public: - protected:). o clasa se defineste printr-o declaratie de clasa. Aceasta are acelasi format ca si declaratia struct, schimbind cuvintul struct cu class. lntr-o astfel de definitie, modificatorul privati? (:ste..iI11plls:it.: Tipul complex, definit mai sllspr;n,;t;:Uc't~Tf detll1ril1'iJr;;lti:~ocE;s~1s t fel: a

*'

class complex ( double roa l . double imago public: double modul ()


(

return

sqrt(real*real+imag*imag);

double arg(); void adcomplex(complex void sccomplex(complex


};

a,complex a,complex

b); b);

Datele membru real~i i!nag sint protejate prin modificatorul impliciti~;l~~iliD Aceasta-ll1.~calnnilci\-la ~_1~~!. au aeces dc.<:;!.tJ!::l.!!£1iil£J~£!"1}br!::l.~tls,_sl~~~i; adica functiile modul, arg, adcomplex si sccomplex. De exemplu, nu este posibil sa atribuim valori componcntelor real si imag, sa afisam valorilc lor etc. In acest caz se rcalizeaza protectia datclor respective. Deci, daca vorn defini 0 data de tipul complex: complex atribuirile: z.real z.imag 1; 1; 69 Z;

68

sint crenate si vor fi sernnalate Ja compilare. Funcriile mernbru ale clasei complex sint to ate publico (un rnodificaror de protecrie esre valabil din punctlll aparitiei lui pina la sfirsitul definirieicIisei SaD pin a in punctllapari\iei U~1llia(tn1od'ificatoi'de protcc\lcT-------.---r:-.-.c'.-~--- .. -.- .. -"Aceasta insearnna ca ele se pot f010SI in tot programul pentru date de tip
_-_.-.•••. "'. ,'~, .... '~._, •• <C_.. ""' __ , ..... ~ ... _.. ,_ ........

. lIlt '1'1'e (11'11proor'l!11 In fclul nccsta . . ,!-tti'! (utilizarea) clnsci cu ce e ace, s , to' '" .... ~~l~i~mentarca unci clasc poatc 1"1 schimbata I~mla schirnha urilizarcu CI in rcstul programuilli. Excrcitil:

complex. Tipurile definite prin struct ~i union au toate componentcle pub/ice. De aceea, despre struct, se obisnuieste sa se spuna ca este 0 clasa cu toate cornponentele

Sc considcra 21.1 defineste

sa sc delineascil

tipul complex, definit ca mai jos, cu ClJu[orullui struct: Se_~er~ [unctiilc mcmbru ale tipului rcspectiv. Funcna (/}<"O SC 10.2.

la fel ca in excrcitilll

pub/ice. Clasele asigura protectia

datelor si a functiilor mernbru la un nivel superior fata de module. Ele permit definirea simpla de tipuri noi, care se nurnesc tipuri abstracte de date. Tipurile introdusc cu ajutorul claselor se apropie de cele predefinire si de aceea se pot defini ~j utiliza simplu date de tipuri abstracto in. comparatie cu facilitatile oferite prin module. Asa cum s-a ararat mai sus, modulele nu of era 0 solutie simpla cind utilizam in program, in acelasi timp, mai rnulte date de tipul celor ascunse intr-un modul. Clasa of era osolutie simpla pentru astfcl de situatii asa cum se va vedea in continuare ~i accasta se realizeaza pe baza apropier ii modului de utilizare al tipurilor abstracto de a celor predefinite. B. Stroustrup afirma ca, in principiu, clascle permit sa se introduce tipuri noi de date pentru care accesul cste limitat princr-un set de functii bine precizat. Program area bazata pe utilizarea tipurilor abstracte de, date se numeste program are prin abstractizarea date/or. Ea este superioara programarii modulare asigurind protectia datelor la un nivel calitativ superior care rezulta din facilitarile existente in definirea ;;i utilizarea tipurilor abstracte de date. Intrucit tipurile abstracte de date se definesc in limbajul C++ prin interrnediul claselor, rezulta ca la baza programarii prin abstracrizarea datclor se afla notiunca de clasa, In principiu, programatorul trebuie S[1 stabileasca clar conceptele de care are nevoie pentru rezolvarea problemei concrete si apoi conceptele respective se realizeaza prin intermediul claselor. La stabilirca ~iimplementarea conceptelor necesare rezolvarii unei problerne se realizeaza un proces de abstractizare care priveste reprezcntarea datelor si prelucrarea acestora. Aceasta justifica terrnenul de program are prin abstrac-

FI!?IERUL BXXI1
#i fnc1ef _._MATH_H #include <math.h> /Ide fine f1ATfi-Jl lienc1i f struct
doub l e

complex
real
i

double double
(

imag; modul () II rcturneaza modulul numarului


+

complex

return

sqrt(real*real II returneaza

imag*imag);

double void
(

arg ();

argulIlcllllll

numarului complex *b) II calculeaza a+h

adcomplex r ea 1 imag

( r.ornp.te x =e , complex 1

a -> a -> imag + b -> imag;


* b)

void

<a , complex sccowplex (camp 1 e x

II calculcaza a-b

real imag

a -> real a ~> imag

b -> real; b .-> imag; *b) II calculcaza a*b *a,comp 1 ex - b -> real a -> imag * b * b -> imag .~ a > imag * b
->

void

mulcomplex(complex real imag

tizarea date/or.
Ca mice proces de abstractizare, si eel legat de abstractizarea datelor prcsupune un proces de generalizare care se rcalizeaza prin neglijarea aspectclor particulare. Conceptele realizare prin clase au 0 parte protejata si una neprotejatd. Partca protejata exprima partea specifica, proprie conceptului exprimat prin clasa respectiva ~i ea are rolul de a asigura implementarea clasei (conccptului). Parten neprotejata, numita ~i publica, reprezinta interfata clasei (conceptului) cu celelalte clase (concepte) ale programului. Implementarca clasei este neglijata in

a -> real a -> real

Lmaq; rea 1.;

int divco!Oplex(cornplex
}i

'ka,complex 'bl;

Ilcalcuicazaa/b

IIi.fndo f #define #define #endif

1'1 PI 3.14159265358979 ~PI

70

71

double
{

complex

arg () II rclurncaza

argumcntui

numarului

complex

double

o
0)

&& imag
>

0) return

o . CJ;

int citcomplex(complex *a) /* - citcstc partca rcala si cca irnaginara a unui numar complex; - rcturncaza: 0- la sfirsit de fisicr: I - altfcl.

*1
{

if (real == 0) if (irnag > 0) return PI/2; o lse II real Osiimag<O return (3"P1)/2;

0) return 0.0; II imag = 0 si real < 0 return PI;

if(pcit_double("partea if(pcit_double("partea return 0; return l;

r ea La : ", &a

imaginara:

-> real) == 0) return ", &a -' imag) == 0) >

0;

II real 0 si imag 'oo 0 a·= atan(irnag/real); if (real < 0) II real < () si y 'oo () return a+Pli e Ls e II real > 0 L f ( i maC] < 0) II real> 0 si imag < () t.u rn 2*PI + d; 1/ real> (J si illlag > () return a; ) /1 sfirsit arg comp]ccx :: divcomplex (complE!x "a, complex II calculcazn alb; rcturucaza () la impartirca cu zero
tnt
{

main () /* - citcstc pc a.b,c -numcrc complcxc; rczolva si - afiscaza radacinilc ccuatici: a*x*x+b*x+c = ()*I complex a,b,c,xl,x2,bp,temp,aa,templ; char err] = "s-a tastat EOF\n"; double r,argument; complex patru = {4.0,0.O}; /1 sc citcsc cocficicruii if (ei tcomplex (&21) printf(er); ex i t {I) ; "b) if(citcomplex(&b) p ri nt.f «31:') ; exit (1); if (citcomplex(&c) printf(er) ; exit (1) ;

0)

0) {

double db> it(d


reed i, rna (] re r.u rn

d; real

* b -> real

b -> imag * b -> imag;

0)

0.0) return 0; ( a -> real • b -> real ( a -> imag * b -> real

+ a -> imag * b -> imag)/d; - a -> real * b -> imag)/d;

21.2 Sa se scrie un program care citcste trei numerc complexe a, b, c care sint coeficienrii ccuatiei: a*x*x+b*x+c 0 rczolva 9i afiseaza radacinile ccuatici respective.
=0

0 && b.real ifla.real -- 0 && a. irnag 0 && c.imag b. imag -- 0 && c.real 1/ a b=c=O printf("ecuatie nedeterminata\n"); exit(O);
)

o
0)

&&
{

if(a.real
{

==

0 && a.imag

==

0 && b.real

&& b. imag

o)

PROGRAMUL

BXXI2

printf ("ecuatia exit(l);

nu are solutie\n");

#include <stdio.h> #include <stdlib.h> Hi lude "BXXIl.CPP" # i.nc l.udo "BX18. CPP"

1/ citcstc un numar de tip double

iE(a.real == 0 && a.imag == 0) { printf("ecuatie de gradul intii\n"); xI . real = +c , real; x l .imag = --c. imag; x2.divcomplex(&xl,&b) ; printf("x=%g+i*(%g)\n",x2.real,x2.imag); ex i t (0) ;

72

73

Illemp = b*b 4*a*c bp.mulcomplex(&b.&b) ; temp.mulcomplex(&patru.&a) ; templ.mulcomplex(&temp. &c); temp.sccomplex(&bp.&templ) ; 1* temp = real -I- i * imag r modulttcmp); argument = argttcmp) *1 r = temp.modul(); ar.gument = temp.arg(); 1* temp = r*(cos(argumcnl)+i*sin(argumcnt)) sqrl(temp) = sqrl(r)*(cos(argumcntl2)+i*sin(argumcntl2)) r sqrt(r); argument = argument/2; II temp = sqrl(b*b-4*a*c) temp. real r*cos(argument);
temp.imag::; r*sin(argument)
i

22. CLASE
La prcgramarca problernelor complexe intervin concepte noi care nu pot f exprimate simplu prin tipuri predefinite de date. De obicei, orice limbaj de programare pune la dispozitia programatorului un numar de tipuri predefinite, care insa, in mod frecvent, l1U corespund tuturor conceptclor necesare programului. Astfel de conccptc se implemcnrcaza in limbajul C++ prin intcrmediul clasclor. -x 0 clasa defincste un tirabstractde date. ¥ 111~1!ti.1'l1?_..d~ date care au 0 aceea~j ~~l?_r~~~!~E.'E ..~,i.p,~l~~r.L.I.c'II:~~~t.£(~e fi.llit_setulcjegpc.rc1Jii._carese .Eot ex cc u ta ,1SU pra c.:lC:l~l~~c.I~!:.n!l!lt~TfliLr.(;spec:!i~(;: exemple de concepte care nu corespund ur;cii: Ca tipuri predefinite din limbajul C++ amintim: sir de caractere; numar complex;

*1

Print~~=~i}~:?i.ac"t{!edati~}11teieg:em2 ...

lista;
II aa " a -I- a aa.aclcornplex(&a.&a) ; II x I cc (-b-l-lcl11p)/aa bp.real -b. real; bp. imag -b. imag;

II bp = -b

II temp I = -b+tcmp tempi. adcomplex (&bp. & temp) ; xl.divcomplex(&templ.&aa) ; II xl = (-b-tcmp)/aa tempI. sccomplex (&bp. &temp) ; x2.divcomplex(&ternpl.&aa) ; printf("xl %g + i(%g)\n".xl.real.xl.imag); printf("x2 = %g+i(%g)\n".x2.real.x2.imag);

arbore; - etc. Pentru fiecare din accste concepte se ponte defini un tip abstract de date prin intermediul claselor, Din definitia tipului abstract de date rezulta ca acesra are 2 parti, 0 parte care dcfineste reprczentarca datelor tipului respectiv ~i 0 parte care defineste opcratiile asupra datelor respective. Parten care dcfineste reprezentarea datelor cste fermata din componente care sint date de diferite tipuri, Aceste componente se numesc date membru ..•. Parten care defineste operatiile asupra datclor tipului rc~pccti~' contine functii n u mite .[j/I1C [i!.'1!..:"?I/-l!_'!I: ¥ Prima inccrcare de a face legatura dintre reprezcntarea datclor unui tip si operatiile asupra datclor respective a condus la extinderca constructiei struct, asa cum s-a vazut in capitolul precedent. Astfel, constructia struct permite definirea rcprczcntarii datclor tipului care se introduce de utilizator (dale membrui, precum si enumcrarca functiilor care definesc operatii cu date Ie respective
ifunctii membruy.

Acest fapt nu este inca suficicnt pentru implemenrarea tipurilor abstracte de elate deoarece nu se asigura protejarea datelor mernbru. Elc pot f accesatc direct $i de catre alte functii decit functiile rnembru. Lipsa unci protectii a date lor, face ca tipurile de date introduse prin constructia struct sa nu poata f supuse unor controale cu privire la operatiile care se executa asupra lor. De accea, pasul urmator in implernenrarea tipurilor abstracto de date este acela de a introduce protejarea datclor si functiilor membru. Acest lucru a condus la notiunea de clasd.

74

75

Protejarea datelor si functiilor membru se realizeaza utilizind modificatorii de


proteciie: - private; - protected; - public.

II functii mcmbru }; In continuare,


complex a;

putem defini date de tip complex in mod obisnuit. De exemplu:

Acesti modificatori sint urmati de doua puncte, Modificatorii private si protected protcjeaza elementelc (date ~i functii mcmbru) aflate in domeniul lor de acti une. D~1111eniulde actiuneal unui modificator dcproteqie tine din punetulin _~~t:£ cste SC ris •. lci(jifl~il t~;:~Crcs~c-c-ti n v-~Tpil1iCl;;"sfri;~ltlir(fc fl i11tiercal'c--i l-cori,\in'csa u l? in~I~~I1al!_I12~d}'fi~~!()i:_-9~EE§'§~?f0'~-""- ...., -_.. " ..._-:--..--~ ...---~-.-~- ....~.-~-:. ' Membrii din domeniul de actiune al modificatorului public nu sint protejan ;>1 ei pot fi folositi fara restrictii in tot programul unde ei sint "vizibili'', ~~_l1~()~_}.!l!.p_lis:.i~,--g1eEr.1,~E~! __ ..u!2~L_c;~~~ s~~~.r!:?~~j~-~!-S~l ..~U_!!_C:Il]:l.ILi~L~_'!!'~~~~!.. afla in domeniul de actiune a lui private. Despre un astfel de membru vorn spune cil cste-J;;:;-v-at."-l~l po~itc7i';_lilTlzat--accatre 0 functie membru dar nu ~i intr-o functie arbitrara. Yom spune ca accesul la un astfcl de 111CmlJI'l1 ..~_c:.J~C.~_~~E~_e_!! _l]-_~! 0...J!icJ_!!:e(:tpl:i~1_}11!SI2.~~~i.l~~~_f':1::__c.@£~_._i11.~I1:l~I~~::1:ri.,"· es te v ala b iI ,icc f,{i iiucru pentru tipurile definite cu ajutorul construcnei struct. In acest caz, membrii data saujill1c!ie sint in mod implicit publici, dcci la ci putern face acccs direct, Accasta explica de ce in prcgramul din excrcitiul 21.2, se pot folosi direct (in afara functiilor mcmbru) cxpresii de forma: a.real ;;1 a.imag unde: a
Intr-adevar,

afara functiilor
a.real a. imag

defincste pe a de tip complex. In acest caz, a este 0 data care are doua componente: real si imag , ambele de tip double dar ele sint private si deci nu putem avca acces direct la elc, De aceca, instructiunilc de mai jos sin! interzise in

membru:

1; 2; real,a.imag);

printf("a=%g+i*(%g)\n",a

obl~nu"~..: Deci,
complex a

, Mai mult

decit
0

am, dalele d~_5~eeS!.JiQ__ll.i£i.l!!l__P.?t f!,_ i_l1ltl<:t.~i~aten mod i dcclaratic de forma: _~~~_w. _


{L. -1} ;

este interzisa.

numai op~~atiTLs::2:~:~{~;~~I£~~u-!i.~·I~~~i:~_}O~2i;]$~~,"( ii;odur"~lrg~l~cr;t,',~dLi;1are: scadere, inmultire ~1'll11partlre), el ;>1 alte operatn cum sint:
initializare;

fune\i'i iorn1C'iTIbrti~"-rczlITta"ca'estc",i1-cvOTedc-flillcfir"meITIbJ:u eai:~srr~~iG~eze-m;" l


J

l_2_e_oarecea datclc mcmbru real si imag este posibil accesu] prin intcrmcdiul l

- Este
constructia
0

afisare.

:Itribl~ire;

r -----·---- ..-~-'--'''--''-~·'·''·····W

--."."-''" ~ .. -'..,-.'''''" .... .. ,


.. _ --.....

variabila

de tip complex.

Este necesar ca to ate aceste functii membru sa fi~lb1ic~ Rezulta ca varianta pentru definirea tipului complex ar putea fi ciasaTemai jos:
class complex ( II date membru private double double public: void real; imag;

prima

struet nu protejeaza datele mcmbru real si imag, deci ele pot fi folositc in mod obisnuit, la fel ca in limbajul C. De aceea, cOl11pilator~d nu poatc realiza nici un control asupra operatiilor realizate cu datelc de tip complex, definite cu ajutorul constructici struct, ca in cxercitiul 21.1. Cu totul alta cstc situatia daca definim tipul complex cu ajutorul unci clase. Mcntionam ca pentru a defini 0 clasa se utilizcaza acclasi format ca si in cazul constructici struct. La d~finirea tipului complex ell ajutorul clasei vom proteja datcle mcmbru, adica real ss imag. Formatul clasci pentru tipul complex va fi: class complex 1 II date mcmbru double real; double imag;

II functii mernbru publice atribuire(double x = a,double real

a)

II rcal+i*imag

= x+i*y

x : imag

y;

double
(

retreal

() II rcturncaza

partea rcala a numarului

complex

private
{

return

real;

double

.r e ti maq ()

II rcturncaza

partca imaginara

a numarului

complex

76

77

void afiscomplex(char *format} II afiscaza numarul complex conform fonnatului


(

dcfinit

de pointcrul

forma!

printf(format,real,imag);

Functiile membru sint functii inline, exceptind functia divcomplex, care, continind mai rnulte instructiuni dccit cclclalte, a fost definita in antra definitici clasei complex ~ideci ea nu este 0 functie inline. in antctul functici divcotnplex s-a utilizat numele:
complex :: divcomplex

void

adc omp Lex (complex'x, real imag

complex

*y) II calculcaza

x+y

x -> real + y -> real; x -> imag + y -> imag;

void

negcomplex(complex real imag -x -> real; -x -> imag;

=x ) /Icalculeaza-x

void

sccomplex (complex real imag

*x, complex

*y) II calculcaza x-y

x -> real-y -> real; x -> imag - y -> imag;

void
(

mulcomplex(complex real imag x -> real*y x -> real"y

"x,complex
-> real-x ->

*y) Ilcalcuicazax*y
-> imag*y -> ->

imag+x

imag*y

imag; -> real;

};

int divcomplex(complex 1* - calculcaza x/y; returncaza: 0- la impartirca cu zero; I - altfcl. *1 II sfirsitul dcfinitici clasci complex

"x,complex

*y);

construit Cll ajurorul operatorului de rezolutie, Aceastaregulil sc utilizeaza pentru t~~t~ful1C\iilelllen1bru carc.lllI sc dcfinesc in "T;teriorlll def~;lf\;cCclaseC'pei1irLI care clc sint functii membru. o clasa defineste un tip care a fost numit tip abstract. Pat-tea privata a unci clase defineste .Illodul. de implemcntare al datclor de ti.fluLab~}t.:a~J~cacil~rc d e--cl,isa --res pec-tivij.P~ite~'1_J?l1_~I;~~:defi n ~~i in te_lj~~Lel. CC aces tor elate cure~.tc~lLp!_(~~E~l!:!luJuj. Aceasta interfata contine, de obicei,illQ<,:tii care au numitejimc{ii membru. Functiile mernbru se mai nurncscsi :':t!etod~ In general, partea publica poate contine si date membru, dar atunci datele respective nu mai sint protejate, lucru care pc cit posibil trebuie evitat. Asa cum s-a subliniat mal sus, lipsa unei protectii pentru datele mernbru IlU perrnite compilatorului sa controleze opcratiile realizate Cll datcle respective. in cazul clasci complex de mai sus, programatorul nu are acces direct la cornponentele real si imag ale date lor de tip complex. Teate operatiile care se pot realiza Cll datele de aces! tip sc fac numai prin intermediul functiilor mcmbru care au fost dcclarate ca publice. Q_'lt.l~!~al~_,C{ll·or tipuri sc dcfinescprintl;~()cIaS[l se numesc~)!~~~':9Cll altc cuvintc, un obicct in C++ este () datil de lin tIP abstract. Obiectcle, la fel ca ~i datclc prcdefinite, se dcclara printr-o declaratic. In forma cea mal simpla, 0 declaratie de obiect are formatul:
_____ ~_ •• ,,~."_"""' __<,_,, __

·_.,.! __...~"o, ..... '"_ ... _,._._,,_,.__ ,

••• _,_.'•.,;.

__

"""''''''''",',.

__ '0''_'' ____ 0 ''0

''-"~

__ ,_._

.....

,_.,,,_.I

->:

11 um

c_ close! lisui _de nume _dc_ohiectc;

undc prin listd_de_lllllJ1c_de_ohiectc intelegem un nume sal! rnai multe separate prin virgula, De aserncnea, nume _c!asd este un nume. Excmplu:
"a,complex *b)

int complex:: divcomplex(complex 1* - calculcaza alb; - rcturncaza: o - la impartirca cu zero; 1- altfcl. *1


(

Daca sc considera definitia clasci complex de mai sus, atunci:


complex z,xl,x2;

double

d;

d b -> real*b -> real+b -> imaq*b -> imag; if(d 0.0) return 0; real (a -> real*b -> real+a -> imag*b -> imag}/d; imaq (a -> imaq*b -> real-a -> real*b -> ima~)/d;

declara pC z, xl ~ix2ca ()~iecte,adica date de tj]Jc;(JJi1p1i:':: Despre oblc-ctele unci clase seobl;iJ1l.iTe~"tcsa se spunfl-ca sint instantier! ale clasei respective. Deci z, xl si x2, sint instantieri ale clasei complex. Pentru a apropia tipuri Ie abstracte de celc prcdefinitc, se impune ca obiccrclc sa ponraf illi(i{[/izatc, ---- Initiailia~cil-"~~;~l;i obiect este 0 problema rnult mai cornplcxa decit cea a datelor obisnuitc (tipuri prcdcfinitc sau definite de utilizator Cll ajutorul

78

79

. 't', cste posibila .tiil / .. / S'\U union). De aceca, 1111)<1li: area unui obiect ·.._· ..···,,·.---"IZ, L ·.··· .. ..···· construct: I UI .1 rue . ". '''-':'''r''A ""1'1 pourta dCl1umlrea de ~~cs t scop .()..fu.I:~.ti~.n:.~!~1~E.~~ 1,1.31.:.. c.~~~··~··········'-,~:'~;'~S~I'!··i-\ .. .p"e~ ~ ..:_c

complex

z; .~-

----..-:>

ConstlUctorul unci clase arc tot.deatll1a acefa,\·/.l~~,l!_!.~·~~~l '~~t: 't" .. D aca 0 .c 1as~l.<1I£.~!~E.IJc:!.<:JE la~':1.nc:i.31~.£~?C:.'!p.c:ls~~;r,<I': ta lltgl~]~:t..~: ..~t:t19_l~<;1 ..~~1.fi. '
U nLl;-;;b~~!:~L~l,~'ic:iE~spc

ad ica fara i 11i [ial iza rc, c,?I1stl'lI ct~.mtl e:~"ts~\P..c:l~~LLn..J.!l.9s!~~!gEl'!.u.~}s:_jlls,t~~t~,:~~ob ~:-:.~1l.~.E,.c:~~~11.~~l_e..c:OJ~1£.9D,,~1)!S .. ... eg~tlef~!.:?.S!'S?val 0 ri Ie imp li cite ( ale parametnlor constructorului). Obiectele sin! distruse de catre programator sau in mod automat. Distn T : biectelor se poate realiza folosind 0 functie mernbru special numita destructor. Un destructor are un nurne aparte si anume: -nume unde: nume " Este numele clasei.[

c:!!::~.

Exemplu: Pcntru

clasa complex dcfinita

mal sus, putem defini un constructor


b=O) -

cu

ajutorul functici membru:


complex(double II constructorul
(

a=O,double

clusci complex

real ~ a; [mag b;

Accasta

. .' . d 'f teste in interiorul definitiei funcne membru sc presupl~ne. C,Isc ell, d if '. . r 'a definitici clasci complex. Deci, este 0 functie 1I1bn~. Pent~·u a 0 C 1111111 a ell C . clasci complex se schimba antetul fUI1C\ICI astfel:
inline complex , (double :: compJ.ex a double ' b)

"

"

De asemenea, destructorul nu arc. parametri. EI se apeleaza de programator cind nu mai este nevoie'-dc7ltlOblccCAccstlllcru este important atunci cind obiectul a fost crcat in memoria heap. Destructorul se apeleaza automat cind obicctul lsi inceteaza ex istcnta (vezi clasele de mernorie). membru se calificind numcle lor cu numele obiectului care se ! nume _obiect.nume _jimctie _Inembru(lista parametrilor efectivii ... :

----"_

II

. '. . d l 1 -atia obiectului dura numclc lui,_~.c:. . P_c:l!tl'U <l.in I\ ~~ll.10 ,~,,~ll~l ~'?~~l<:_ :~e~'j~~~;~!~I;: (\ 111 I l:il'~)I:·c·ol~strl;c~~l:llfUf. tl':'I"l"-e {c "[;[\1' C l.nc,lllcl}n para n t ezc !£~!rl~.'::y_~~g_~ __ , _........ . . ........".._, . .. ,-_., .. I'~xclllplu :
complex z(1,2);
0

De exernplu, daca z este 0 instantiere a clasei camp/ex (complex z;), atunci pcntru a afisa partea real{1 (li cea imaginara a obiectului z, se va apela functia membru afiscomplex ca mai jos:
z.afiscomplex("partea reala

%~\tPartea

imaginara

%g\n") ;

. ... Se lI1stanlIaza initiale:


z.real
~I

bi 'Ctlll"
IC

L.,

de til) complex
. .,

ale carui componcnte

au valorile

In mod analog, daca obiectele z, Z 1 si z2 sint instantieri atunci pentru a realiza atribuirea:
z

ale clasci complex,

zl+z2;

se va apcla functia membru adcomplex astfel:


z.adcomplex(&zl,&z2) ;

. I mci se po ate utiliza 1 . .. l' in cazul in care exista o singura valoarea ce !l11\~aizare, a L, .' semnul de atribuire (=). De exemplu, declara\la:
complex z " 123;

z.irnag

In cazul in care. _.se utilizeaza • __ un .t"""=-"....,'""-'"':_ ...".~ s_preun..................-~~.~, pointer obiect: __ ._~ __ ~ __ • •.•""'-,~.,.- ..•nume _clasa "po; fllI1~!!~~:,I,~:~1_1~:I (:p~2.~'\E~£r_i!:1.~r-o _~.~ constr~f.!i~ ..9£..fQ.nll'~_. po -> nume _jilllctie _membru(lista parametrilor efectivii

este identic a cu declara\ia:


complex z(123);

Ele ini\iali1,eaZ[l obiectul z astfel: z.rcal = 123; z.imag = 0 " valoarea implicita. La
0

declara\ie

de forma:

In corpul unci functii membru, ne putern referi la obiectul pentru care a fost apelata functia mcrnbru folosind pointerul iml?l~ci"L{'-!~'. Acest pointer se utilizeaza in corpul functiilor membru in mod implicit la datele membru ale obiectului pentru care este apelata functia mcmbru respectiva, Cu toate acestea, programatorul poatc utiliza explicit pointerul this pentru a se referi, in corpul unei functii membru, la obicctul pentru care s..a apelat functia respective:
81

80

In continuare, prin obiect_<::!'I:C:~()!!lJ:_:l_I~l~g~.9_I)i~_c.!~lJ?entru care s-a apclat o flll~cticI11e_l_p~Eu, obiectul spre care poinrcaza pointerullii'J'-',---r------adica Apelul unei functii membrureferitorTa un o6ICct-~ilclasci PCl1tru care functia respectiva cste functie membru, simplifica modul de exprimare al operatiilor care se realizeuza asupra obiectclor. De aserncnea, acest mod de apel poate fi controlat de compilator, Orice apelneautorizat va fi scmnalat si eliminat de eompilator. in felul acesta, lucrul cu obiectele unei c1ase devine similar cu eel existent pentru datele de tipuri predefinite: - obiectelc se pot initializa; - asupra lor se pot face numai operatii in prcalabil definite pnn functi i membru si care sint controlabile prin compilator. Protectia datelor si functiilor membru ale unei clase care nu sint pub/ice constituie un mijloc de "ascundere" a elementelor mernbru respective, Aceasta "ascundere", numita si in~~(lJ?!._~!Lq,:!:_ realizeaza la un nivel calitativ superior fata se de ascunderea realizata cu ajutorul modulelor. De exernplu, prin intermediul clasei complex, definita mai sus.se pot instantia oricite obiecte (numere) de tip complex care pot fi si initializate, iar operatiile cu ele se realizeaza simplu cu ajutorul functiilor membru si aplicarea lor este controlata de compilator. Mai jos, introducem tipul abstract stiva pentru a pune mai bine in evidenta diferenta dintre facil ita tile obtinute pe baza utilizarii claselor. fata de cele oferite de programarea modulara, • Amintim ca in capitolul 7, a fost definit un modul pentru implementarea unei stive cu ajutorul unui tablou de tip into Mai jos, vern implementa tipuJ stiva tot cu ajutorul unui tablou de tip int care are eel mult 100 de clemente. Modulul definit in capitolul 7 implernenteaza 0 singurd stiva. In cazul de fata se pot instantia oricite obiecte de tip stiva, .
enum Boolean (false,true); class stiva ( int stack [100 J ; int ist.ack; public: s t iva ()
(

void

clear() istack"O;

II vidcaza

suva

Boolean

empty () II returncazn i~; r.ac k

true claca stiva csre vida si false nlrfcl true : false;

re turn

o"

Boolean

full () II returncuzn

true daca stiva este plina false altfcl : false;

return

ist:ack

100 ? true

);

in continuare,
stiva

se pot instantia obiecte de tip stiva:


stiva2;

stival,

La instanticrca obiccrclor stiva I ~i stiva l se apelcaza constructorul clasci, Acesta rcalizeaza atribuirea:
istack = 0;

in mod

automat

7:-···-

in felul acosta, stivele stiva 1 si stival sint vide la instantierc. Datele rncmbru stack ::;i istack sint "mcapsularc" (ascunse) in clasa stiva, fiind private. Ele nu pot f acccsatc direct en si in cazul modulului dcfinit in capitolul Stivclc sc pot gesriona simplu cu ajutorul functiilor membru, Astfcl, pentru a pune Ut1clement pc stiva stival , utilizam apclul fllllqicipush:
stival.push(expresi )

in mod analog, punct11 un clement


push ca 111ai os: j
stiva2.push(expres

pc stiva

.I'li\'(12,

apclind

acceasi

functie

II constructor Ilia inccput stiva este vida

istack=O;

void push(int int pop();

n) ;llpuncpenpestiva

1/ scoare elementul din virful stivei II sc rcturncaza clcmcntul din virful stivci
II returncaza II clcrncntul elementul din virful stivei raminc pc stiva

int top ();

r--

in felul acosta, functiilc mcmbru gcstiOt1Caz[l simplu oricitc stivc de tip stiva. Acest lucru nu cstc posibil prin intermediul modulului dcscris in capitolul 7_ Evident, se poate construi un modul care sa gestionezc rnai multc stivc, dar aces! lucru nu se rcalizcaza atit de simplu 0i elegant ca mai sus, prin utilizarca claselor, Acest fapt cxplica afirmatia lui B. Stroustrup: daca intr-un program estc suficicnt un singur exemplar al unci date de un anurnit tip, atunci este suficient un modul pcntru lucrul cu data respective. Altfcl, sc definestc 0 clasa pentru tipul datei respective 5i astfel se vor putca instanria oricite excrnplarc. in accasta consta escnta saltului realizat prin trecerca de la programarea rnodulara la stilul programarii prin abstractizarea datclor. In rezumat, programarea prin abstractizarca datclor arc la baza urilizarea tipurilor abstracte de date. in aces! scop, sc porncsrc cu stabilirca conccptclor 83

82

necesare la rcalizarca unui program, 0 parte din accstc couccptc se rcalizcaza cu ajutorul iipurilor prcdefinitc, existcntc in limbajul de programarc utilizat (in cazul de fata limbajul C++), Cclclalte conccptc se rcalizcaza sub forma de tipuri abstracto de date care sc definesc in limbajul C++ cu ajutorul clasclor. Un tip abstract de data prezinta doua aspcctc: unul lcgat de implemcntarca tipului ~i cclalalt lcgat de utilizarca lui, care dcfincstc intcrfata tipului rcspcctiv cu rcstul programului. [Inplc1l1cntarca tipului este partea Il!,Lpl"ot(;jalil, iar intcrfata.constituie partea publicaa tipt~lui, utilizabila in tot programul. ~"Despre partca prorejata se spline ca.continc informatia incapsulata in clasa care defincstc tipul rcspcctiv. La definirea unci clasc se prccizeaza: - reprezcntarca datelor tipului abstract; functiile care descriu operatii cu datclc tipului abstract. Reprczcntarea datelor se dcfineste prin componente date numite date mcmbru. Functiile care defincsc operatii cu datelc tipului abstract, se numesc functii
mcmbru. De obicci, partes incapsulata in clasa contine date mernbru, dar ca po ate continc ~i functii mcmbru. Elemcntele publicc sint fUI1C\iimernbru. Elc pot fi ~idate mcmbru, dar atunci acestca nu mai sin! protcjatc, lucru care estc binc S,\ lie cvitat, Un tip abstract de date trcbuie astfel dcfinit, incit la utilizarca lui sa se faca abstractic de implcmcntarc. Mai mult decit atit, utilizarca datclor de un tip abstract nu trcbuic sa fie influentata de implcmcnrarc. Aceasta inscamna ca implcmcntarca tipului abstract poate f oricind schimbata, Iara a schimba ~i utilizarea, in program, a datelor tipului respcctiv. De cxcmplu, la implcmcntarca tipului stiva s-a folosit un tab lou de tip int de 100 de clemente ~i variabila istack de tip int . Schimbind implcmentarea prin inlocuirea tabloului cu 0 lista simplu inlantuita (vczi capiro lul 11), interfata formata din functiile mcrnbru:

.: 1-0 . I .,'Un obiect "poate ri distn pnn tr functre'. speciala numita destructor Numcle . ,IS (e~tJ}I~~~I,~dul este numclc clasei prcccdat de caracterul "_".) , .: I~~:l~~l~ 1l1,embru pot fi definite in interiorul definiticr~lasei daca sint foarte ~l~I~;e~' ceasta dcoarcce, 1Il acest caz, ele se definesc in mod implicit ca functii

o ft.,Inqie.l11embru definita in afara definitici teaSel eons rUI! cu ajutorul operarorului de rczolutic: '
nume _ clasa ;; Ill/me _lime tie _lI1embru

. arc numcle

din antet

. ~~~_'.:!;:ltILt~l1<:.i"l'l~nc\ii . 111Cmbru~(.',,,9illifiea numele functici cu b leetulul.!Jel1tru care, .. ,,,.,£_~!.l.~.a.uncua. o_______ ;.· r....,'..... ... ",-._, "" "" ..... .. " ", "_",_~. __ se an ,1. "

...Ul11ee

11

obi F~~:li:'idtl~e ~btinute cu ajutorul ~I;~~~lor apropie modul de tratare si utilizare al ICC etoi e eel al datelor de tipuri predefinite. . O. .cbfc.'ren([lintre utilizarea obicctelor si a datelor de tip .: . d f . scrie . "1 ' un pi e e 1111 te apare la jos: lea expresu or. Asa de exemplu, daca se considera datelc dcclarate ca mai
int i.j,k; double a.b,c; Atunci sc pot utiliza expresii
k
C

de forma:

=
"

i+j; a+b;

~are sint sugestive fa(a de cxprimarca f unctict mcrnbru adcomplex:


complex
Z,U,Vi

adunarii

datelor de tip complex prin ape I 1

. ."

v.adcomplex(&z,&u)

De aceca, ar fi bine ca cxpresii


V :::: z+u;

de forma:

push, pop, top, clear, empty ~i/idl se utilizcaza in acclasi mod, Evident, functiilc se modifies, dar clc sint apclatc la fel si au acclasi cfect. Dac,l-accsCluCI:ll nu cstc realiz,15il, Trlscilll1fl[\'c,i"tlplIl abstract nu a fost bine dcfinit, dcoarecc la utilizarea lui nu se face abstractie _ciejrtlp lcmcn ta rl.:.: ... Datelc de un tip abstract sint nurnitc obiecte ale tipului rcspcctiv. Obicctele sc dcclara printr-o dcclaratic ascmanatoarc cu declaratia datclor pentru tipuri prcdcfinitc. Elc pot fi initializate la declararca lor. Obicctclc sc creeaza,de obicei, printr-un constructor, care este o functie l11en~b;u 'sp~~'lala al carui numc coincide .ou numclc clasci: COI;~t;'~lct~);Tdl;nei ~i,~;;e sc ap~lcaz'l lllt-~~li{ltf~ct)n:~ti:llil:e;;;inui ~i;;ectal cl'l~~i respective, Despre " Ull obiect al unei clase se spune C,l este 0 il1stan[icre a clasei respective,
84

sa fie acceptate de compilator si pcntru obiecte Aceasta idee d notiunea ,._'''".......sUIjJrainccircare a ',.. atOJ1IO!. lntr-udcvar de __ .... .: .... '. ~~.~££!"'J:.~t::.~Jil s·. _ .•_ .._.... .. ... OIJU se poate ' ope' t .. I ~ ,.... ;:..::;,(;...-.-.----... , .... (pune ca ra OJ u ' este supramcarcat pentru tipuri predefinite. d ;; se poate aplica Ia opcranzi de tipuri numeriee predcfinite tint lotto flo t ou e, unsigned ~l long double). De aceea, pentru a putea sc '. obiectelor complcxe z si II sub forma expresiei: c eric uc unarea

"i"

~'

z+u

predefinite. , este suficicnt ca 0pera tor I"" sa poata , c Olll de tip complex. ' c Supraincarcareu operatorilor este 0 facilitate eate ,.'Sllnp ]'j'"Ica mult . expnrnarca " .. ' . "I .' c I opeiatil 01 asupra obleetelor. Pe baza ei se pot scrie eXI' .. b" , ell date de tipuri predcflnite. )ICSII cu 0 lecte la leI ca ~l
I supramcarcat

ca sin cazul tipurilor numericc fi '..


cu operanzi

85

Supraincarcarea operatorilor se realizeaza prin constructii asemanatoare functiilor dar care all lin antet special in care cste prezcnt cuvintul operator. In sflrsit arnintim ca, supraincarcarea operatorilor pentru obiecte este completata si eu diferite conversii care se aplica la operatii cu obiectele respective. In felul acesta se ajunge sa utilizam obiectele la fel de simplu ca si datele de tipuri predefinite. in incheiere putern afirma ca, clasele sint un instrument pentru a crea tipuri noi care pot f utilizate tot asa de bine ca si tipurile predcfinite, Ideal, tipurile noi (tipurile abstracte) nu trebuie sa difere, in utilizare, de tipurile predefinite, ci numai in modul in care sint create.

Funciiilc definite sau pcntru care cste pre/ell I 11111l1ai protoripul, III definitia clasci, sc numesc iJ!!l.~li!~.!!lelllhru. Amintim ca finlcliiI~jcfin;tc II~d~!111!1!(1.url~iclase trcbu ic xa fie simple, cleoarecc._~le_:~~_~lcllnescill nlod_)mplicit ca functii inline. Pcntruil1l1cti(lc l1i'ai complexe_ sc indica III dcfinitia cl(lscil~ll-1111;;-'ilrot;;t;rurilc functiilor respective ~i cle se dcfincsc ulterior. In accst caz, antetul functici contine un numc format cu ajutorul operatorului de rczolutie: Jnllne_ clasa :: nume _lime!ie _/J1embru

22.1. Definitla claselor

o clasa defineste un tip abstract simplificat este indicat mai jos:


class flume

de date. Ea are

dcfinitie al carei format

1lista _elementelor

_membru

1;

Ulterior 0 sa vedem si un alt format mai complex, pentru clase. In limbajul C++, formatul de mai sus poate f folosit si pentru a defini tipuri noi cu ajutorul cuvintelor cheie struct si union. Deci,in formatul de mai sus, se poate inlocui cuvintul class prin struct sau lillian. De fapt, in cele ce urrneaza, vom considera ca si forrnatele in care cuvintul cheie class se inlocuieste prin struct sau union definesc tot clase, Difcrenta consta in aceea Cit, in cazul utilizarii cuvintului class, elementele membru in mod implicit sint protejate prin protcctia ) oferita de modificatorul de protectie private, iar in cazul lui struct si lillian, in \_ mod implicit elementele mernbru sint neprotejate (publice), In cazul utilizarii cuvintului struet se poate modi fica protectia cu ajutorul modificatorilor de protectie. In sehimb, in cazul utilizarii cuvintului union, elementcle mcmbru pot fi nurnai publice. De aceca, se obisnuicste sa se spuna ca struct si union definesc c1ase cu clemente mcmbru publice. In cele ce U1111CaZa vorn intelege prin clast! de tip struct 0 clasa definita cu ajutorul lui struct, iar prin clasa de tip union, 0 clasa definita cu ajutorul lui union. Numcle aflat: dupa class, struct sau union ~.~!_~~!_<:l~_ _tip!:'lt:!_Ur~.!E~~ltl~ prin definitia respectiva. El se numcsre ~i Ill/mete clasei ~i in continuare po<ltc·fi lltliTi,ltp·;;~tr~·a eclara (instantia) date de tiPt.~r;.~~p~~tiv, date numite si obiecte d de tipul respectiv. Lista elementelor membru poate contine: _ declaratii de date; _ definitii de functii; _ prototipuri de functii; - modificatori de protectie. Datele declarate intr-o definitie de clasa se numesc date nle!11!J}~1I_:_

De obicei, 0 clasa arc unul sau mai m~lhi constructori precum ~i un destructor. Acestia sint functii membru de nume spcciale, si anume, numele constructorilor <;(liJ1~i~L~_~~!_!ll1112c sci (d a d\ sin 1 m a i mult i COil st ;:;lctO-I:T,:1 Ie_cln tl;llc;;;c~~ii;; sin t functii supraincarcatc), iar numcle des1.~~lEt()1~uluLestenumele clasei prccedat de ca~~c.ter.'::lL::,(totdeauna e_!(Jstil. mult U]l.destructor).> . UJl_~I!_caz E0_!'hcular_d..':.J~~ll(;\ii membru 's!nt'cele e~re definesc operator! ~1 ~~~~IJ?_~t.l~~I_(),~~~c.tg ]s.~l.~?el_rc.specti ve .'_ Ca modificatori de protcctie am vazut se pot folosi: _ private: protected:
t'l

_ public: Primii doi asigura 0 protectie a datelor sau functiilor mernbru dill domeniul de actiune al lor, iar ultimul se urilizcaza pentru elemente mernbru care dorim sa l1U fie protejate. Dorneniul unui modificator de protcctie incepc din punetul in care cstc scris si pina la sflrsitul definitici clasei care il contine sau pina la intilnirea unui alt modificator de protcctie. De obicei, date le membru sint protejate, dar aceasta J1U inseamna ca ele llU pot fi publico. De asemcnea, functiile membru, numite $i metode, de obicci sint publice, dar ele pot fi si protejate. Cla~c:l~_p_otficlefinite ineomplet in cazul in ca.reeste nevoic sa ne rcferirn lu (21~:0 astfel de definitie incornpleta are forrnatul: - - -class nume; _ struct Ill/me; sau _ union l1ume; Dat~le melr:bru se declara in mod obisnuit. Daca este prezenta 0 clasa de ...me1110]'1e, atunci aceasta poate f numai clasa de memorie static. ~) , 0 datil membru a l~I]:ei_~La~~ ntIJ)?at_~J:i9.~;~i£luLdefinit prin cla.~ares12~~tivil: Eel PFS~I.tde .c:n~l~llarun p()lnter spre tlpulrc.sps.~.tlv sal! 0 refel:ill~~IIatipul rcspectiv. ie ennina:
\I

86

87

class

Ill/me

Complex *pz; char *format

uume "ptr;
tiume
IlUl1Ie

II corect II corect II incorect

"%g\t%g\n";

Atunci:
z. (format) ;

Sc

ref;

obiect;

afi~caz,\ COl11ponenleic l1um£lrului complex -r constructorul clasci are parametri impliciti zel:)
Acclasi cfcct se obtine folosind sccven;a:

C
1Il

cazul de falfl () () deoarece

date de tipuri intl\JduSeprin

Data mcmbru

obiect de tip nume nu cste adrnisa.


altc clasc,

In sehimb,se
...----

pot dcclara
----

pz

&z

PZ .. afi.scomplex(fot'mat); >

:;1.

5·.
I

- D<~nlc;11t;rZlcex}sicnt~~fi1lii:;;cT~i~ll1ei clasc estc din punetul definirii ci pina la sfirsitul blocului (instructiunii cornpuse care 0 coniine). De obicci, d~fini\iauneiclase se,seriela it:eeputul fi~ier~lui sursa in care este utilizata 51 Il1 alma oncarui bloc. Se obisnuieste adcsca sa se construiasca un fisicr de tip h care sa contina definitii de' clase. Fisicrul respcctiv sc include la \. inccputulfiecarui fisier care utilizcaza definitiile clasclor respective.

P:'ogramatorul poate utiliza in mod ex lie. ',. '. [L_I!_J~~l5:~~ta arc ca valoare adres:ol~i:,;Oi~l:ILE~I~., .. cQ!mll.\lI}~i s~<:_fa~_l!!Jlp~B~CtW1~'il'crn;-clnbi:u~---,,-~E ..~~~.?Llre~~L.~.S!!E~_'.~.9_~ic:g!ll.I.ll.i .. CXccp!Ie de la acesto reglJTO-'~~'prc";'''-:' funcr. l11emorie static, Acestea se ," z:~ta ul1C\llle l11embru care au clasa de .. "e nUl11esc runctn membr t t' ' poatc fi apelaia in dowlmoduri: .' II S a Ice. 0 astfel de funqie

~bU~::~_
• • Ca oriee Indr-rv-

:-n

22.2. Obiecte
Un obiect este 0 datil de un tip dcfinit printr-o clasa, Se obisnuicstc sa sc spuua ca este 0 i!lstailli.£L~.a clasei respective. Declaratia de obiecte este asernanatoare eu cea pentru datele de tipuri prcdcfinite. in cea mai simpla
I

fUl1qie mcrnbru Iolosind ,', ... ' opcratorul pune! sau sagcara. ndependent de un obi, t 'I I c . aces(c;-lz, ..'.l·l)Cl·L··l·I·····s:e;l·.-c·-:l.·l l· zce:-l~:z·_:Ei}l,l~·?~:flEI~l.~ru. .._......_ ...... ··_·· 1.1.1.b.n.. . 1'11 ~a.rc cst.e fu n cti·e 111.... . I .-------'" 'I 0 OSII1· · ·C forl11a:·-·---- .. ··...-·-····- ..·-:~··· ..··_· ~?p~ratorul de rezolutic 2. adic.j-:-b ·. ..__(.... · ____ ~ '. ..." , ' su
_

nume _', clam" ..


'
C'1Z

tume

_/.

forma, un obiect se declara folosind


_

formatuJ:

..

In aces]

uz.pomtcru

. _ tIllS I1U rnai Hoate II utilizat.

unctie _membru

slafica

Excmplu: Fie definit,ia de clasa:


class dc ( int zi,luna,an; static int zZ.ll.aa;. public, dc(int
(

\ nume _clasa nume __.._ object;

De obicei, clasele au constrllctori care se apelcazll automat la intilnirea declaratiei dc inSlalltl~;~~-~-t1l1;:~robie'et aid'lS.circspeetive.---·~-""··---·----··-···-"~'-biit~fe-n1embr~1 ~~~-;;io~a dist;-;~et-'lafi'C'carclnstanticre a clasci. Dcci, date le mernbru cxista in atitca exemplare cite obiccte au fost instantiate. 0 exceptio 0 )'constituie datcle mernbru care au clasa de memorie static. 0 datil mcmbru de

->

(:.!ryV'v\) i.A.e.

IfJ, \}
f

-* ') toatei\ ... ~i.. m. el.~~o. clasci.c ..$1 exista mtr-un ~.!a .. ..S C 1.;i.c.>Si (n.un..l. a.d.al... membrUS!l.!.tic ...i)... s.te 0 ..t.Cl t.. .. ci a.. e l instantierile exemplar.
,i.t.

z=l.int

l=l.int

pal:~<:.~.?:~o~ p~.l~tr.! ..2~ I .\

21=1995) a'

z i ::::: luna::.: z, static Boolean

1; an

--'I~'uI1CtliTc-;11eil1b;'u sint·";ntl::u~·~i~lgur exemplaroricite instantieri ar exista, 0 functie mernbru se apeleaza totdeauna in strinsa dependents cu un obicct care este 0 instantiere a clasei pentru care functia respcctiva estc functie membru, Lcgatura dintre functii mcmbru $i obiectul pentru care se face apelul se rcalizcaza folosind operatorul ElInct sau sageata. Exemplu: Consideram
complex z;

v_calend(dc

*d);

i.

tipul complex definit la inceputul capitolului.

Fie declaratiile:

Datele membru statice' 77 II nnt --. aa . . d cose biIre de eclclalte date.. care se. 'I' SIn cornune pentr 1 u. t oate l.llstant,Icrile, spre .- dis . ~ . " . ' d oca isnnct la Iiecare i 't . urrna, se !I11\wlizeaz[1 cu aji t I .. . ins anllere. Acestea din F' '. I oru consn uctorului 'UllctW ]I calend verifica d t '1 d . . . I . _ ua a ca en' anstlc'l d 'fi '. d una (i."1 an, care sint COl11poncnte ale 'lb' t I .' e 1Illta e datele mernbru zi " d fi . . . ( lec Ll UI sprc1 ca' '.. ' cca e Il1Ita de datele mcmbru statice zz II' :,', C p_oll1tca~a d, prccurn ~i , ~l aa. Ea poate fi defintta ca rnai jos:

88
89

Booleandc :: v__ calend(dc *d) 1* veri fica data calcndaristica zi, luna, an, ale obicctului sprc care pointcaza II, aa; _ rcturncaza
- ZZ,

d;

deoarece in acest caz pointcrul this nu este definit, functia v__ alcnd ncfiind c apcluta pcntru un obicct, De areca, rcferirea la datclc statice ZZ, II, ~i aa s-a facut folosind numcle clasei si operatorul de rezolutie: dc::zz,dc:: dc::aa II

True daea datclc sint corcctc ~i False altfcl.

*1 static tnrz[] int z,l,a;

to,

31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 3l};

if (d -> an < 1600 II d -> an > 4900) return False; if(d -> luna < 1 I I d -> luna> 12) return False; if (d -> zi < 1 II d -> zi > tnrz [d -> luna] + (d -> luna==2 && (d ->an%4==0 && d -> an%100 I I d ->an%400 0))) return False; z dc .. zz; 1 dc .. 11; a ::: de .. aai if (a < 1600 if(l < 1 II

22.3. Domeniul unui nume


Unui mane ii corespunde un domeniu. Accsta se defineste prin declaratia lui salt este corpul uneifunctii daca cl cste nurnele unci etichete. Prin bloc intelegem 0 instructiune cornpusa. In limbajul C 0 declaratie poate fi in intcriorul unui bloc sau in afara blocurilor. In plus, in limbajul C++ 0 dcclaratie poate f ~i in interiorul unci clase (in interiorul declarariei de clasa): o dcclaratic, care este in afara blocurilor sau a elaselor ~i care nu este 0 declaratie de date externe, se spunc ca este 0 definitie. Pentru un nUI11Cvom distinge 3 tipuri dc domenii, in functie de pozitia declaratiei (definitiei) sale. Accste tipuri sint: local.fisier ~i clasa. Un nume declarat intr-un bloc are un domeniu de tip local. Acesta inccpe in punctul in care este declarat si tine pina la sfirsitul blocului respcctiv. Un astfcl de nUJ11epoatc f utilizat in dorncniul lui, inclusiv in blocurile incluse in domeniul rcspectiv, daca el nu este rcdeclarat in aceste blocuri. Exemplu: Fie instructiunilc compuse imbricate de mai jos:

II a > 4900) return False; 1 > 12) return False; II


a%400==0)))

if (z<l II z>tnrz [1] + (1==2 && (a%4==0 && a%lOO return False; return True;

Fie instantierea:
dc data_calend(29,2);

Pentru a valida instantierea

data_calend se va apela Iunctia v_calend astfcl:


== False) (

if(dc: :v_calend(&data_calend) II data calcndaristica cronata

else( II data calcndaristica

int corccta

i;

II inccpc domcniul de lip local a lui i Iinu incepe alt bloc II atribuire
corecta

i=lO;

In acest caz functia v calend a fost apelata folosind operatorul de rczolutie. Se verifica data ~ale~daristiea definita de datele mernbru zi, luna si an a instantierii data calend. Construetorul aeestei clase a initializat obiccrul data calend cu valorile: zi = 29 luna = 2 an = 1995 Datele membru statice(zz,ll,aa) exista in afara instantierilor clasci de. DC$i aceste date sint private, referirea la ele se poate face in functia v_calend care este o functia membru a clasei dc. Totusi, referirea la ele nu se poate face direct,

int j;
j

= i + 2;

Ilcxpresic

111111 cxisra declnratie pentru i corecta dcoarece i se afla in II domcniul lui si Illl a fost rcdeclarat

Jong long

n; i;

II rcdcclnrarea lui i II in accst bloc nu se ponte utiliza variabila

90

91

II i declurata
n

la inccput

de tip inl

Exemplu:
class de tip long i
)

0;

II sc utilizeaza

i de lip long

II in' ;;CCSI PUllet sc tcrmina domcniul lui i decimal . II nu cxista redcclnrarcu lui i II cstc valahila prima decluratic a lui i i= 1 00; II sc ntribuie IOU v.uiabilci i de lip int ) II in aces I punct sc tcrmina dorncniul lui i dcclarut

int i

{ II iustructiunc compusa aflata in domcniul double a; II rcdcclurarca lui a a = :3, 1415; II atribuire corecta c le s s i i a x : I/xcsteoillstunticrcaiuia

numclui a

Un nurne dcclarat in afara ori,I::~lrlliI21()g..:<;aucelara\i<;(~1.c:.n.!1iticl eJi~?~lare d de i'" : /.;; /..p j{'s·{·,~,~'A'cest domcniu inccpc in punctul in ca.re. numclc cstc i Clll.tl (. "'," ..' , .. . 'El ' tc dclEft si-t;;1~'p'i;;a lu sfirsitul fisierului care continc dcfinitia rcspectiva. "_ poa: c .'{ 'J f utili;at' in dorncniul rcspcctiv fara nici 0 rcstrictic daca Ill! cstc rcdcfinit 111
('un (om
j

Cblocurik

inclusc in domcniul sau, .. . -.' . II Daca lin numc carc arc un q.()Il1cniu <jptip fi~icr cste r<:sl~f.I!2.I.~1~~!E:.:.~ID. .. ~ (~. '-.-' .it.i "'1 daca cstc ~_, inclus in domcniul sau, atune: . clpo,\te fI ~ IOSI ,In. ,l(;(':.;.lbloc .•. .~~ __ '_ j]receddt_ 0 _ i~.£PCriitorul d~ r~iol utie.
Exemplu:
int i
.LOa;

Aceasta regula se utilizeaza si in cazul constructiilor struct, union ;;i enum. De fapt, constructiile struct Z;i union se considera ca definesc clase ale caror clemente rncmbru sint toate publice,

(.IC!I!I_e.11i.!!.~{0[jL;;lCiia.A ce~i·staii1seaJnn:1--C[l9].::p?~!~_~f~i?~K!}~;~~Li~;~~~:~li;~;l
functiilor rnemhru ale clasei respective,
.' . .. .'

Un nume al unui clement

membru

a1 unci clase care nu este J:l.ublic arc un


..

- Elcmc;'ltcic "!11embrust;;tic"c"yor ..tl"prefixate dc


opcratorul

numele

clasei

Ul111at

del
-

o clasa

de rezolutie

(vezi paragraful

precedent). care sint instantieri

dcfinitiu lui i BU cstc inclusa in nici un bloc sal! clasa; II arc domcniu de lip fisicr care inccpc in accst punet

ponte contine ca si date mcmbru obiecte cTari1ua1c"c'E1sci i:c~p~~ti~e:"-'- ...--'--'"'-'''

..----.---- .. -- ,-,_ -

ale altei

.....

Exemplu:
class clasa II obiect l este instantierc a clasci clasal II eroare; 0 clasa nu poatc coniine en obiccre Ill11cl1lbn.1 instuntieri ale ei

i.n r. 'j;

/1 i Ill! cstc rcdcclar.u pma in accxt punct j~i+12:3; lise utilizcala i dcfiuit mni sus long j=i--12 j~j+ /1 redcclararc a lui i // inccpc un domcniu de lip local pentr'u .i II xc urilizcaz» i declarat prin long i i II sc utilizcazu i dcclarut prin int

clasa1 obiectl; clasa obiect;

);

referinte
4_.~_ ... ~,." ..

Inschimb,se

spre oblec'tele Cliisclfcspeetivc.----·


<." ., .. '.""',~.";,, ,"',.~,."',"" ... "

P?tdefinidate

mcmbru
~'T"""

ale unei clase care

_ _-_,._ ..

sa

fie pointeri

--- .

sau

.......,=""'," •.,.•..,",. '.,~.~"' ..,"""'" ..

,7>","~•.~.,~,.~_,•.• O'•.'''.,' .

.•L~''><',."''.,,

Exemplu:
II sfirsit fisicr: sc tcrmina
dorncniul

lui i dcclarat

prin int i

class

clasa II pointer spre un obicct de tip clusa II referinta la un obiect de tip clasa

clasa arc 0 dcclaraiic (dcfinitic) care dcfincstc un tip abstract de dale. Numele acestui tip estc considen,lt,.t()t()dat~_C:,a fiind nillne_le..l~l/.e,lql~!:~e.:.. "1 --N~~1:;clc;:lnei clasc arc un domcniu care se stabileste la fcl ca ~l dorncniu oricarei variabile. , ..' . folos Un numc de clasa ponte 11rcdeclarat ca orice numc. In acest caz: put e 111 OOSI numcle respectiv intr-un domeniu inclus in care este rcdefinit folosind
constructia:

clasa *pobiect; clasa& robiect;


);

o astfel

Clasele

pot fi declarate incomplet de declaratic arc formatul:

class nume; Astfcl de dcclaratii


sc pot folosi ~iin cazul constructiilor

struct ~i union.

in locul numclui.
92

93

Exemplu:
c1ass struct union class
a
S

a;
Si

\1;

static. Alocarea pc stiva se face cind controlul programului ajungc III locul in care sin! declarate. Cind controlul prograrnului iese din blond in care sint declaratc , datele l:csl?~ctive sc climina de pe stiva.
j

Durata dinamica

'kpa;
?'PSi

- Este durata datelor alocate in memoria heap. Acestca se aloca ~i se elibereaza la exccutie prin func\ii sau opcratori
corespunzatori, Ea se realizeaza de catre programator. In acest scop, in limbajele C si C++, se pot utiliza functiile

U };

*pu;

malloc sifree.
De obicei, capitoluI20). in limbajul C++· se utilizeaza operatorii

new si delete (vezi

22.4. Vizibilitate
Un nume este vizibil in domeniul sau daca nu este redefinit in blocuri incluse in domeniul respectiv. Un nume redefinit in blocuri din domeniul san, devine temporar ascuns. Un nume cu domeniul de tip fisier poate fi facut vizibil in domeniul in care este redefinit, folosind operatorul de rezolutie iar daca nurnele respectiv este nurnele unci clase, atunci el va fi precedat de cuvintul cheie corespunzator: class, struct sau UlliOI1. Domeniul de vizibilitate al unui nump este acea parte a dorneniului S~IU in care el poate fi utilizat, De obicei, domeniul de vizibilitate al unui nume coincide cu dorncniul sau,

22.6. Alocarea sl dezalocarea obiectelor


obiectelor sc face in functie de durata de viata a obiectelor. de durata statica si locala se aloca automat. Obiectele dinamice se aloca de catre programator. In acest scop, de obicei, se utilizeaza operatorul new. In mod analog, dezalocarea obiectelor sc realizeaza automat daca ele au durata statica sau locala ~! de catre prograrnator daca sint dinarnice, Obicctcle alocate cu ajutorul operatorului new se dezaloca cu ajutorul operatoruluTcieiete. ·AI()carea obiectelor sc mai nurneste ~i crearea saut'oll,\:il:lIii-c,G()bicCtcTor. Dezalocarca obiectelor sc mai nurneste ~i distrugerea obiectelor. Alocarea obiectclor starice care sint globule se realizcaza inaintc de cxecuria tunctiei main a programului. Ele se dezaloca la terrninarea prcgramului ca parte a procedurii de iesire din functia main. Obiectele locale se aloca in mornentul in care domeniul lor devine activ, adica atunci cind controlul programului ajunge la instantierca lor. Ele se dezaloca in momentul in care controlul programului iese din dorncniul lor. Alocarea obiectelor estc 0 operatic mai complcxa dccit alocarea datclor de tip prcdefinit sau definit de urilizator. Alocarea datelor de tip predefinit sau definit de utilizator se po ate face impreuna cu initializarea datclor respective. in cazul obiectelor, initializarea datelor mcmbru este 0 problema rnai cornplexa din cauza protectiei datelor respective. De aceea, se pune problema ca initializarca obiectelor sa fie 0 operatic care se realizcaza la alocarea lor, prin functii mcmbru speciale. Accste functii membru, care rcalizeaza alocarea si initializarea obiecrelor, se considera ca ele construicsc obiectul care se instantiaza. De aceea, ele se numesc constructori. Un constructor este 0 functie membru al unci clase care se apeleaza la fiecare instantiere, EI are acelasi l111l11e a si numele clasei. c Dezalocarca unui obiect este ~i el un proces complex care se realizeaza eu 0 functie mernbru speciala numita destructor. Dcstructorul unci clase se apeleaza Obiectele 95

Alocarea

22.5. Durata de viata a datelor


Durata de existenta a datelor cstc legata de clasa de mernorie a accstora, Prin ell/rata de viata a datelor se intelcge perioada in care elc sint alocate in mernorie, Exista J fcluri de dllrahl: staticd, locald si dinamicd. -v-Durata staticd - lnseamna
ca data respectiva este alocata in mcmorie pe 12£Ti.o.ilclaexecll\iei_progranmlui: de la lansarc ~l pina la terminarea executiei prograrnului.

Datele care au un domeniu de tip fisier sint date ell durata statica. Datele care au un domeniu de tip fisier sint date globule sau locale fisierului daca ele sint declarate Cll ajutorul cuvintului cheie static. In ambele cazuri, ele au o duratd staticd. De asemenea, datele care au un domeniu de tip local au 0 durata statica1ciacasintdec1arate cuajutorul cuvintului cheie static.-··· .. ... --In

static au

concluzie~ datele globale, 0 durata statica,

precum

si celc declarate

cu ajutorul

cuvintului

/ Durata locald

- Este durata datelor automatice. Acestea sint date cu domeniu de tip local si care sint alocate, hl~xecufi~,pc sti~a sau in registri. Ele nu contin, in declaratia lor, cuv-i~tul

94

1a distrugcrca obieetullii. ~~l~ga£()Igaz~UlLltoll1at sau uncori cX1}lici,t de ,~at,ll'~ ~ ]""'11'" t ·llisefacepcntrlladlstlllgcoblcc~_:.\:.":;'~-, ." programalor. Apclul explclt ,1seStlllCOIU 1 , •.... .,' din;micc. Pcntru celelalte obicctc, destruetorul se apclcaza automat la mcctarca c;;~t~'ltci lor: _ la icsircu priu functia exit pentru obiecte]e globalc; ._ la icsirca din domeniul unui obicct de durata locala.

22.7. lnitializare
Datclc pot f initializatc prin dcclaratiilc (defll1iliilc) lor., ", ., in general, datclc de durata statica (giobale sau cme ,w. eld,~d (:~ mcmone ./ tic 'din dcclaratia lor incepe pnn cuvintul cheic stotlc)(vezl cap. 5 ~I 6) static. '" , . .' C III tr'd'd'lted'lc'l neilliri(/Iizate, au valoarca initiala cgala eu zero. e c a te ca cgoru C ( c Ill! si;1t initializatc, au 0 valoarc inilial{ll1cde/iJ1ihi. .. . .' . " ... Datele' de tipuri preciefinite ~i cclc definite de utilizator sc initializeaza . . . 'last prccizate lI1 capitolul 6 SI folosind fonnatclc din limbaju 1 C ,cafe <lU ,( (. • paragraful 10.1. . .t I in limbajul C++ sc pot initializa ;;i datcle de tip unlizator dcfinite cu al~l~ru, Aceasta cste posibil numm pcntru prima componenta a constructici union. rellniulIll. . '. . '1"ltOI' S'C Elcmcntcle unui tablou, unci structuri, unci rl:UI1I111l1 .sau un ~1:,Ull1e" '. itf Jot initializa prin exprcsii constante, a_dic{lexpresu care contm 01?CldnZI c~.,pOl. I cvaluati la compilare, la intilnirea lor. In acesie cxprcsn se poate folosi OPCI,ltOlul sizcof. . ., 1 ti urncrarc se pot Datcle care nu sint tablouri, structun, rcumuru sau de ip en . ,',,',' .. '" initializa prin cxprcsii care nu cste ncccsar sa fie cxprcsu constantc .. l;ll~IC~S.tt,~z: operanzii cxprcsiilor care se utilizcaza la ~nittaltzare, trcbuie sa poata II eva uati in momcntul in care eontrolul programulUl ajunge la ct. Excmplu:
int flint nl

initializate au valoarca initials zero. Datclc membru ale cclorlalte obiecte tobiecte de duratd locale sau dinamicdi care nu sint initializate, au 0 valoarca initiala nedcfinita, Datcle Inembru sraticc se.in.iliaJizcaza inafllra constructorilor.Aceasta, ~eoil1·~~e_~9~!f!.i~el~1_b_I:~ est~·.·~~~-Ol;·<i·' ~ ;1~;~{1~~~ai:e-Dli-=sC=n1UTtjpli~};'-1~_ fiecare instantiere aclas~it:E§l?_(;':<;:ljyc: .. --1111\Elllziirca uner~IStfel de date se rcalizeaza la fel ca 0 data globala obisnuita, adica printr-o definitie a datei respective in care este prezenta si valoarea de initializare, dcfinitic care se scrie in afara corpului oricarei functii.

~~~'i~c~ ..

Exemplu:
class dc int zi,luna,ani static int zZ,ll,aai public:
; ZZ,

Datele rnernbru stat ice intdc::zz I; int de :: II = I; int de :: aa = 1600;

ll, aa se

VOl'

initializa astfel:

Se obscrva prezenta nurnelui clasei si a operatorului de rezolutie pentru a specifica faptul ca ZZ, l! si aa sint date membru ale clasei de. in absenta numclui clasci ~i a opcratorului de rezolutie, datele zz, ll, aa dcvin date globale initializate cu valorile respective. Atribuiri de forma:
de :: zz

1; dc

:: 11 = 1; de

:: a = 1600;

int i 10; .. . .. '1'_' /* Jaramclrul narc prccizata valoarca cind controlul programului aJ.un?c 1.(1 va U,lIe:l e .' ~xprcsici n+IO si anurnc valoarca lui cstc cgala cu a pararnctrului ctccuv de la apclul lui t

dar uurnai daca,sint scrise jn~orpu11lneifun<::tii. melllQt:u (datele respective sintprOi:ejatcfAstfc(de atribuiri, de obicei, nu sint considerate a fi initializari. Ele se reaiizeaza numai daca functia membru care le confine este ape lata. Daca datele mcmbru staticc nu se initializeaza, cle I1U trebuie definite in modul indicat mai SLlS. Elc sint alocatc in mod automat si au valoarea initials egala cu zero.
sint posibile,

*;
int

k-2 inl k~3;


j

II croarc; k

IlU

cstc dcfinit la intilnirca

cxprcsici

k-Z

22.8. Constructor
Datcle de tip prcdefinit sau dcfinit de utilizator se aloca in mod automat, in conformitate ell dcclaratia sau definitia acestora. Odata eu alocarea datelor se pot face si initializari. in cazul obiectelor, accstea sc .aloca fa iJ1stanliereal()L Deasemcnea, obieetele pot fi inijializatc la instan(iere, in acest scop, utilizaiorlJl1;O~ttc dcfini constructori, care sint Iunctii mcmbru de acclasi nume Cll numelc clasci. Se pot

Un loc aparte il ocupa initializarea obiectelor. Asa cum S-(I spus mai sus, obiectclc se ini(ializcaz{( ell ajutorul constmctorilor care se apeleaza 111 mod automat lot instantierea lor. Datclc mcmhru ale obiccrclor stat icc (obicctc de dnrata ..
,1'/11//1'(1)

"".,

.: care nu SlI1t

97

defini mai multi constructori pentru 0 clasa. in accst caz, ei sint functii supraincarcatc si dcci ei difera prin numarul si/sau tipurile paramctrilor.
Valorile de ini!ializarese transfers constructorului si ele joaca acelasi rol ca ~~<l~;:;~triief~ti-\{d~Iaapelurile funqiil(jr o-bi$nuite. Ele formcazilo list[l car~ se include intre paranteze rotunde si sint prezente in declaratia (definitia) obicctelor. in felul acesta, 0 declararie sau definitie de obiect poate avea forrnatul:

Exemplu:
c lass de in t; zi luna, cH1; public: dc () II constructor lara pammetri
I

zi
luna an

1;
1; 1600;

Ilume_clasa Illlme_obiecttlistay;
unde:

lis/a
:1·

- Este fermata virgula,

dintr-o

expresie

sau mai rnulte,

separate

prin nu

Lista, impreuna cu parantezele care 0 includ, sint absente daca obiectul i~~\i(llizeaza sau daca exista un constructor cu toti parametriimpliciti,

dc(int z,int l,int a=1995) 1* constructor cu trei paramctri e1c tip int *1
(

Exemplu:
Se considers clasa complex definita ca mai jos:
class complex ( double real; double imag; public: complex(double

i z; luna 1; an a;

dc(int z,char *denl, I'constructor pcntru initializarc


)

int a); cu dcnumirca

lunii calcndaristicc

*/

x=O,double.y=O)

Exemple
dc dl;

de instantieri

ale clasci de:

1* constructor pcntru numcrc cornplcxe; implicit sc instantiaza numarul complex cu ambclc parti egalc cu zero *1 real = x; imag = y;

Exemple
complex ~.. complex complex complex

de instantieri
z; r (3) i i(O,l); c( 1.5, -1.5);

ale clasei complex:


II II II II II II II II sc instantiaza numarul complex initializat implicit: z = O+O*i sc instantiaza numarul complex r 3+()*i sc instantiaza numarul complex i o-i-: sc instantiaza numarul complex e I,S-I,S*i

II sc apclcaza constructorul tara paramctri II dl: zi=l , luna=l , an=16()O dc cl2 ( 1', , 9 , 19 9~,); II sc apclcaza constructorul eu loti purarnctri de tip int II tl2: zi=15, luna=O, an=1995 dc d3 (15,9); II sc apclcaza acclasi constructor ca la d2 si sc obtinc acclasi rczultat dc d4(15, "septembrie",1997); apclcaza constructorul cu paramcrrul char "dcnl */ *pd = new dc (15,9); . sc apclcaza constructorulca si in" cazul obicctclor el2 si d3' obicctul sc aloca in memoria heap, datclc mcmbru sc inirializcaza en 1,1 obicctclc d2 51 d3; I'd arc ca valoarc adrcsa de inccput a obicctului alocat in memoria heap *1

~(lc_es.t_exemplu s-a definit un constructor c011~trllctol~ se nume~tec()nslructor implicit.

Hira. pararnetri,

Un astfel

de

La initializare, se utilizeaza regulile de la apelurile functiilor supraincarcatc daca exista mai multi constructori. I?ac{~_(;xi~~~.?ingllrC?_I~.!E~c;_t_qt:,_(~t~~ ~!iS~ft?gll I~(leJ'1'1Jlelllrilefunc (iilord in] in!lJaj ul C, ad icapa 1:(l_rl1etri_~feetiy_i(i!1 (;.azulde fatae~presiile princare se face injtiillizarea) seconv_ertesc spre tipurile E~rametrilorf()rl1itlIIe()~~~pIII1Z,\tori aiconst_ruetoflllui. --.- ..------_. __ Aceasta regula se aplica si in cazul clasei complex, de mai sus, care are un singur constructor. Mai jos, dam un exemplu de clasa cu mai multi constructori:

Il~al':uli.n _care exista un constructor implicit nu se mai poare defini, pentru clasa respecnva, un constructor cu totipararnetrii impliciti. Intr-adevar, un astfe! de constructor conduce la ambiguitate la instantierea obicctelor. De exernplu; daca alaturi de constructorul dci) al clasei de, am defini constructorul:
dc(int z=l,int l=l,int a=1600)

atunci instantierea:
de d;

este arnbigua, deoarece se pot apela ambii constructori. Prezenta constructorilor nu estc obligatorie. Se pot

defini

clase

~l fara

98

99

construe tori , ill accst caz, compilatorul Cs+ gcncrcaza in l11odautqll1'~Lull constructor Ella paramctri, adica un constructor implicit. Acosta arc rol 1I11111ai de al~c~rc a obicctclor clasci respective. Constructorii dcfinitide El:ogl"alll~\tor_~illl neccsari numai in cazul in care se dorcste initializarca obiectclor la instanticrea lQ£. in cazul III care 0 clasa arecclpu\in un~ollstruQtQL ~Lnicl _llmlLn~l~stG constructorulimplicit: atunci 11Ll CpOI insiantia obiectcllcinitializ.ate. S Accasta, 'dcoarccc compilatorul nu crecaza constructorul implicit clasclc care au eel putin un constructor. Exemplu:
class complex
doubl e rea 1;

complex
c ornp lox cornpl ox

Z; z 1 (1) ; z2 = 1;

complex

z3(1,2);

O+O*i I+O*iJ' I l(z2='I+O*i • (( z3 I +2*i


cs

(( z
(lzl

In cazul in care dorim sa instantiem obiecte atit initializate, cit si neinitializatc, putcm folosi un constructor implicit vid, carc se va apela la instanticrca obicctelor ncinitializatc. Exemplu:
class de int zi,luna,an;

doub1e .imag; public: cornplex(double


(

public: dc () 1/ constructor implicit vid { I( sc utilizcaza cntru instautierca obicctc1or p ncinitializatc


}

x,double
imag
y;

y)

dc(int z,int l,int a) 1* constructor utilizatcntru initializarca p obicctclor *(


{

real

==

x;

zi = Z; luna
l:

= 1; an = a;

in acest caz, sc pot instantia nurnai obiectc cu ambcle patti initializate:


compLex z(1,2);

Se pot utiliza instantieri de forma:


de

complex

z1;

(/croarc:nu cxistaconstructor implicit

Dcclaratia (definitia) obicctelor pentru care lista de initializarc se rcduce la un singur pararnetru, poate fi scrisa intr-un format care S~l nu difcrc de eel utili:,:,1t la .initializarca variabilclor simple. Astfcl: nunie _clasa Ill/me ~obieci == expresie; realizeaza instantierea obiectului numeobiect al clasei nume clasa, instantiere la care se apeleaza un constructor pentru care primul pararnetru are ca valoare, valoarca lui expresie. 6JJipara!l1etri, sau 111JC)(is!t\lacon~t1"".Ll(;!()rulapelat sat!_~ll}t p"rill11etri impliciti, Exemplu:
class complex double real; double imag; public: complex(double
{

dc d : (( sc apclcaza constructorul mplicit i d l (1, 2 , 1997 ) ~ II sc instantiazabicctul d I initializat o (I astfcl: zi=l,luna=2, an=1997

Parametrii unui constructor potfide crice tip, cu exceptia tipului detinitdc clasa pcntru care estc functie mernbru, Deci, daca clasa este numcle unci clase, atunci nu sc poate defini un constructor de antct:
clasa(clasa p)

In schimb, construetorul unei clase .p()ate a'y'~(1c(1.parall1etl:i l~efel:i_rl\~.Ia,_()i:Ji~~!clelasei!.e.sp~ctive." c Deci: ..... "
clasa(clasa *p)

pointeri

sau

clasa(clasa& x=O,doub1e y=O)

p)

sint antete corecte de constructori. Constructorul:

real

= x; imag

y;

i.

Excrnplc 100

de instanticri:

cOl1struCI(~r c_ol~iere. Constructorul insa trcbuic s'111~1111Plici\i.

este un constrll<::.!()rspeciall;a,r~J:){!1111it~ (;opie.t:£(l..9l!j~<;t~lor. El sc numeste . de copicrc poa,!e <ly~a~L~JLJ:)~rametri care

101

Constructorul jos:
clasa clasa

de copiere

se apelcaza

intr-o instantiere

de felul cclci de mai

col;

linia;

c( ... ); c1 " c;

II instanticrc cu initializarc obisnuita II sc apclcaza constructorul de copicrc; II c I CSIc 0 copic a lui c

Daca programatorulnlldefinc~te un constructor de copiere, atunci compila~£!l:lrgenereaza un constructor de copierc implicit, daca esre 'nevoTc'(le'

eC---

Exemplu:
Mai jos, dcfinim
class

se poate trasa daca se definesc doua virfuri diagonal opllse. De obicci, se considera virful din stinga sus al dreptunghiului si eel din drcapta jos. Un virf al dreptunghiului cste un obiect al clasei Punct. De accca, putem defini clasa Dreptunghi cu ajutorul a doua obiecte ale clasei Punct:
class Dreptunghi Punct st_sus; Punct dr_jos;
};

Un dreptunghi

un constructor

de copiere

pentru numercle

cornplexe.

complex ( doub le real; double imag; public: complex (double


(

x"O,double

y=O)

Constructorul

clasei

Dreptunghi trebuie sa transfere

valori pcntru pararnetrii ca mai jos.

real imag

x; y; c) II constructor de copiere

constructorului clasei Punct. Acest lucru se realizeaza modificind Fie clasa cl dcfinita astfel:

antetul constructorului,

c ornplex(const complex&
(

real imag

c.real; c.imag;

class cI 1 ell c l ; el2 c2; cln en;

);

Exemple
complex complex

de instantieri:
2(1,2); 21 =z; II z = 1+2*i II sc apclcaza constructorul de copicrc II zl = 1+2*i II so apcleaza constructorul de copicrc Ilz2=1+2*i

1.' J,

unde: c! l,el2, .. .cln

. Sint nume de clase, in prealabil


sint toate distincte. Ele, au

definite, care nu neaparat Ticcare, eonstructori pcntru pentru obiectele mcrnbru

initializarca
Constructorul

obiectelor,
de initializare

Datelc rnembru ale unei clase pot f date arbitrare dar nu obiecte ale clasei respective. Il!parti(;ulaT,datele membru pot fi obiecte ale unei alte clase. Un exemplu simplu este eel oferit de primitivele care se utilizeaza la definirea figurilor pe ecranul setat in mod grafic. Consideram clasa Punet care defineste un punct pc ecran. Acesta are 0 pozi tie definita prin coordonatele sale (coloana si linia in care se afiseaza punctul respectiv). Definim clasa Punct ca mai jos:
class Punct int x; int y; II coloana Illinia

c1,c2, ... .cn prin antetul


In acest antet exemplul

cl transfera valorilc S~1U de format:

vor

lipsi obicctele

pentru

care definiria

nu

sc transfera

date

de

initializare.
Reluind constructori:
class Dreptunghi Punct st"sus; Punct dr,.jos; public: Dreplunghi (int dr ,in\: j): dr_j os t dr, j) Iisc instantiaza drcptunuhiu) cu virfurilc: II stinga sus: (0,0) -implici:

de mai sus, completam

clasei Dreptunghi eu doi

public: Punct(int col=O,int linia = 0) II constructor: punctul implicit cstc eel de coordonatc (0,0)

102

103

II
( )

drcnpta jos: (dr,j)

22.9. Destructor
Des trueto rii s j nt~lI1c tii earc ~!..tL~~21siclet:':l:.tL.~_~_~.s~E,~~1_?:~~ SCI~S.n v.~rs i f'lk(~.~.~l_£llctori, Ei au multo caractcristici in e011l1111 cu constructorii, dar intre ei exista ~i diferente. NJll!~e_!e__II!l_l:lj_.de.\:truc I OJ~ CS.t(!,.llU 111e)~gla sc:_i_re cedatqg(;_\ll"\C:_( G rul "-", U 11 p destructor nu are paramctri si cl cste unic pentru 0 clasa. Daca prcgramatorul nu a definit un destructor, atunci compilatorul genereaza un destructor pentru clasa respectiva, Antetul destructorilor nu confine cuvintul void, desi ei nu returneaza valori. De aceea, destructorii au antctul: =nume_ c/asa 0
in interiorul definitiei clasei nume clasa. in afara definitiei clasei, antetul destructorului

Dreptunghi(int st,int sus,int dr,int jos}: sl_sus(st,sus) ,dI .. os(dr,j j ) II sc instantiaza drcptunghiul II siinga SlIS: (st.sus) II drcapia jos: (dr.jos) ell virfurilc:

);

Metoda

de initializare

a obicctelor,

care sint date mcmbru

ale unci clase,

poate f utilizata si pcntru date membru Astfel, un constructor de forma:


complex(double
{

care nu sint obiecte.

x,double

y)

va fi:

real

x; imag

y;

numejclasa :: -numeclasai) Ca si in cazul constructorilor, adresa dcstructorului nu poate fi deterrninata. O~i~£~c..~~.~I~_c::_l.'t.s_~c'~J:~~\J_~lll.gcstgls:_!g~~i/sau cell)utin un constructor nu se P.0_.11!U.i?:~~~'U'.\££!1-P.2!1_e}}t£.<.tlC::.~lllei rCUl~iuni. -, --'. l~aca_la ig.stal}tie!~g~l.Ulll:li_o~i~~t s~<.tllapelatmai l11ulti coustructori, atunci la g~_tE~t_g~I~ea de~l~~!c.t()l:t~~:::.or ~lp.el'!j.!2"grqilleill y~.t:~'i,_ l,:!L . Pe 11 trll_1I11.()Qi£(;tgl()b~l,cl~~tl:l!ct()ru.1s_<::. pe 1(!_<1;;:ac(1.part~_'IPI()(;~gllrii.ex it .de a la terrninarca executiei functiei main, De aceea, unastfel de destructor nu trebuie sa apeleze functia exit deoarece se intra mtr-un ciclu infinit, P~n tf_l!__ll_l__~.2!J.~c::e!Jgc::."lA~,~t!:!:~c::t()l:LIL~.~,,'lpelc::aza d ... ..ci ~1 c()l)tr9_l~llm9graml!lhli ies ~_9~~~.()1!lC::J.1illl.)~!i.(,;.e. .illl:JlClc::tILi.llearc::.~s de~ lar,ii), i~§c::A te . . Obiectele dinarnice nu pot fi distruse automat. Distrltgel'ea se realizeaza de catre programator deoarece numai el stie cind un astfel de obiect nu mai este necesar. , I~estl::.~!:.CJ~~.E()"tc::_.!}_ap~!a..!..deprograrnator atit dircctL .. c;iL.~ijl1qin:~\:Lptjn _ 1 !1__tc::nllc.cii~ll"ClRC::E'!!i.cI~1 te. -'.""" ..--.--.'-~)l:tllll e ......... ._--.,._ Noi utilizarn oper~i·o·rurdetele pentru a distruge ajutorul operatorului new (obiecte dinamice), Exemple: 1, Fie tipul complex definit in exernplele precedcnte.
complex *pz;

poate fi scris si sub forma:


complex (double
{ }

x ,double

y)

real (x) ,imag

(y)

in inchcicrea

accstui

paragraf,

enurneram

caraet~l:i~!i<:ilede.])azA,.'lJe

constructorilor. "'~C'onstnt~torii nu rctumcaza nici 0 valoarc la rcvcnirca din ei. Mai mult dccit alit, antctul lor constituie 0 exceptio, deoarcce nu cste admis cuvintul chcie void, cuvint care trebuie sa fie prezent in antctul functiilor care nu rcturneaza 0 valoare. L i in cazul in care 0 clasa are obiecte membru care au constructori, accstia se apclcaza inainte de a sc apcla constructorul clasci respective, . '.'! Obicctclc clasclor care au eel putin un constructor nu pot f componente ale 1I11ei rcuniuni. Y) Sprc dcoscbire
deterrnina. ~ ) De obicei,

de functiile

obisnuite,

adresa

constructorului

nu se po ate

obiectecreate

dinamic cu

constructorii sint functii mcmbru publico, dar nu se pot apcla explicit la fel ca cclelaltc functii mernbru. . ,. Un constructor poatc fi apelat explicit pcntru situatii de fclul cclui de mat jos: complex z
=

complcx( 1,2);

i-tttL'/j)

-r,

Cov

cL ,

in accst caz a fost apclat constructorul clasci complex pcntru a crca un obicct anonim care cste initializat cu valorilc 1 pcntru partca rcala ~i 2 pentru partca imaginara. Apoi, obiectul respectiv cste copiat in obiectul z.

pz new complex(l,2); II in memoria heap sc construiestc un obiect de lip complex Cll partea rcala egala II ell I si partea imaginara cgala ell 2; pz pointcaza sprc obicctul rcspcctiv

104

105

delete

pz;

II se disuuge

obiectul

crcat mai sus prin new

2.

Sc dcfincste
class

clasa string ca

mai

jos:

II constructor folosit 1<1 inirialivurc c ornpl ex (r.on s t compl ex",); II constructor de copicrc double modul (); double arg () ; double r e t.r e a 1. ( ) ; double re t i.mao() ; void a f .i s c orr.p lcx (); II sfirsit dcfinitic clasa complex II II II II II modulul numarului complex complex

string ( char *siri int Lunq : public: string(char -string() ;

argumcnrul

numarului

*); }; *s ) II definitia construcrorului

rcuuneaza partea rcalu rcturncaza patten imaginara afiscaza numarul complex

s tr ing
(

::

Str

in" (cha r

FI$IERUL BXXII1
BXXIll_H #ifndef #include "BXXIIl.H" #define BXXIIl_H #endif #ifndef __ MA'I'H H #include <mat:h.h> #define MATH_H
lfendif

lung = strlen(s) + 1; sir = new char[lung]; strcpy(sir,s); . string :: +s t r i nq () sir; II dcfinitia dcstructorului

delete

Excmple

de instantieri:
11 );

string sir_de_caractere( este un sir de caractere II se crccaza obiectul sirdccaractcrc in memoria heap si sc initializcnza cu tcxtul : II "Acosta csrc un sir de caractcrc"

#ifndef #define #define #eneli£

PI PI 3.14159265358979 PI

II constructor pcntru initializarca obiccrclor inline complex:: complex(double


(

x,double

y)

del e te s ir~de_carac te re : II sc distrugc obiectul apclindu-sc indirect dcstructorul

Apcluldircct

.aLcl.<;~Jrllc:torul11isGPQatc

JaGt::_J1lJm,lL.(Jacfl_l}_t!lI1<::]C.Jlli_ este

real imag

Xi

y;

EEe_cecla d er;ul~eIe.~I~~<:i.£~re t
string s. s("exemplu");

"este ,llrnl,t1cjG"oper<1!.2Il:ll(~e.l~~?~~!e:
II constructor de copicrc inline complex :: cornpl.ex(canst cornplex& z )
(

II ape I direct al dcstructorului

real

z.real;

imag

z.imagj

Exercitii:
22.1 Sit se defineasca tipul abstract de date complex care sa aiba functii rnembru pcntru modul, argument, pentru accesul la partea rcala si irnaginara a obiectelor de tip complex, pcntru afisarea obicctelor complcxc, prccum ~i constructori pentru initializare si copicre.
inl ine double return complex :: modul () II calculcaza modulul numarului complex sqrt(real*real+imag*imag);

double
(

complex a;

.. a rq () II calculcaza

argumcntul

numarului

complex

FI~IERUL BXXII1.H
class complex ( 1/ date mcmbru protejatc(private) double real; 1/ partea reala double ima,,; II partca imuginarn

double

pub li c:

/1 funcrii

membru

neprotcjrue

complex(double

x=O,double

y=O);

if(real==O && imag==O) return if(imag==O) if(real> 0) return 0.0; else return PI; if(real==O) if (irna" > 0) return PI/2;

0.0;

106

107

(else return

(3*PI)/2;

- sumn numcrclor *1
(

cornplcxc

cititc,

II real I.~0 si illw~ I,",0 a tan (i ma q 1 rea l) ; if ( < 0) II real < () si y 1",0 return (:j,+PI; II real> 0 i. f (imag < 0) II real> () si il1lag < ()
rc t. u rn :~*PI+a;

double double double double do

x' y; sx sy

0; 0;

II real 0 si imag > 0 return a; Ii snr5il arg inli double complex:: retreal() II rcrurncaza patten rcala a nurnarului complex re t.urn real;

printf("partea reala ='); if ( scan f ( "% 1f " , &x) ! = l) break; Iinu mai sint numerc printf('partea imaginara .); if(scanf("%lf",&y) '= l){ Ilcroarc pr.intf ("partea imaqinara eronata\n"); printf("se reia citirea numarului\n"); f flush (stdin); II vidcaza zona tampon de In intrarca standard con tinue; II se reia ciclul de citire II sc insumcaza partca reala si cea imaginara sx += Xi sy += y; a numcrclor complcxc cititc

.i.n l doubl complex: :n?timaq () II rcturncaza purtcn imag.naru a nuruurului complex


ret u rn irnaq;

iI11:1 void c ompl.ex il afiscaza uumurul complex P' i nt f. (


)

i"

('?\q)

'x n"

'tmaq);

c omp lex z (x ,y) ; II sc construicste nurnarul complex avind partilc cititc; II sc apclcaza constructorul care rcalizcaza init ial izarca obicctului II z: z=x+i=y z .a f iscomplex (); II afiseaza numarulcitit double m = z.modu l (); II calculcaza modulullui z double·a=z.arq(); II calculeaza argumenrul IlnuJ11arului complex double 011 sqrt (01) ; II radacina pat rata din modulul z double a1 a/2; II scinlargumcntul numarutui z II rz I = sqrt(z) printf('modulul %q\targurnentul = %g\n',m,a); double preal = ml*cos(al); double pimag = rnl*sin(al); complex rzl = complex (preal,pirnag) ; II rz2 = sqrt(z); complex rz2 = complex (-preal, -pimaq) ; printf('radacina patrata\n'); printf('sqrtzl = .); rzl.afiscomplex(); p rint.f (" sqrtz2 = .); rz2.afiscornplex(); while(1); complex sz = complex(sx,sy); II sz == surna printf('surna nurnerelor cornplexe citite = "); sz .a f iscornplex (); II afiseazu suma nurncrclor complcxecititc a unui

22,2 Sa se scric un program care rcalizeaza urrnatoarcle: • citeste pcrcchi de nurnere care rcprezinta, fiecarc, partca rcala tiv partca imaginara a unui numar complex;
• afiscaza:

.
~l

respcc-

nurnarul complex citit; .. radacina p{ttraEl din ficcare numar complex citit; surna numerclor cornplcxc citite. PROGRAMUL BXXII2

#include <stdio,h> #include <conio.h> ftinclude "BXXII1.CPP·

~a i::!~~tc

pcrcchi de 1l11111erecarc rcprczinta

partca reala si rcspcctiv

cea imaginara

numar complex: al"lscaza: uumnrul complex citit; ,adacina palntla din liu!1\anlll'lll1tj1kx

citit:

22,3 Sit sc cxtinda tipul abstract complex, dcfinit in exercitiul 22,1, asa inc it S,l sc poata rcaliza urmatoarele opcrati: asupra obiectclor complexe: adunarc; 109

108

scadcre; negativare; inmultire; iIIIpa rtire; citirea de la intrarea standard a componentelor unui obiect complex. FI~IERUL BXXII3.H
enum Boolean (false,true]; class complex ( II date mcmbru protcjate (private) double real; double imag; publ .i c : II functii membru neprotejate complex(double x=O,double yccO); II constructor complex (const complex&); /I constructor de copiere double modul ( ); II modulul nurnarului complex double arg ( ); /I argumentul nurnarului complex double retreal (); II returncaza partea rcala double retimag (); II returneuza pm·tea irnaginara void af iscomplex (); II afiseaza numarul complex II functii mcmbru noi

iI i fndo f .__ .STDIO_H 11nclude <stdio.h> II de [ inc _. "'I'DIO_H Uend:i II sc dcfincstc BXXIII_I-! pcntru a nu mai include II BXXIII.H prin includcrca fisicrului BXXIII.CPP jlinclude II dcfinitiilc fisicrul

"BXXII1. CPP" II sc prciau dcfiniriilc funcriilor funcriilor mcrnbru noi

mcmbru

vcchi

Boolean complex :: c i tcomplex () 1* - citcstc componentcle numarului complex; - rcturncaza: falsc la sfirsitul fisicrului; true altfcl.

*1
{ doub1 (,~~r ea 1 i p

double

pirnag; )

Boolean citcomplex(); II citcstc cornponcntclc numarului complex; /I rcrurncaza false la EOF void adcomplex(complex *zl,complex*z2); II calculcaza z = z I+z2 void sccomplex(complex *zl,complex *z2); II calculcaza z = z l·z2 void negcomplex(complex *zl); II calculcaza z = -7. I void mulcomplex(complex *zl,complEcex *z2); II calculcaza z = z I *z2 Boolean divcomplex(cornplex *zl,complex *z2); II calculcaza z z I/z2; rcturncaza false la impartirca ell zero
];

it(pcit_double("Partea reala:",&prea return false; II EOF if (pc t_.double (" Pal·Lei.l imaginara: re t.ur n f al s o : II EOF rea] pr(~al; ima~J pirnag; r o r.ur n true;

==

0) 0)

", ,'<pirnaq)

inlin" void complex II culculcnza z ,~ z l-I-z2


(

.,

adc omp.lex t c cmpl ex

*z1,

complex

'k

real
i.rnaq

z]
21

--> ->

rea 1+
irnag'fz2

>

rca l

i ma q :

Fisierul de mai jos, contine definitiile functiilor membru noi. Definitiile functiilor membru vechi se preiau din fisierul BXXII I.CPP. FI~IERUL BXXII3
#ifndE'f #include #define #endif #define iii f nde f #include #define #endif _BXXII3_H "BXXII3.H" _BXXII3_H _BXXIIl_H _BXl8_CPP "BX18.CPP" BX18 CPP

in I void complex., Ilcalcuicazaz zl-z2


(

sccomplex

(c()Jnp1

* z 1, c()lHpl

real irnag

21 ._> real zl _.> imaq

-> real; 22 -> imagi

.i n li nc vo i.d complex II calculcaza z ,= -v. I real ima9


-z.l -'21 -> ->

..

nE?gcomplex (complex

*z

real ; imag;

110

III

.i n line
re a l imaq Boolean

void

complex

.. mulcomplex(complex

*zl,

complex -> irnag; -> r e a I i

*z2)

II calculcuza z = 7.1*z2 real*z2 z1 z1 -> real*z2 -> real - 21 -> imag + z1 -> imag*z2 -> imag*z2

c.retreal() == 0 && c.retimag() == 0) printf("ecuatie nedeterminata\n"); exi t (0) ; if(a.retreal() == b.retreal() == printf("ecuatia exit(l);

° ° °

&& a.retimag() == 0 && && b.retimag() == 0) ( nu are solutie\n");

complex z = z I Izl z2

.. divcomplex

(complex

*zl,

complex

*z2)

II calculcaza

double d = II divizor nul if (ei 0) rc~turn false; {(cal = (z1 -> real*z2 irnaq (z1 c> imag*z2
ret.urn true;

> real

·z2 -> real

+ z2

-> imag*z2

->

imag;

~> real -> real

z1 .• > imaq*z2 z1 -> real*z2

-> ._>

imag) /d; imag) /d;

if(a.retreal() == && a.retimaq() == 0) { printf ("ecuatie de gradul l\n"); complex X,2; z .divcomplex(&c, &b); II l = c/b x.negcomplex(&z); Ilx-z printf ("x="); x.afiscomplex() ; ex i t (0) ; II obicctele x si z se distrug in accst punct Ilecuatic de gradul 2 compl ox bpi bp.mulcomplex(&b,&b);

22.4 Sa sc scrie un program care citeste numercle cornplcxe afiscaza radacinile ccuatici de gradul 2:

a, b, c, rezolva ~i

a*x*x+b*x+c=O
PROGRAMUL BXXII4
lude <sLcJlib.h> Hitndef STDIO_H iii Jude <stdio.h> ltde inle .~.STDIO_H Herldi # lude "BXXII3.CPP" main () 1* . citcstc:
rczolva

Ilbp=b"b

complex patru(4,0); complex patrua; patrua.mulcomplex(&a,&patru); complex patruac

114*a

• patruac;
.mu Lcomp lex (&patrui!l,&c); 114*a*c

a.b,c ccuatia:

. aflscaza

a*x*x+b*xt·c·'O soluti ilc ccuatici

complex del tap; del tap. sccomplex (&bp, &patruac); double r = deltap.modul(); r = sqrt(r); double argument = deltap.arg(); argument = argument!2; EOF\n";

II b"'b-4*a*c

complex alb, err]

"s·a

tastat ==

complex delta(r*cos(argument),r*sin(argument)). II delta = sqrt(b*b-4*a*c) complex mb; mb ,negcomplex complex doia; do i a .adcomplex complex x; (&mb, &del ta); II rnb = -b II doia = a+a

if(a.citcomplex() printf (er); exi t (1) ; if(b.citcomplex() printf (er); exit(l) ; if(c.citcomplex() p r i nt.f(er) ; ex i t (l) i if (a. r e t rea I () b . r e t.r e a l. ()

false){

(&b);

false) (

(&a, &a);

false) (

x. adcomplex complex xl;

II x = -b+delta

° °

&& a.retimag() && b.retimag()

° °

&& &&

x l .d i vcomplex (&x, &doia); II x I = (-b+della)/(2*a) printf("xl = "); xl.afiscomplex(); II af'iseaza radacina I x

112

113

complex x2; x.sccomplex(limb,&delLa); fix ~-b-ddla x2 .divcomplex (&x,&doia); 1/ x2 (-b-ddta)/(l*a) printf ("x2 '" "); x2. afiscomplex (); II afiseaza radacina xl

sc initializcaza prin constructorul rcspcctiv. In caz de croarc, se afiscaza lin mcsaj corcspunzator cu data calcndaristica minima. Alte functii mcmbru: constructor de copiere; • • • • • • • • •

~isc instanpaZil un ohicct

22.5

Sa se defineasca tipul abstract de pentru implementarea datei ealendaristice. In acest scop se defineste clasa de care are urmatoarele cornponente de tip ill t: zi, luna, an; minzz ; minll, minaa - pentru data calendaristica considcrata ca data valida minima; maxzz, maxll, maxaa pentru data calendaristica considcrata ca data valida maxima; - tnrz - este un tablou ale carui clemente definesc numarul de zile ale lunilor calendaristice (luna februarie se considers ca are 28 de zilc).

retzi: rcturneaza retan: returncaza

ziua din data obiectului anul din data obiectului data minima; data maxima; data minima; data maxima;

curent; curcnt; curent; curent;

retluna: returneaza

luna din data obiectului

afisdata: afiscaza data calcndaristica datamin: returneaza datamax: rctumeaza modifinin: modifica modifmax: modifica citdata: citesre dildata:determina zi_din_an: zilla_si_luna: din an;
obiectului
0

a obiectului

Componentele minzz, minll, minoa, maxzz, maxll, maxaa si tnrz nu sc multiplica la fiecare instantiere a clasei de, ele fiind utilizate in comun de catre functiile membru. De aceea, ele se definesc ca date membru statice. In mod implicit, data calcndaristica minima se considcra 1 ianuarie 1600, iar cea maxima se considera 31 decembrie 4900. Clasa de arc 3 functii pentru verificarea corectitudinii datelor calendaristice. Una este 0 functie mernbru obisnuita care verifica data calendaristica a obiectului curent, iar celelalte doua verifica corectitudinea darelor calendaristice definite de datcle rnembru statice minzz, minll, minoa, maxzz, maxll, ~i niaxaa. Aceste doua functii sint functii mernbru statice, Aceste 3 functii apcleaza () functie membru statica v_calend care valideaza 0 data calendaristica definite prin paramerrii ei. Faptul ca 0 data calendaristica este dintr-un an bisect sau nu, se deterrnina folosind trei functii, una pentru obiectele de tip de ~idoua pentru cele doua date membru statice. Aceste functii foloscsc in cornun 0 functic bisect care stabileste daca data calcndaristica definita de parametri ei este 0 data dintr-un an bisect sau nu. Functia bisect este 0 functie obisnuita. Ea sc defincstc in acclasi fisicr cu functiilc mernbru ale clasei. Clasa are un constructor implicit care se utilizeaza la instanticrea obicctelor fara initializarea datei calendaristice nestatice (zi, luna, ~ian). Amintim ca datele statice se initializeaza independent, in afara constructerilor. Constructorii clasei de VOl' verifica corectitudinea datelor calendaristice

datil calendaristica; curent; curent; an ~i ziua a


diferenta,

adzi: aduna un numar de zile la data obiectului rcturneaza

• • • • •

in zile, dintre doua date calcndaristice;

ziua din an pentru data obiectului

dctcrmina

luna $i ziua din luna din pararnetrii


nurnarul

nr_zile _luna: returncaza curent;

de zile din luna calcndaristica ~i maxima; daca


0

veriJ'_mil1_max: vcrifioa datcle minima I (l00 pentru data minima si 31 dcccmbrie

eronata, se da un mcsaj de eroare ~i se forteaza data implicita:

data estc 1 ianuarie 4900 pentru data maxima.

FI$IERUL BXXII5.H
#ifndef Boolean #define __ Boolean enum Boolean {false,true}; #endif class dc
II date mcmbru protcjatc int zi, luna/ani

in caz de eroare, se afiseaza un mesaj corespunzator si se forteaza datele implicite. Pentru instantierea obiectelor initializate se utilizeaza un constructor cu trei parametri pentru cele 3 date mernbru care llU sint statice (zi, luna ~ian). Constructorul utilizat in acest scop, verifica atit datele statice, cit si cele care
114

statice,

static static static static static static static static

int minzz,minll,minaa; int maxzz,maxll,maxaa; int tnrz[13]; char *tdenluna[13]; char *ermin; char *ermax; char *erdc; void afiser(char 'sir) ;

115

il atiscaza

static
II vcrifica

tcxiul spre care poinrcaza sir voi d vCLif_~min~~_rnax (); darclc minima si maxima; la crourc se cia mcsaj

void de

afisdata *dat:amin ();

();

II afiscuza

data obieetului un pointer

curcnt

II returnenza II returncaza

spre data minima

II si sc forrcaza data implicira

corcspunz.uoarc

de void a obicctului curcnt: void

*datarnax ();

UII

pointer sprc data maxima minima eu

public: Boolean valid_del); 1* vcrifica corcctitudinca darci calendaristicc la croarc rcturncaza false *1

modi fmin ( );

I*schimba data calendarisuca data obiectului curcnt=/ 1* sehimba data calcndaristica data obicctului curcnt *1

modi fmax ();

maxima

cu

static Boolean valid~~de_mlnl); 1* vcrifir a corcctitudinea datci minimc; la croarc rcurrncaza static Boolean valid_dc_maxl); 1* veri fica corcctitudinca darci maximo: la croarc rcturncaza Boolean bisect_de(); 1* rcturncaza: true ~ daca data obiectului false altfe!. *1

false *1

int

ci tdata

I);

1* citcste 0 data calcndaristica; rcturneazn () la sfirsi: de fisier si 1 altfel *1 z); 1* aduna, la data obiectului curent, numarul de zilc dat de paramctrul

false *1

Bo o Le an

adz i (long

z *1

curcnt cstc dintr-un

an bisect;

long difdata(de *d); 1* rcturncaza difcrcnta, in numar de zilc, dintrc data calcndaristica a obicclului curcnt si cca sprc care pointeaza
cha r

d *1

*denluna

I);

static Boolean blseet dc_mini); J* rcturncaza: true - duca data minima cstc dintr-un all bisect; false - alucl *1 stat ic Boolean true
*/

1* returncaza un pointer spre dcnurnirea lunii datci obicctului curcnt *1 1* rcturncaza ziua din an pcntru data obiectului curent *1

int

zi_din._an

I);

bisect_.dc~_max () ; cstc dintr-un an bisect;

/* rcturncaza:

daca data maxima

Boolean ~iua_si_lunalint z,int a); 1* dctcrtniuadata calcndaristica a obicctului curcnt din z - ziua din an si din a ~ anul calcndaristic *!

false - altfcl.

static Boolean v_calend(int z,int l,int a); 1* rcturncaza: true ~ daca data dcfinita de pararnctrii r; I si a cstc valida; false - altfe!. *1 de ( ); II constructor implicit pcntru obiccie ncinirializatc

int

nr_zile_luna clasci de

I);

l . II sfirsit dcfinitia

1* retumeaza numarul de zile din luna calcndaristica a datci obieetului

curcnt

*1

Definitiile functiilor fisier de extensie .Cl'P

membru

si initializarea

datelor statice

se dau intr-un

FI!?IERUL BXXII5
iiifndef ._STDIO_H #include <stdio.h> #define _STDIO_H #endif #ifndef _Boolean enum Boolean (false,true); #define __ Boolean #endif #ifndef DC_H #include "BXXIIS.H" Ildcfinitiaclaseidc iidefine DC_I-!

dc ti n t z,int l,int. a); 1/ constructor pcntru inirializarca de (cons t:. de&); int re t zi () ; i nt;
i.nt.

obicctclor pentru copicrc ziua din data obicctului luna din data obiectului anul din data obicciului curcnt curcnt curcnt

II constructor II rcrumeuza II rcuuneaza II rcturncaza

retl.una retan

(); I) ;

116

117

#endif II initializarc» int int int int int datelor stat icc 1;
1;

false in eaz conirar.

*1

dc::minzz de: :minll

II implicit, data calcndaristica II minima cstc II I ianuaric 1600 II implicit, data calcndaristica II maxima cstc 1131 dcccmbric 4900

de: :minaa de::maxzz dc::maxll int de: :maxaa II initializarca tabloului int de: :tnrz[13] II inirializarca char *de:: char *dc:: char *de::

1600; 31; 12; 4900;


cu numarul

if(a < 1600 I I a > 4900) return false; if (a < de: :minaa II a > de: :maxaa) r e t.ur n false; if (] < 1 II I > 12) return false; if(a==de::minaa && l<de::minll II a==de::maxaa && l>dc::maxll) return false; if(z < 1 I I z > tnrz[1]+(I==2 && biseet(a))) return false; if(a==de: :minaa && l==de: :minl && z < de: :minzz II a==de: :maxaa && l==de: :maxll && z > de: :maxzz) return falsei return true;

zilclor din lunilc ealcndaristiec {O,31,28,31,30,31,30,31,31,30,31,30,31}; inline void de: ra f i s er Ic ha r II afiscaza lex lui sprc care pointcaza sir
(

*sir)

tcxtclor de croarc e r dc "data ealendaristiea eronata\n"; ermin "data minima eronata\n"; ermax "data maxima eronata\n'!;

printf
}

(l!%s\nlO I sir)

II inii ializarca tabloului eu dcnumirile lunilor calcndaristicc char *dc: :tdenluna[13] "luna ilegala", ianuarie" "februarie" , "rnart i e " I'aprilie "rna i ", "iunie
II I I fl I tl l

inl ine Boolean de: : val id_de ( ) 1* - vcrifica corcctitudinca datci calcndaristicc - la eroare rcturncaza false, *1

a obicctului

curcnt;

return v_calend(zi,luna,an);
in1 ine BooLoa n de: : val i.d__ e min () d 1* - vcrifica corcctitudinca datci minimc: - la croarc rcturncazn false, *1 return v_calend(dc: :minzz,dc: :minll,dc: :minaa);

lIiulie

ll

lIaugustn

IIseptemb:r-iell{ octombrie" noiembrie "decembrie"


!l II II

II functic obisnuira

folosita de functiile

mcmbru

inline Boolean de: :valid_de_max() 1* - vcrifica corcctitudinca datci maximo: - la croarc rcturncaza 1:1I5e, *1 r e t ur n v_calend(dc: :maxzz,de: :maxll,de: :maxaa);

inline int biseet(int a) /* returncaza: I daea a dcfincste un an bisect; o altfe\. *1


{

Boolean de: : biseet_dc (I 1* rcturncaza true daca anul calcndaristie if(biseet(an)) else return return false; true;

al obicctului

curcnt cstc bisect "]

return

a%4==O

&&

a%100

II

a%400

0,

/1 functii mcmbru Boo Laari de::v_ealend(int z,int l,int a) z, I si a cstc valida;

Boolean

1* rcturncaza

dc: : bisect_dc rnin () true daca anul minim cstc bisect *1 :minaa)) false; return true;

1* rctumcaza:
true daca data ealendaristica dcfinita de paramctrii

if(biseet(de: else return

118

119

Boolean de: :biseet~de~moxl) /* rcturnc.rza true duca anul maxim cstc bisect *1 i E (bisect (de:: :maxaa)) return Ls o : return t r uo :

an = d.an; f (vali.d_de I) =c= false) afiserlde: :erde); zi:::: dc i i m i nz z ,

luna:::: de: :minll;


an ::::de: :minaa;

void de: :verif min maxi) 1* vcrifica datclc minima si maxima; daca 0 data csrc cronata sc da un mcsaj de crourc si sc fortcaz.. data implicita */ it Idc: :vali(l._dc __ i n t ) m false) ( de: : a f. i s er Ide: : ermin); II sc Iortcnzn data minima
dc: dc: } .rr.inz z 1; 1; .rn in Ll

corcspunzatoarc.

.inI i.ne return

int zi;

de:: retzi

I)

II rcturncaza

ziua obicctului

curcnt

implicita

.i.n Line

int.

de:

: re t Luna I)

1/ rcturncaza

luna obicctului

curcnt

de: : rninaa

1600;

.return

luna;

iElde: :valid_de._maxl) false) ( de: : a ti. sa r I de: : o rrnax l . II sc lortcaza data maxima de: .rna xa z 31; de: : ma xLl. 12; de: :maxaa 4900;

implicita

inline r e t.urn

int an;

dc: :retanl)

II rcturncaza

anul obicctului

curcnt

in1 ine de :ciclint z,int ,int a) 1* constructor pcntru initialivarca obiccrclor; - sc vcrifica data minima, maxima SI cca care sc insiantiaza. . :verifmin.maxI); /1 initializarca zi luna an
if(va
Z

void

de:

: af isclata

I)

II afiscnza data obicctului

curcnt

p r i.n t ftvzi . %d\tluna:


}

'Iod\t.iUl: %d\n",

zi,lu.na,an);

*/

de *de:: da t amin I)

II rcturncaza

lin pointer

sprc data minima :minaa);

obicctului

care sc iustantiaza

de *d_min = new de(de: return d_min;

:minzz,de:

:minll,dc:

1;

de
(

=dc

i : da

tamax I)

II rcturncaza

un pointer

sprc data maxima

a; id ... el)==false)( d fiserlde: :arde); zi = de: :minzz; 1.una de: : mi n 1.1 ; an :;::; e:: rninaa; d

de *d~max = new de(de: return d_rnax;

:maxzz,de:

:maxl1,de:

:maxaa);

void de: de: de: dc:


)

de: :modi fm in I) :minzz zi; :minll luna; :minaa ani :verif~min_.maxl);

II schimba

data calcndaristica

minima

cu data obiccrului

curenl

inl .ir.e de:: de I) de: :verif_

1* constructor

pcntru obicctc

ncinitializatc

*1

min ..rnax t ) :

void de: : de (cons t zi luna de &d) 1* constructor de copicrc *1

de: : modi fmax () II schimba z i: l.una; an;

data calcndaristica

maxima

cu data obiectului

curcnt

d. z i : cc d. luna;

de: : maxzz cle: :maxll


de: : ma x a a

120

121

de: :verif_min_max();
Boolc.a n de: :Zi\.!(,l_,.si
__lllna(i.nt .

z . i.n t

a)

int dc;;citdata() II citcste 0 data calcndaristica; II rcturncaza: II () la sfirsit dc fisicr; II I altfcl.


(

II dctcrrnina data calcudarisuca II z - ziua din an II si din II a anul


(

din:

int i,c; for (; ;) { for (;;)( printf("ziua: "); if «e=seanf ("%d", &i)) break; if(e == EOF) return 0; printf("ziua eronata\n"): fflush (stdin) ;

int b = bisect(a); if (z > 3 65+b) { II ziuu din an eronata printf ("ziua 'I,d rona t a vn". z); e return false:
}

1 && i > 0 && i <= 31)

if (a
(

<

1600

II

a > 4900)

II anul eronat

printf("anul return false;

'~d e rona t vn vi a j

for (;;) ( printf("luna: "); if ( (e=sean f ("%d" r & i) ) break: if(e == EOF) return 0; printf("luna eronata\n"); fflush(stdin) ; luna=i: for (;;) ( printf("anul: "); if(c=seanf("%cl",&i)) break; if(e == EOF) return 0; printf ("anul eronat\n"); fflush(stdin) ;

1 && i > 0 && i <= 12)

int i = 1; dol int j = de; :tnrz[i]+(i==2 if(z <= j) break; z -= j: i++; }while(l) : zi = z; luna i· an a; return valid_de();
}

&& b);

in1ine char 'de: ;clen.luna() II rcturncaza un pointer sprc dcnumirca lunii obicctului
(

curcnt

return 1 && i >= 1600 && i <= 4900)

1una<1

II

1una>12

? de: :tclen1una[0]

cle::tden1una[lunal;

Boolean dc : : adz i (1 o riq z) 1* aduna la data obicctului curcut numarul


{

de zile dat de paramctrul

z *j

a n=i i if(valid_dcl) == true) break; printf("data calenclaristiea: %d /%d/%d\ eronata\n", zi,luna,an):

long totzile = zi_din_an(); totzile += z; l*nulllurultolaldczilccarescconsidcradupa 31 dcccmbric din anul precedent int ziledinan = 365 + biseet(an); if(totzile >= 0) while(totzile >= ziledinan) totzile -= ziledinan;
an++;

celui curcnt *1

1* se socotcsc anii "I

int de: :zi_dIn_anl) II rcturncaza ziua din an pcntru data obicctului


(

curcnt else(

if( an <= 4900)

ziledinan

365+bisect

(an) ;

bisect (an) ; int b int z=zi; for(int i=l;i


Zi

an-- i

< luna;i++)

z +=de: :tnrz[i]+(i==2&&b);

return

ziledinan = 365 +biseet(an): while ( totzile >= ziledinan){ totzile += ziledinan:

l"sesocotescanii*1

122

123

a n-: i [(an >= 1600)


)

ziledinan 1* determinn

65+bisectlan); uumarul de zilcdinanllldctcnninut *1

functii au forma: obiect.nume functiei


SHU

.., )

totzile

+= ziledinan;

ifltotzile 0)( z i = 31 ; luna = 12; an -- ; return valid_del);

pobieet -> nume functiei ... ) unde: pobiect - este un pointer spre tipul implementat nume functie este functie membru.

princlasa

pcntru care

return zi,ua_si_luna(totzil.e,an);
lonq de: :elitd,.ta(dc 'el) 1* rcturncuza di tcrcnla, in nurnar de zilc, dintrc data calcndaristica curcnta si cca sprc care pointcaza d *1 long zidinan1 long z idinan2 long difzi int an1,an2;
z i din_an I); 1" numarul de zile din anul curcnt *1 = d ~ > z i._d in__ I ) ; 1* numarul de zile din anul dcfinit de an pointcrul d *1 zidinan2; zidinanl

Mai sus. s-au apelat functii membru nestatice ale clasei de in eorpul altor functii mcmbru nestaticc ale aceleeasi clase nmi a respecta regula de mai sus. De cxernplu.in eorpul Iunctiei mcmbru citdata se apcleaza functia membru valid_de astfel:
if (valid_de () true) break;

Acosta este coreet deoarece in mod implicit apelul de mai sus este realizat folosind pointerul this:
if(this -> valid_de()

==

true)

break;

22.6

iflan < d > an) ( anI an; d .-> an; an2


o Ls o {

Sit se scrie un program care citeste, de la intrarea standard, 0 succesiune de date calendaristice si afiseaza fiecare data calendaristica impreuna cu cca a zilei urmatoare,

PROGRAMUL

BXXII6

ani an2

.>

ani

an :

long difzian = 0; whilelanl < an2){ int b bisect(anl); difzian += 365+b;


anl++';

#Hndef STqIO_H #inelude <stdio.h> #define STDIO_H #endif #ifndef __ CONIO_H #include <conio.h> #define __ CONIO_H #endif #inelude "BXXIIS.CPP" -difziani
ma i n t ) /* citcstc () succcsiunc de date calcndaristicc imprcuna ell data zilci urmatoarc *1

if(an < d > an) difzian return difz + difzian;

si afiscaza datclc cititc

Observatii: 1. Funetiilc membru stance, de obicei, se apcleaza calificind numele lor cu numele clasci urmat de operatorul de rezolutie. Mai sus a fost apelata functia membru statica v ealend fara a respccta acest lucru. Accasta este posibil daca nu exista defulita in acelasi program inca 0 alta functie cu acelasi nume si lista a parametrilor forma Ii . .. Pcntru a cvi la astfel de situatii se recornanda sft se respccte regula cu pnvire la calificarca numelor functiilor membru statice prin numele clasci urrnat de opcratorul de rczolutie. .. .... Functiilc rncmbru care nu sint staticc se apclcaza 11111l1al 111 lcgatura cu un obicct al clasci pcntru eare clc sin! functii mcmbru. Apclurilc unci astfcl de

for (;;) ( dc data_citita; if(data_citita.citdata() == 0) break; Ils-aintilnitEOF data_ci ti ta. afisdata I); II afiseaza data citita dc data_urm = data_citita; Ilcopiere da ta_urm. adz i (lL); II determina data zilei urruatoarc data_urm. af isda t a (); II nfiseaza data zilei urmatoare
} }

22.7

Sfl se scrie un program

2.

care realizeaza urrnatoarelc: citeste date calendaristice care sint situate intrc doua date limita; afiscaza fiecare data citita impreuna cu diferen;a, in numar de zile, dinrre 125

124

data citita si datele limits. Cele doua date limita se definesc prin argumenre

programului.

Data minima este prima datil calendaristica

in linia de cornanda din linia de cornanda,

PROGRAMUL BXXII7
STDIO_H II i f ride f #include <stdio.h> #define _STDIO_H #endif STDLIB H #ifnd"f #include <stdlib.h> #deEine STDLIB_l! #endif CONIO __ H #ifndef #include <conio.h> #define CONIO_H #endif #inclLde "bxxii5.cpp"
}

/1 citirca datclor calcndaristicc for (;;){ dc data __ crt; if(clata_crt.citdata() == 0) break; Ils-ainlilnitEOP data_crt. afisdata (); 1/ ufiseaza data citirn long di f i ,difs; d if i e Li.m.i n f .difdata (&data __ crt); difs = limsup.difdata(&data_crt); printf("diferenta in numar de zile %ld\n",difi,difs); dc "pinf; pinf = pinf -> datamin(); dc "psup ; psup = psup -> datamax(); printf("limita inferioara\n"); pinf -> afisdata(); printf("limita superioara\n"); psup -> afisdata(); delete pinf; delete psup;
}

main(int ,char *argv[]) 1* - citcstc date calcndaristicc situate intrc doua dale limita; - afiscaza datcle citite irnprcuna eu difcrcnta, in numar de zilc, dintre datcle lirnita si data eitita *1 if (argc! 7) { printf("numar exit(l); int tabarg[6]; for(int i=1;i < 7;i++) { char *p = argv[i]; for(int j=O;"p;j++,p++) if (*p < '0' II *p > '9') { printf ("argument eronat: %c\ t%d\n", "p, *p) ; exi t (1) ;
)

22.8

Sa se defineasca tipul abstract punct care sa se utilizeze


punctelor din plan prin coordonate rectangulare.

la instantierea

FI$IERUL BXXII8.H
class punct double x; double y; public: punctldouble abs=O,double ord=Oi; punct(const punct&); in t c .i tpunc t. ( ); 1* citcstc coordonatclc punctului: rcturncaza: o la EOF; *1 I altfcl. void a f ispunct (); 1* afiscaza coordoruuele punctului */ void xtrans (double dx); 1* rranslatic pe directia abscisei void ytrans (double dy); l" rranslatie pe directiaordonatei double .retx(); II retumeaza abscisa double rety (); /1 returncuza ordonara

argumente

%d eronat\n",arg~);

*1
"I

if(j>4){ printf("argument exi t (1) ; tabarg [i-1]

eronat:

%s\n",argv[i]);

);

= a to i (argv [i] l : II conversia argumentului

Functiile

mernbru

se definesc

separat intr-un

fisier dc tip CPP.

dc liminf(tabarg[O],tabarg[l] ,tabarg[2]); dc limsup(tabarg[3],tabarg[4],tabarg[5]); liminf.afisdata(); limsup.afisdata() ; liminf.modifmin(); 1imsup. modi fmax (); // afiseaza lirnita inferioara // afiseaza lirnita superioara // defineste data statica minima // defineste data starica superioara

FI$IERUL BXXII8
PUNCT_H #ifndef ltinclude "BXXII8.H" PUNCT_H #define 1t end i f inline punct::punct(double abs,double ord) /* - constructor pcniru instanticrca obicctclor de lip punet;

126

127

- implicit sc instant iaza originc«

axclor.

*/

in1 ine doub Lo pune return x;

:: retx () /f rcturncaza abscisa

ails; V

ord :

inline punet: :punct(eonst II constructor de copicrc


(

punet&

p)

inline

elouble punet: :r e t.y ()

/1 rcturncaza

ordoruua

ret.urn y; p.x;

·v; 22.9 Sa se scrie un program care gcnercaza obiccte de tip punct ale carer coordonate se genercaza aleator. Programul afiseaza punctcle care apartin ecranului, iar in final se indica: numarul 111 al punctelor afisate; numarul n al punctelor generate; raportul m/n. PROGRAMUL
Ii ifndef #include !lde! ine #endif #ifndef #include #define #endif iii fnc1"f: #include #define Hendif Hinclude

int punct: :citpunct{) /* - cucstc coordonatcle punctului: rcturncaza: o -Ia EOI'; I . altfe!' */
.in

t. c::

BXXlI9
STDIO STDIO_H I!

for (;;) (

<stdio.h>

if(e==EOF) i nt.f ("nu

return
s-a

0;
numa r x nv)
i

t.a s t a t. un

if Lu s h t s t.d i n ) ;

CONIO I! <eonio.h> CONIO_I!


STDL.[13 H

for (;;)( p r i n tf tvordone t.a »") ; if((cc:se;lrl1(" "",<V)) 1) return i ((c.=· .•EUF) return 0; inr. ( " s-a t.a s t.a t. un nurnar\n") f lush(st.din);
) }

1.; ;

<stdlib.h> STDLID H "BXXIIB.CPP"

inline void punet: :afispunet() /1 afiscaza coordouatc!c punctului


(

printf{"

tv=%g\n", x, V) ;

ma i n l ) 1* . gcncrcaza puncrc cu coordonatc alcatoarc; · afiscaza punctclc care apart in ccranului (80 coloane · afiscazn numarul !11 al punctclor afisatc: · afiscaza nnmarul n al tuturor punctclor generate: · raporlul min. *1 int rn~O,n=O; for (; ;) ( double xaleat = ranc1()%lOO; double yaleat = rand()%lOO; punet pet(xaleat,yaleat);
n++;

a 25 linii):

in1ino voiel punet: :xtrans(douille elx) 1/ translatic in dircctia axei x


(

+= elx;

inline void punet: :ytrans(elouble ely) // translatie in dircctia axci y


(

yl

dV;

if(xaleat > 0 && xaleat valeat> 0 &.& yaleat m++; pct.afispuDct(} ; if (rn't22 OJ{

<= 80 &&
<= 25){

Ilafiscalapunctul

128

129

printf("Actionati

tasla

pentru

a continua\n");

cxtensic Cl'P, FI$IERUL BXXII10


#ifndef VECTOR H #include "BXXII10.H" #define _VECTOR_H #endif iii fndef _MA1'H ... H #include <math.h> #define MATH H #endif #ifndef PI #define PI 3.141592 #define PI #endif

printi(I'Actionati
if{getchl)
0"

zero pentru a termina\n");

'0') break;

pr ntfl"numarul punctelor afisate = %d\n",m); pr ntf("numarul punctelor generate = %d\n",n); pr ntf("ra.portul min = %9\n", (double) min);
}

22.10

Sa se defineasca

tipul abstract vector. de doua puncte. Unul este originca vectorului, iar

Un vector estc definit celalalt este virful lui, FI~IERUL BXXII10.H


#ifndef _PUNCT_H #include "BXXII8.CPp" #define PUNCT H #endif class

58979

inline vector: :vectorldouble xv, double II originca arc eoordonatclc egale eu zero (valori implicitc)
( )

yv) :virf(xv,yv)

inline

vector: :vector(double pcntru initializarca originii

vector punct origine; punct virf; pub Li c : ! constructor: I vectorldouble xo,double vector (double xV,double vector(const vector&); double modul (); IllllOdulul double arg I ); II argumentul

II constructor
{ }

xO,double yo,double xv,double origine(xo,yo) ,virf(xv,yv) si virfului unui vector

yv):

yo,double yv); vectorului vectorului

xV,doubl", yv);

vector: :vector(const II constructor de copicrc


(
)

vector&

vI: origine(v.originel,virflv.virf)

(unghiul

Iacut cu axa Ox)

double
(

vector: :modul () a = virf.retx() b = virf.rety() sqrLla*a+b*b);

II rcturncaza

modulul

unui vector

void x_trans(double dx); II trauslatic in dircctia axci Ox void y .. _trans (double dy); II rranslatic ill dircctia axci Oy

double double return

origine.retx() ; origine.retyll;

double punct punct retorig(); retvirfl); II returneaza II rcturncaza onginea vectorului virful vcciorului
(

vector:: arg ()

II rcturncaza

argumcntul

unui vector

double prodscalarlvector ·v); II rcturncaza produsul scalar dintrc vcciorul curcnt si eel sprc care pointcaza
};

Observatie: Modulul si argumcntul vectorilor argumentul nurnerelor complexe. donarele extrernitatilor vcctorului. Functiile 130
mernbru ale clasci

In acest caz se face diferenta dintre coorin fisierul

se calculeaza

asemanator

cu modulul

si

double a = virf.retxl) origine.retxl); double b = virf.retyl) origine.rety(); if(a 0 &&b 0) return 0.0; if(b == 0) ifla> 0) return 0.0; else return PI; if(a == 0) if(b> 0) return PI/2; else return(3*PI)/2;

==

==

vector se dcfincsc

de mal .lOS, de

II a 1= 0 si b 1= 0 double c = atan(b/a); i£(a < 0) return PI+c;

Ila<Osib'=()

131

if t h

<

0) ()

return

2*PI+e;

Ila>()sib<O

main ()

i* _ citcstc coordonatclc
" () si b
re t u r n

c:
*1

a doi vcctori; - calculcaza si ufiscaza: _ modulul si argurncntul ficcarui vector: , produsul scalar al eclor doi vccrori.

in l. ine void

vee t.o r : : x "trans (doub Lo ;

dx ) litransla(i(:

in dircctia axei Ox puncr:.ovl; punct vvl; punet ov2; punet vv2; Iloriginc II vir!" Iloriginc II virf

origj_llc.xtrans(dx) virf.xtrans(dx) ;

. ·1' In ..... void vector: :y._lrans(eloubl,cely) II(ranslalieindircctiaaxeiOy lne

origine.ytrans(ely); virf.ytrans(dy) ;
)

II citcstc primul vector ovl.citpunet.() ; vvl.citpunet() ; II citcstc al doilca vector ov2.eitpunet() ; vv2.citpunct() ; II construicstc vcctorii vector vl(ovl.retx() vector v2(ov2.retx()

in Li no punc t. vector:: return oriqine;

re t.o r i o () II rcturncaza

originca

vcctorului

i n Lino punct return virf;

vec tor: :r e t v irf () 1/ rcturncaza virful vcctorului

,ovl.rety() ,vvl.retx() ,vv1.rety()); ,ov2.rety() ,vv2.retx() ,vv2.ret.y());

doub le VE'C : :prodscalar (vector *v) ;* rctumcaza produsul scalar diutrc vccrorul curcnl si eel sprc care poinicaza double double double doub lo return ax v
> v i rI
v i

v "'I

II afiscaza rnodulul si argumcntul lui v I si v2 p r in t f ("Vec.torul v I \n") ; printf("modul %g\t argument printf ("Vecto~ul v2\n"); printf ("modul' = %g\ t argument,

%g\n",vl.modul() %g\n",v2.modul()

,vl.arg()); , .arg() );

re t x t ) - v -> or i qi.ne r e t x t l : t:'ij.F V > virf.rety() - v -> origine.rety(); bx vir f. r e t x () o r i.o ino .r e t.x (); by virf. ro ty () o rioino . r e t y (); ax*~)x~ay*by;

1/ afiscaza produsul scalar printf(" (vl,v2) = %g\n",vl.prodscalar(&v2)


}

I;

22.12

Sfl sc defineasca tipul abstract sir pcntru instanticrea sirurilor de caractcre. Acest tip este definit in cdc mai multe lucrari relative la limbajul C++.

22.11

Sit se scric lin program care citcstc coordonatelc a doi vcctori din plan si afiscaza mcdulul ~i argumcntul ficcurui vector, prccurn )i produsul lor scalar.

PROGRAMUL BXXII11
Hifndef s'rDIO ._H

Interesul manifestat pentru acest tip rezulta din faptul ca sirurile de caractere sint urilizatc frecvent in aproape to ate prograrnele. Mai jos, prezcntam 0 implcmcntarc a tipului sir analoga Cll cea indicata in lucrarea [7]. Ca date mcmbru alcgem un pointer spre zona de meruorie in care se pastrcaza caractercle sirului ~i lungimea accstuia in numar de caractere mini caracterul eu/ de la sfirsitul sirului), FI~IERUL BXXII12.H
cla;;s sir { char *psir; int lung; pub1ic: sir (char's);

Ilinclude <sl:dio.h>
IIdefine SJ DJO !I liendif #ifndef STDLJB H #inelude <stdlih.h> STDLIB_H ifdefine ilendif nine ude "SXXrTIO.CPP"

1* constructor pentru initializareu obicctului ell pointcrul de caructcrc: accsta sc pastrcaza in memoria heap *1

sprc sirul

132

133

sir (int nrcar=70); sir(const sir&); s ir () ; int; r o t l.unq () ; void afsir (); int citsir();
=

II II II II II

1* constructor care rczcrva zonade mcmoric in memoria heap si pastrcaza in ea sirul vid *1 constructor de copiere destructor returncaza lungimea sirului afiseaza sind de caractere citeste un si r de caractcre

sir: ",ir(const
(

s i rs. s )

Ilcollstruelordccopicre II lungimca sirulu: II rczerva zona II copiaza sirul

lung" s.lung; psir= new char[lung+l]: strcpy(psir,s.psir) ;

Boolean atribsir(sir *s); 1* - transfcra sirul sprc care pointcaza s in zona rczcrvata pentru simi obicctului curcnt; .. daca nu cxista zona sufieienta, sc trunchcaza sirul sprc care pointeaza s si sc returncaza valoarca false; - altfel sc rctumcaza true. *1

i n I i nc sir: :-sir() 1* destructor: clibcrcaza zona din memoria


(

heap ocupata

de sir *1

delete
)

psir;

i.

inline int sir: :retlung() II rcturncaza lungimcu sirului: numarul


(

caractcrclor

srrului

far.. caracicrul

nul

Mai jos, se definesc functiile mernbru FI:?IERUL BXXII12


lIifndef Boolean #define __ Boolean enum Boolean {false,true}; #endif #ifndef STDIO_H #include <stdio.h> .define STDIO_H #endif STRING_H #ifndef #include <string.h> #define STRING H #endif SIR_H #ifndef #include "BXXIIl2.H" #define SIR_H #endif

ale clasei sir.

return

lung;

inline void sir: :afsir() Ii afiscaza sind sprc care pointcaza psir
(

printf (psir) ; p ri ntt tvvn")


}

int sir: :citsir() 1* - circstc un sir de la intrarca standard si-l pnstrcaza in zona heap rczcrvara - rctumcaza: () - la sfirsii de fisicr -I - la trunchicrca sirului citit - altfcJ. *1 char temp(255J; II s-a intilnit sfirsitul

pcntru obicctul

curcnt:

sir: :sir(char *s) 1* constructor utilizat la initializarca obicctului cu pointcrul in memoria heap a sirului sprc care pointcaza s *1

spre copia

lung = strlen(s); Illungimeasirului psir = new char [lung+ 1 J; II rezervaona in memoria z s trcpy (psir, s); II rransfera sind in memoria heap
}

if(gets(temp) 0) return 0; strncpy(psir, temp, lung) ; *(psir+lung)='\O'; if(strlen(temp) > lung) return else return 1;

de fisier

-1;

II trunchiere

heap Boolean sir: :atribsir{sir *5) 1* - transfers sirul sprc care poinrcaza s in zona rezcrvata pcntru sirul obicctului curcnt: - daca nu cxista zona suficicnta, sc trunchcaza simi sprc care pointcaza s si sc rctUrI1CaZ3 valoarca false; altfcl sc rcrurncaza true */ strncpy(psir,s .> psir,lung); if(strlen(s -> psir) > lung) return t r ue :

sir: :sir(int dim) 1* - constructor care rezcrva zona pcntru siruri de dimcnsiunca • pastrcaza sirul vid in zona rcspectiva. *1 lung = dim; psir new char[lung+1J; *psir'" '\0';

dim;

II deterrnina lungimea II rczerva zona II pustreaza sirul vid

return

false;

22.13 Sa sc scric un program care rcalizcaza

unnatourclc

opcratii asupra obicctclor 135

134

de tip sir:
initinlizarc:

22.10. Functie prieten (Friend function)


La inccputul capitolului, s-a afirmat ca 0 proprietatc de baza a tipurilor abstracrc este protectia date lor mernbru ale tipului respectiv. Elemcntele protejate constituie asa numita implementare a tipului abstract. Tipurile abstracte sc dcfinesc cu ajutorul clasclor. Sc obisnuieste S,\ se spuua ca datcle protejate ale unui tip abstract sint illC~Ip_~1I1ate in clasa care defincste tipul respectiv. Protectia datelor se rcalizeaza prin aceca ca la ell' au acces numai functiile mernbru ale tipului (clasci). De asernenea, d-,leaot\1l1t::tieln~In1:lru .este protejata, atuncic_aJ)()atc:fi apelat,j r)11mAinri11il}!t:!.!:nlediuLt,J~leifuncJiif!lel11bru a tipului

citirc de sirur: de caractcrc de la intrarea standard; _ copicrc de obicctc de tip sir; atribuiri de obiectc de tip sir; _ afisar: de ;;i ruri de caractcrc din compunerca obicctclor PROGRAMUL BXXII13
S'TDIO_H <::::tcli.o, h> #endii

de lip sir.

#i
#include #deE #endi f Dine main ()
instnnticri \r

(<:I'!.s_c;i1_
<stdlib.h> STDLIB H "BXXI
1* opcratii

12.CPP" cu obicctc de lip sir de lip sir *1

de obicctc

i:

C. -I- este un C mai bun"): ("Lin~hljul C •• suporta stilul de programare:\n\ ill abstractizarea datelor;\n\ orientata spre obiecte"); II instanticrc fam initializarc: sirl coniine sintl viti ir ic3 i s i. r 1: II insrunticre foloxind constructorul de copicre ir ;:,ir4 1 ( "L,irnbajul. mai sus

Aces! mod de lucru, desi asigura 0 protectie buna a clemente lor membru protejate ale clasei (clemente protejate prin private sau protected), uneori este considerat prca rigid. Astfcl, desi exista functii descrise in C care pot fi utilizate pentru a prelucra instantieri ale unci clase, ele nu se pot utiliza simplu decarece nu sint functii mernbru ale clasei respective si deci nu au acces la datele mernbru. Mai mult decit atit, 0 functie membru se apeleaza totdeauna in dependents cu un obiect care cstc numit obiectul curent al apelului. In acest fel, 0 functie mernbru se apeleaza prin una din urrnatoarclc formate:
/11//1/e _object.lll/me _filllcfie _111 bru (...) em

sau pointer
fiume _ clasa ->

nume _/illlctie

~lIlell7br1/()

If afisurca obicctclor instantiate print (",;ir vn"l :


() ;

,(if.

prinLf_{"s

sic3 .afsir (); print I: (" si 1:4 \n") sirll.aLsic ();

II citiri de siruri de In intrarca standard whilc(sir3.cit:sir()) Ilcitircasinnilor sir3.afsir(); Ilafisareasirurilorcilil.e II atribuiri de siruri if(sirJ.atribsir(&sirl) printE("trunchicre sir3. a t s i r () ; if(sir3.atribsir(&sir2) print ("trunchierc sir] .alsir ();

In cazul functiilor obisnuite nu se admit astfel de apeluri, toate datele prelucrate de functie sc transfera prin parametri sau sint globale. De aceea, 0 functie obisnuita poate fi utilizata pentru a prelucra obiectcle unei clase daca ca sc modifica in asa fel ca S,1 devina functie mernbru. S-a facut un compromis pentru a admire accesul la clementele protejare si pentru anumite functii care l1U sint mcmbru. Aceste functii au fost numite(ill7c{ii j)l:ie.tell pentru clasa respcctiva. ~_~_!!:~~~lic_;,a ..ficjJI~e~izate ca atare in dC-iToj!la clasci. in acest scop, P_~~()loti12!.lriI(:J9l:.sil1!_P._!·~~~1_l_!~ ..i~1_d~fi.l~E~.~lasei si sin! precedate de cuvintul cl2eie L':~~nd_: Exemplu: Fie tipul definit de utilizator:
struct complex ( double real; double imag;
)

== false) Ia atribuire\n"); =~ fa.lse) la atribuire\n");

Functia tnodul, pentru calculul modulului definita, ca mai jos, ca 0 functie obisnuita:

unci date de tip complex poate fi

136

137

double modul(complex *zl 1* rcrumcuza modnlul numarului complex


(

sprc care pointcaza

r. *1
->

complex, ca mai .iOS:


class imagl; complex { double real; double imag; public: complex(double
(

return
)

sqrt(z

-> real*z

-> real

+z -> imag*z

Daca sc considera
compiex z] double d;

declaratiile:

x=O,doublo irnag ::: y;

y=OI

{l,ll;

rea 1 ~ x; friend
};

atunci instructiunca
d

de atribuire:

double

modul(complex

*z);

modul (&z11;

atribuie lui d modulul numarului complex z l = I +i. Acclasi lucru se poate rcaliza implernentind tipul abstract exercitiul 22.1.:
class complex double> real; double imag; public: complex(double
{

complex ca in

Functia modul, prieten a clasei complex, are aceeasi definitic ca $i functia modul dcfinita pentru tipul complex introdus prin constructia struct. De asernenea.ca sc apelcaza ca orice functie obisnuita:
In excrnplul
complex

de fata, daca se considcra


sc apclcaza

instanticrca:

z(l,ll;

x=O,double .i.rna q ::: Yi

y=O)

atuncijilllctiaprieten
d = modul (&.zl

in mod obisnuit,

adica prin:

real:::::
doub
(

x;

le modul (1 return sqrt(real*real+imag*imag);

Spre dcosebirc de functiile membru, il1,cazul functiilor pricten nu mai este definit pointerulimplicitj/uv. Acest lucru conduce la faptul ca 0 functic prietcn

are un pararnetru
Qfunqie

cxemplul
};

in plus fa(,\ de 0 functic mernbru care arc acclasi cfcct. fi 0 funqie obi5nuit!t (ca in cazul functici moe/III din de mai sus) sau 0 mcmbru a unci altc clasc.
prietcnpoate

Declaratia
complex

pcntru zf se serie:
21(1,1);

Exernplu:
class clasa1
t

iar instructiunea
d

de atribuire devine: ca se apeleaza pentru implicit this ~i acesta

tip t unc
);

i.o _ ornbru (... 1; _m

z1 .moc1u1 ();

In acest caz, functia tnodul nu are parametru deoarece obiectul zl . Tn corpul funcrici modul cste definit pointerul are ca valoare chiar adresa lui z 1.

class

clasa2

friend
};

tip clasa1: :functie __ embru (... ) ; m

Expresia:
real*real+imag*imag

din corpul funcriei mcmbru modul, trebuie considcrata forma:


this
->

ca si cind ar fi scrisa sub


->

real*this

->

real+this

-> imag*this

imag

FU!1Clia functie _membru cste 0 functie mernbru a clasci clasa f. Ea este 0 funcrie prictcn a clasei clasa2. In cazul in care se clOIT~tC ca toate functiilc membru ale clasci clasa 1 sa fie functii prieten ale c1aseiCtasa2, se poate proceda ca rnai jos, in Ioc de a indica individual ficcare functic din clasa clasa l en este functic prictcn:
class class clasal; II dcfinitia clasa2 ( prcscurtata de clasa

Functia tuodul, definita pentru tipul utilizator complex poatc mlocui functia membru modul a c1aseicomplex daca ca sc dcclara Cit functic pricten a clase! 138

139

f r icnd );

clc1s,al;

22.15

Sa se modifice definitia clasei complex din fisierul BXX1I3.H functia cputere ca functie prieten.

inserind

y
-il.

in aces! caz, sc spunc ca clasa I cstc 0 clasa prictcn a clas(;i_c/asa2. Propt'ietatca de clasa prietcni[lL0cstc tl:<lnzitiv<l. Astfel, daca clasa l este 0 clasa prieten pentru clasa? si clasa l estc 0 clasa prieten pcntru clasai, aceasta nu implica faptul en clasa 1 cste clasa prictcn pcntru clasas. Moditicatmi~ dCPl:otcc\ic nu au I:icio int1uen\<l asupra unci funC\iiplj~te~1~ 12cac~ea, .speciticarea faptului C[1 o functie cstc pncten pcntru 0 clasa, poate II scrisa ill oricepunct din interiorul definitiei clasci respective. .._-._._. -F_1J'11clia pri~tell.llll-"st~_pr()t~jilt~ si deci ponte f utilizata f[lra nici 0 restrictie ca orice functic obisnuita. J<
Exercitii:

FI!?IERUL BXXII15.H
enum class Boolean {false,true};

22.14

Sa se scric pozitiva.

functic care ridica un numar complex intrcaga

la

puiere intreaga

Un numar complex se ponte ridica la o putcrc formula lui MUI\/'c. Accasta sc cxprima prin rclaiia: (r*(cos(a)+ i * si n(a)))* *11=r**n *( cos(n *a )+i *sin(n unde:
I'

poziti vii folosind

eomplex ( II date mcmbru protcjatc (private) double real; double irnag; publ ic: /1 functii mcmbru ncprotcjatc complex(double x = O,double y 0); cornplex(const cornplex&); double rnodul(); double arg(); double retreal(); double retirnag(); void afiscornplex(); Boolean citcornplex(); void adcompl.ex(cornplex *zl,cornpl.ex *z2); void sccornplex(complex *zl,cornplex *z2); void negcomplex(cornplex *z1); void rnulcornplex(cornplex *z1,cornplex *z2); Boolean divcomplex(cornplex *zl,complex *z2);

* a»)
} ,.

- Estc modulul Tipul coinpl,» sc implcmcuteaza

numarului ncestuia.

complex

II functic pricicn friend void cputere(cornplex& II calculcaza z**n, pcntru n natural

z,int

n);

- Estc argumentul

fclosind eli/sa dcfinita in cxcrci\iul22.3.

22.16

S1\ sc scrie un program care ridica numarul complex Numarul » cste un intreg citit de la intrarea standard. BXXII16

l+i la puterea

11.

FUNCTIA BXXII14
void {complex& lint n} /* ridica In putcrcn n nurnaml complex la care z csrc rcfcrin{a
(

PROGRAMUL
*/

doub ) E.'

doubl
r

a,.

. se calculcaza modulul numarului complex la care z cstc rcfcrinta: - sc apclcaza tuncria mcrnbru modul a clasci complex . sc calculcuzn argumcniut nurnarului complex In care 1. c'stc' rcferinta: a .ar" () ; - sc apclcaza Iunctia mcmbru arg a clasci complex *1 d()uL~1(0 rlan pow t r . (double)n); doub l e na ::;:n*a; z.real r"lan*cos(na); ...... in:E!q ::::: rlan*sin(na);
,_rnociu 1 ( ) i ,

hfndef PI #define PI 3.141592653589793238 #define PI #endif hfndef _MATH H #include <rnath.h> #define _MATH H ·#endif STDIO_H #ifndef .include <stdio.h> #define STDIO_H #endif
II pcntru

Observatie: Funciia ('/)11/1'1'1' IlU cstc 0 fUI1C\ic mcmbru a clusci complex. Fa are acccs la cornponentclc rca/ ~iimus; ale obicctului de lip complex rcfcrit dc r, nUJ1Jai duca csic () funciic pricicn ;t clusci coutplc».
140

a IlU include fisicrul BXXlJ3.H sc dcfincstc BXXlJ3 #define _BXXII3_H II sc include dcfinitia clasci complex din fisicrul BXXIIIS.H #include 'BXXII15.H' II sc includ dcfinitiilc functiilor mcmbru #include 'BXXII3.CPP'

141

// se include dcfinitia functiei prictcn cputcrc #include "BXXII14.CPP" #include <stdlib.h> main () /* citcstc intrcgul
(

23. SUPRAINCARCAREA OPERATORILOR


*/

n, calculcaza

si afiscaza (I+i)**n

int

DIe;

complex complex

z(1,1); zlan;

IIz=l+i IlzIan=O+O"'i

II citcsrc pe n for (;;) ( printf("exponent="); if((c" scanf("%d",&n)) 1) break; printf(j'nu s-a tastat un intreg\n"); if(c == EOF) ( . printf(·s-a tastat EOF\n"); exit ( ); fflush(stdin) ;

Tipurile abstracto de date sc definesc in limbajul C+! cu ajutorul clasclor. Ar fi ideal ca tipurile abstracte SCI se comporte ca si cele predefinite. Asa cum s-a ararat in capitolul precedent, exista 0 serie de asernanari intre tipuriIe abstracte si cele prec!efinite. Asa de exemplu, datele de tip abstract (obiectele) se declare! la fel ca si cele de tip predefinit, De asernenea, cle pot fi initial izate la dcclararc, Operatiile care sc pot executa asupra obiectelor sint bine precizarc ca si in cazul tipurilor predefinitc. in cazul tipurilor abstracto, opcratiilc se dcfinesc cu ajutorul/imc(ii/or membru ~iprieten. Exemplu: Pentru clasa complex se pot defini functii membru si prietcn pcntru a realiza ceie 4 operatii aritmctice asupra obiectelor de tip complex. In definitia de clasa, de mai jos, se defineste 0 functie mernbru pentru adunarea obiectclor de tip complex $i 0 functie prietcn pentru scaderca obiectclor de tip complex.
class complex double real; double imag; public; cornplex(double

complex int Ini

complex_unu(l,O);

m = n < 0 ? -n : n; II calculeaza absm) if(m == 0) ( II (I +i)**O = I +O.i comp lexjunu .afiscomplex (); exi t (0) ;
H(n

x=O,double

y=O)

== 1) ( z.afiscomplex() exit (0) ;

II (I+i)**! ;

== l+i

II constructor
real imag x; y;

if ( n == -1) ( II (l+i)**(-I)= 1/(I+i) zlan.divcomplex(&complex_unu,&z) ; zlan.afiscomplex() ; exi t (0) ;

II functic mcmbru pcntru adunarca obieetclor de lip complex compl"x ac1complex(comp.lex& z2); II fuuctic pricicn pcntru scadcrca obicctclor de lip complex fr iend compI "X sc comp Lox (complex& z 1, complex"

/1 m > I
cputere (z,m);
H(n> 1)(

II z = z**111 ;
};

z2);

z.afiscomplex() exit(O) ;

In continuare,
;

se pot defini functiile

adcomplex $i sccomplex ca mai jos.

/1 putcrc ncgativa:

z**n = llz**abs(n) zlan.divcomplex(&complex_unu,&z) zlan.afiscomplex();

complex comp lcx ::ac1complex (complex& z) 1* rcturncaza surna dintrc obiccrul complex curent si eel rcfcrit de z *1
(

complex

ztemp; real + z.real; irnag + z.imag;

ztemp.real ztemp. imag

142

143

return

zt.ernpi

Mccanismul operatii asupra


zl,complex& z2)

de protectie a date lor private asigura ca sa nu se poata realiza alte obiectelor de tip complex decit cdc precizate la definitia clasci 0 analogic intre tipurile predefinitc

complex sccomplex(complex& '* rcturucaza difcrciua zl-z2 */ complex ztemp;

complex.
Se obscrva abstract complex. Cu toate acestea, operatorilor obisnuiti operatiilor cu numere Astfel, daca i, j, k

.. int, long, float, double ;;1 tipul

ztemp.real zl.real ztemp.imag zl.imag return ztemp;


}

-z2.real; -z2.imag;

tipul complex definit ca mai sus, nu permite utilizarea pentru a exprima operatii cu obiecte complexe ca in cazul de tip int, long, float sau double. sint declarate prin declaratia:

Daca

a,

b,

sint 3 obiecte de tip complex

instantiate

ell ajutorul

declaratiei:

int i,j,k;

atunci se pot scrie expresii

de forma:

complex

a,b,c;

(5)
sau adunarii obiectelor complexe

k = i+j;

atunci instructiunea: (I) c " a. adcomplex (b) ; atribuie lui c, de tip complex, rezultatul Mcntionarn ca apelul: (2) a. adcornplex (b)

a si b.

(6)k

i-j;

Expresii de acest fel sint valabile daca x, y ~i z sint date de tip double:
double
X,Y,Z;

~ipentru alte tipuri predefinite.

De exernplu,

retumcaza un obiect de tip complex la tel cum tip tip.


1111111C_j( ... )

functie de antet: vcno') retumcaza


0 valoare de tip

atunci se pot utiliza expresii similare:

unde tip este un tip predefinit

(difcrit de cuvintul

(7)
sau

= =

X+Y;

Obiectul complex returnat prin apelul (2) (adica suma a+b) se atribuie obicctului complex c prin instructiunea (1). in daca obi si ob2sint illstarlti.erialc clasei I1l1l11e=clasa:

(8)

X-Y;

numeclasa obLobZ,
atunci 0 expresie
:,I

Evident, expresiilc de forma (5), (6), (7) si (8) sint sugestive si ar fi de dorit ca cle sa poata fi extinse si pentru obiecte de tip complex. Cu alte cuvintc, am dori ca in locul instructiunii (1) sa putCI11 folosi 0 instructiune de forma:

de forma:

(9)

a+b;

(3)

obl

ob2

iar in locul lui (4), instructiunea: (10) c = a-b; Acest lucru este posibil prin mecanismul de S_L!£I:3!,!~.q!.~:~!:(!~l?'jJ_'!.C(ltq!·il()!._. Operatorii + si - trebuie supraincarcati pentru a realiza operatii corespunzatoare ell obiecte de tip complex . De altfel, ei sint supraincarcati pentru tipurile predefinite int, long, float, double, unsigned, unsigned long si long double, deoarece se admit expresii de forma: obiectului asupra

c~tcadmisa de compilator ~i ea .atribuie lui obivaloarea O~i~~!llLLli.J?~:? Aceasta ~tribull:e se realizeaza priritr-o'eopiere bit cu bit a valorl10r cornponentelor lui ob2 in zoncJe de mernorie alocate cornponentelor lui obi. 0 astfel de atribuire nu este totdeauna corecta. cazul nostru, ea este suficienta pentru atribuirea obiectelor de tip complex. In mod analog, instructiunea:

.. " 1;;

(4) c = sccomplex(a,b); atribuie lui C obiectul complex rezultat prin scaderea obiectul complex a. In felul acesta se pot introduce si altc operatii complex Iolosind functii mcmbru sau prietcn.

complex b din
de tip sau

q+r;

obiectclor

q-r;

144

145

predefinite, enumerate mai sus. Supraincarcarile de tipuri predefinite sint prcdefinitc. De aceea, pentru a putea utiliza acesti operatori si cu operanzi de tipuri abstracte, este nevoie ca Ja definirea tipurilor respective sa se supraincarce operatorii in mod corespunzator. Ca rezultat al supraincarcarii operatorilor se ajunge ca operatorii respectivi sa poata fi utilizati in expresii obisnuite cu operanzi obiecte de tipuri abstracte. Limbajul Cs+ permite supraiucarcarea numai a operatoriJor existenti in

pentru

operanzi

de tipurile

este legala si ea are ca rezultat expresiei:


a. adcomplex (b)

obieetul

operatorilor

+ si -pentru operanzi

complexe a ~i b. Cu altc cuvintc,

complex rezultat prin adunarca obiectelor accasta expresic ponte II utilizara in locul

al carui sens este mai putin evident. se transcrie sub forma:


c = a+b;

in felul

acesta, instructiunea

(1) de mai sus,

limbaj.

l)iI1_t~_ace~!iaI1upot

fi supr'liI1carc£ltL~p~ratoEii:

:: ? si :
De ascmenea, pe;;tru

-¥ prin tipuri supraiI1carCareal)peratorilor .. 111 ~~(! .Pl)'lt(!__§C;hiIllQa 1 __ __ operatorilor, acestea fiind clemente predcfiillte~ideci ele se vor mentine si pentru tipuri

n-ariJg!_ea, prio!.it.gfC:u sau asociativitate_apredcfinite

care este la fel de simpla ~i clara ca si instructiunile (5) si (7) utilizate pcntru opcranzi de tipurile predefinite int si respectiv double. In mod analog, operatorul - poate fi supramcarcat schimbind numele functiei prietcn sccomplex cu operator - ca mai JOS:
complex operator - (complex& zl,complex& 22) /* _ suprainearca opcratorul _ pcntru obicctc de tip complex; _ functia returncaza un obicct complex care reprezinta difcrcnra dintrc obicctclc zl si z2 */ complex zternpi -z2.real; -z2.imag;

abstracte. Prin n-aritate intelegem ca operatorul este binar sau unar. Supraincarcarea operatorilor se realizeaza cu ajutorul unor functii membru sau prieten speciale. Specificul lor consta in numele acestora. El se compune din cuvintul cheie operator si unul sau rnai multe caractere care definesc operatorul care se supraincarca. Intre cuvintul cheie operator si caracterele care definesc
operatorul care se supraincarca se afla cel putin un spatiu alb. In cazul tipului complex, vorn folosi pentru supraincarcarea functia definita mai jos:
complex complex: :operator + (complex& z) /* supraincarca opcratorul + pentru obiecte de tip complex; _ funciia rctumcaza un obiect complex care rcprezinta SlI1113 dintrc obicctul complex curcnt si eel refcrit de z. */
(

ztemp.real zl.real ztemp.imag zl.imag return ztemp;


}

operatorului

In continuare, a-b in locul apclului

se pot utiliza expresii

de forma:

funcriei sccomplex:

sccomplex(a,b)

complex

temp; z.real; + z. imag ;


+

temp. real = real temp. imag = imag r e t.ur n temp;


)

Din cele de mai sus se observa ca ~_~~~~EiLp()!E~_Upra!11.earca\iprillfunctii mcmbru sau prin functii prieren. Odiferentaintre cele dona tipuri de functii ~onst[l ..in numarul de parametri, Astfel, f~jile_Jl1embru care xupraincarca 01?~_ra1<?Ei_iunari au parametri, jar celecare suprail1carc~-operatori I1U hinari. all un singur P?rqmetlu.· .. _ _ , . in cazul functiilor prieten, numarul parametrilor este egal CLl n-ariratea operatorulu i care sesupraincarca. Motivul pentru a utiliza 0 functie membru sau prieten pentru a supraincarca un operator va rezulta dintr-un paragrafulterior. I:(l_S~lprajncarc(lre"operatorilorpentru.2biccte de tip abstract nu se ponte face diferenta intre forrnele prefixate si postfixate. . . Anumiti operatori prezinta unele particularitari la supraincarcarea lor Si de aceca ei vor fi tratati in paragrafe separate. in principiu, functiile mcmbru care supraincarca un operator nu sint statice, exceptie de la aceasta regula 0 constituie supraincarcarea operatorilor unari /lew ~idelete. Acestia se pot supraincarca nurnai prin functii mernbru statice,

..,

·v

In aces! caz, numele

functiei

este:

operator +
in rest, functia care supraincarca operatorul

+ este

identica

cu functia membru

adcomplex definita mai sus.


Efeetul schimbarii numelui adcomplex prin operator + cste acela al supraincarcarii operatorului + pentru a admite ca operanzi obieete de tip complex. Deci, 0 expresie de forma: a+b

146

147

Alti operator: care prezinta particularitati la supraincarcare sint parantczclc, opcratorul -> si opcratorul de atribuire (=). Mai sus, am considerat supraincarcarea operatorilor binari pentru cazul cind arnbii operanzi sint de tipul abstract complex. Se punc problema de a utiliza operatorii rcspectivi si cu operanzi diferiti, adica in expresii de forma: a+k, k+a, a-k, k-a unde: k - Este 0 variabila de tip int, iar a un obiect de tip complex.

Adaugind una din aceste functii, se pot utiliza instructiuni de forma:


complex int k; b b a,b;

a+k; a+123;

S[, observarn ca functiile de mai sus imp lie a faptul ca primul operand al operatorului + sa fie de tip complex. Aceasta inseamna ca expresiile de forma: k+a i 123+a • sint ilegale. Pentruaaceepta astf~ld~expresiiestenecesarca opcratorul + sa fie suprail1earcatil1i~od c()r~~punzator, adica pentru-expresiiin eare primul operand estecl~_tipint,. iarc91c\ealdoilea de tip c:omplex , o astfel de supraincarcare se poate realiza dar flllmaiprjntr"01ful1C!ieprietcl1( dcoarece in cazul funqiiior meii1f)ru~prlmul parametru ~St~h)tdeauna ON9-ctul' curenf~rd-eCl acesta-- PQatefi d~ tipillt. . -- .. -.. --De aceca, pentru a admite expresii in care primul operand este de tip int, iar eel de al doilea este un obiect de tip complex, vom utiliza functia prieten de mai jos.
complex operator + (int k,complex& /* rcturncaza obicetul complex k+z */
0
{

Exista doua solutii pentru a putea utiliza cxpresii dc aceasta forma. 0 prima solutio este supraincarcarca operatorului + nu numai pentru opcranzi de tip complex, CI ~I pcntru operanzi de tipuri diferite. . A doua solutio consta in conversia operandului care nu estc de tip complex mtr-un obicct de up complex inainte de a aplica operatorul plus supraincarcat pentru operanzi de tip complex. Acest lucru se poate realiza de stu I de simplu, dar nu totdeauna este eficient, Pcntru moment ne rcfcrim la prima solutio, iar solutia a doua va fi tratata intr-un capitol nou eu privire Ia eonversii. Pentru a lcgaliza expresii de forma:
a+k

'I(

t_ )

z)

unde (~estc un obicct de tip complex, iar lc 0 variabila dc tip int, putern adauga noua functic operator membru sau prieten de felul celor de mai jos.
complex complex: :operator + (int k) f* returncaza obicctul de tip complex rczultat prin adaugarca la obicctul complex curent a valorii lui k *f
(

complex

ztemp;

ztemp.real = z.real+k; ztemp.imag = z.imag; return ztemp;


}

complex

ztemp; k;

ztem.real = real. ztemp.imag = imag; return ztemp;


)

Din acest exemplu se vede ca supraincarcarea operatorilor nu permite mostenirea proprietatii de cornutativitate a acestora, Astfel, desi operatorul + este comutativ pentru operanzi de tipuri predefinite, supraincarcarea lui pentru expresii de forma: a+k uncle: a k - Este obiect de tip complex. - Este 0 variabila de tip int, nu este valabila si pentru expresii de forma: k+a Exercitii: 23.1 Sa se defineasca tipul abstract complex supraincarcind operatii eu numere eomplexe dupa cum urmeaza: operatori pentru

are acelasi efect.

In locul acestei functii membru putern defini functia prietcn, de mai jos, care

complex operator + (complex& zl,int k) f* rcturncaza obicctul de tip complex rczultat prin adaugarca la zl a valorii lui k *f
(

complex

ztemp;

ztemp.real zl.real + k; ztemp.imag zl.imag; return ztemPi

148

149

"----"-"--"-"--"-

---,-.-~~-~--.--_---,----

operatori ----Adunare

tipul operandului sting

--------complex double complex

tipul operandului drept

-----

tipul rezultatulu

----]
.

afisarea unui numar complex; incrcmentarea dccrcmentarea returnarea returnarea parti: imaginate partii imaginate a unui numar complex; a unui
I1UI11[H

+ + +
Scadere

complex complex double

complex complex complex

complex;

partii reale a unui nurnar complex; partii imaginate a unui numar complex.

complex
"--

complex double complex

complex complex complex ----complex complex complex complex complex complex

Ridicarea la putere (operatorul t,) sc rcalizeaza folosind formula lui Moivre. Daca z = a+b*i, atunci tic forma trigonornctrica a lui z:
"Z

complex double

= r*(cos(alfa)+i*sin(alfll)) r**n*(cos(n*alfa)+i*sin(n*alfa» 2*k*PI+beta


- Este

Pentru n tntreg si pozitiv, avem: z**n n=alfa uncle: k


=

Inmultire

* *

complex complex double complex complex double

complex double complex complex double complex


lmpartire I I I --"Ridicarc la putere
A

Unghiul n+alfa se poate reduce la primul cere daca se pune sub forma:
=

partea intreaga a irnpartirii

(n*alfa)/(2*PI).

PJ= 3.14159265358979. Daca n < 0, atunci: z**n


=

l/z**abs(n) C, pcntru ridicarca la putcre s-a mica decit it opcratorilor binari se vor utilizaparanteze rotunde expresiei:

complex --.-~- ...-..------ f---------Test de egalitate

-------complex double complex

int

".'

.-~-".-,-.-.-----

complex

----

complex complex double

int int int


"--_

Intrucit operatorul ** nu cxista in limbajul ales operatorul ". Prioritatea acestuia este rnai aritmetici. De aceea, in cxpresii mai eomplexe pentru a impune ordinea dorita a operatiilor. De exemplu, ordinea operatiilor in evaluarea a*x"lO

-Negativare

---

complex

complex

Incrementare

unde a $i x sint nurnere complexe, cste urmatoarea: • se mmulteste a cu x; • rezultatul inmultirii se ridica la puterea 10. la putere a lui x si apoi inrnultirca cu a, vom Pentru a realiza inrii ridicarea utiliza expresia: a*(x" 10) Testul de egalitate este util mai ales la stabilirea nul sau nu. 0 expresie de forma: a==b uncle a ~i b sint ambele numere complexe sau unul este complex 0i cclalalt de tip numeric (int, long, unsigned, double ete.) are ca rezultat una din valorile Osau I. Rezultatul expresiei este 0 daca cei doi operanzi sint diferiti si I altfcl. 151 daca un numar complex este

++
Decrementare

complex

complex
"----"

-Radacina pturatd

complex

complex

- ------

complex
----- ------_
l------------

, ,,,,"oJ

De asemenea, se definesc functii membru pentru: modulul unui numar complex; argumentul unui numar complex; citirea unui numar complex; 150

Opcratorul

de incrementare

(++),

incrementeaza

partea

rcala a numarului partea rcala a a numarului

complex la care sc aplica, in mod analog, operatorul

II incrcmcntcaza partca imaginara void i p i. () ; II dccrcrncntcaza partca irnaginara void dpi (); II obicctul curcnt sc notcaza eu z II obicctul rczultat sc notcaza ell r II opcratori unari /1 ncgativarc complex ope ra t o r - (); /1 incrcmcntcaza partca rcala complex operator ++

de decrementare folosind

(--), decremcntcaza forma

numarului

complex
patrata

la care sc aplica,
se calculcaza

Radacina

trigonornetrica

complex. Astfel, daca: z

a-fib

r*(cos(alfa)+i*sin(alfa)) patrata din z sc determine ca mai jos:

atunci radacina

// r

-r.

zl = sqrt(r)*(eos(alfaJ2)+i*sin(alfa/2»
~l

();

z2

sqrt(r)*(eos(alfa/2+PI)+i*sin(alfa/2+PI» -sqrt(r)*(cos(alfa/2)+i*sin(alfa/2» = -zl

// dccrcmcnteaza partea rcala complex operator /1 radacina patrata complex operator II opcratori binari II adunarc d); II r= z+z2 complex II r = z+d complex Ilr=d+z2 friend II scadcrc II r= z-z2 complex II r= z-d complex

();

FIl?IERUL BXXIII1.H
class complex ( double real; double imag; static int citdouble(char *s,double& 1* - afiscaza s; citcstc un numar si-l alribuic datci rcfcritc de d:
- rcturncaza:

! ();

II r

sqruz)

operator

(complex&

z2);

o - la sfirsit
I - altfcl. */

de fisicr;

operator

(double

dl ;

publ ic: II constructor complex(double x=O,double II rnodulul nurnarului complex double modul () ; II argumcntul numarului complex double arg (); /1 citcstc 1I1111Umarcomplex

y=O);

complex

operator

(double

d, complex&

z2);

operator

- (complex&

z2);

operator

- (double

d);

int citcomplex (char *s); 1* - afiscaza s; - eitestc cornponcntclc nurnarului complex; - rcturncaza: o - la sfirsit de fisicr; I - altfel. */ II afiscaza un numar complex void afiscomplex(char *f); I*atlscaza cornponcntclc numarului complex conform forrnatului

II r = d-z2 friend complex

operator

- (double

d, complex&

z2);

/1 inrnultirc 1/ r = z*z2
complex II r= z'd complex f */ operator

(complex&

z2);

operator

(double

d l:

II r ,= d*z2 friend complex

operator

(double

d, complex&

z2);

152

153

II impartirc II r 7172 complex operator II r z/d complex

/ (complex&

z2);

operator

/ (double

d);

II r d/z2 friend complex

operator

/ (double

d, complex&

z2);

#endif hfndef BXXIIIl_H #include "BXXIII1.H" #define _BXXIII1_H #endif .ifndef STRING~1 #include <string.h> #def ine S'I'RING_H # end if inline complex: :complex (double // constructor utilizat la initializarc; 1/ implicit. x~y~O
(

x,double

y)

II ridicarc la putcrc Ilr z**i complex operator II test de cgalitatc

r i nt; i);

real
irna<;f

x; Y;

/* a == b; sc rcturncaza 0 sau I dupa cum relatia cstc falsa sau adcvarata *1 II z == b int operator d // z int operator II d == b friend inl ine double complex:: modul () II rcturneaza modulul obicctului curcnt (complex& b);
(

return (double d) ;

sqrt(real*real

+ imag*imag);

double complex: :arg() II rcturncaza argumcntul obicctului curcnt int operator (double d,complex& b);
(

II rcturncaza partca rcala a lui z double retreal(); II rcturncaza parte a imaginara double retimag();
);

a lui z

if(real == 0 && irnag 0) return 0.0; Hz==O if (irnaq == 0) II r. = parte rcala if(real > 0) return 0.0; /Iz purtcreala c O else return PI; II z = parte reala < 0 if (real == 0) II z = parte imaginara if (imag > 0) r e tur n PI/ 2; II t. = parte irnaginara else return (3*PI) /2; II z = parte imaginara // z real +i*imag; real!= 0 si imag
1= ()

> () <0

Functiile care intcrvin in definiria scparat, de extensie CPP. FI~IERUL BXXIII1


Hfndef STDIO_H #include <stdio.h> #define __ STDIO_H #endif MATH_H #ifndef ffinclude <math.h> #define .l'iA1'H_H #endif Ilifndef PI #define PI 3.14159265358979 #define PI Ilendif #ifndef __ s'rDLIB_H #include <stdlib.h> Ide fine STDLIB_H

clasei complex se defincsc intr-un fisier

double a = atan(imag/real); if(real < 0) return P1+a; if(imag < 0) return 2*P1+a; return a:

/1 real < 0 si imag != 0 II real> 0 si imag < () II real> () si imag > 0

int complex: :citdouble(char

*s,double&

d)

/* - afiscaza s;
• citcstc un numar si-l atribuic datci rcfcritc de <I; . rcturncaza: () - la sfirsit de fisicr; I - altfcl. */ char
t [2551 ;

155 154

for ( ; ; I {
.if(stl.-len(

II pt"i.ntt(sl; (I
f (!lnu s-a

Ilsil"lIlsnllcslevid

o:

print

p r i.nt. J {" n 1;

reia

0; II s-a intilnit EOI' 1} break; un numar\n" I; citirea\n"l;

return 0; if (complex: : c i tdouble return 0; return 1;

( "Partea

imaginara

",imag)

01

void complex: :afiscomplex(char *fl 1* afiscaza componcntclc obicctului curcnt cu forrnatul f; daca Ircprczinta sind vid, cornponcntclc sc afiscaza in format standard if ( * f I II fonnatul de afisare nu este vid printf(f,real,imagl; else /1 format standard printf ("%g+i* (%gl \n" ,real, imagl;

*1

tnt
/*

:C'itcomplE~:z:(char *s} afiscaza s daca nu cstc vid: daca s cstc vid sc afiscaza i'artca rcala si Parten imaginara - citcsrc cumponcntclc obicctului complex curcnt; - rcturncaza: O· la slirsit de fisicr; I alttcl.
complez:

rcxtc standard:

i n Line void 1* incrcmcntcaza imag++;

oomp l ex : : .ip i (I partea imaginara a obicctului

complex

curent *1

*1 if (*sl { II simi s nu cstc vid; /1 sc citcsc componcntclc obicctului for (; ; I ( intl(sl; int
clouble
j ((

curcnt

In Li ne void 1* dccrcmcntcaza
(

complex: :dpi(1 partca imaginara a obicctului complex

curent *1

di

imag--i
== EOF)

scanf("%lf"",dll
1) {

return

0;

if

(j

plintf("nu

s--a tastat

un numar\n");

complex complex: : operator () II rcturncaza negativul obicctului complex eurcnt: r = -z


(

printf("pentru partea reala\n"); p rin t f t vs o r e i a citirea de 12.1inceput\n"); 1 u s h (s tdin I; /1 vidcaza zona tampon c o n t i.nuc:
ls e
((i

complex

r:

real
1) (

d;

r.imag return

imagi
ri

scanf("%If",&d))

==

EOF)

return

O'

if

(i

printf("nu s-a tastat un numar\n'l); [)yirltf("pentru partea imaginara\n"); printf("se reia citirea de la inceput\n"l f flush (s t d in I; II vidcaza zona tampon

inline complex complex: : operator ++ (I 1* incrcmcntcaza partca rcala a obicetului complex curcnt *1
(

real++ ; return *this;

irna9 -.= <:1; fl u s h ts t d in ) ; ret.urn 1, , II xfirxit for II xfirxit ins) Ii s poinrcaza ,'pre sim! viti if( : :ci t doul-ie
(I'.r)a.rt(~(.l

inline
(

1* dccrcmcntcaza
real-return
i

complex complex:: opera tor -- (I partca rcala a ohicctului complex curcnt *1

*this;

rE::fJla

", .noill I

1)1

compl ex complex:: opera tor ! (I 1* calculcaza radacina patrata din obicctul complex

curcnt OJ

156

157

complex r : double d;

// implicit

real=imag=O

r. real = real-d; r. .i ma q :::: imag i r e t.urn r . r; // obiect complex nul complex operator r: - (double d, complex& z2) II r = d-z2
(

i f ( ( d=modu I ( ) )

0) return

double alfa; alfa = arg(); // argumentul obiecrului complex d = sqrt(d); II radacina patrata din modul alfa = alfa/2; r.real = d*cos(alfa); r.imag = d*sin(alfa); return r'

complex r.real r.imag return

=
=
r;

d - z2.real; -z2.imag;

complex complex
(

complex: :operator r;
= real*z2.real

* (complex&

z2)

1/ r = 7*z2

complex: :opera tor + r;


= real

(complex&

22)

// r = z+z2

complex complex r.real r.imag return r.real r.imag .return

imag

+ z2.real; + z2.imag;

= real*z2.imag rj

- imag*z2.imag; + imag*z2.real;

ri complex complex: :operator r; :;:: real'kd; = imag*d;


ri

* (double

d)

II r = z*d

complex
(

complex: :operator r;
= real + d;

(double

d)

Ilr=z+d

complex complex r.real r.imag return r.real r.imag


return

:::: imagi rj

complex
(

operator r;

+ (double

d ,complex&

z2) /1 r = d+z2

complex
(

operator r;
=d* ri

* (double

d,complex&

z2) Ilr=d*z2

complex r.real r.imag return

complex r.real r.imag


return

d + z2.real; = z2.imag; r;

z2.real; = d * z2.imag;

complex
(

complex: :operator r;

-(complex&

z2)

II r = z-z2

complex
(

complex: :operator

(complex&

z2) II r = 7/z2; cc 0 daca z2 r

()

complex r.real r.imag return

complex r; double d = z2.real*z2.real - z2.real; - z2.imag;

z2.imag*z2.imag;

real imag

r;

complex
(

complex: :operator r;

- (double d)

II r = z-d

if(d =oo 0) /lz2=0 return rj r.real (real*z2.real+imag*z2.imag)/d; r.imag (imag*z2.real -real*z2.imag)/d; return r;

complex

158

159

complex
(

complex:
ri

:operiJtor

(double

d) Ilr

z/d;r

(l duca d= U

cornp1ex

ifld
ri
r e a

0) I
·2
r ea

return
Lv d :

r;

inline int complex::operator /* rcturncaza: I daca z=zz: () altfcl. *1


(

(complex&

z2)

r.imag return

imag/d;

return

rea I

z2.real

&& imag

z2.imaC);

r; inline int complex: /* rcturncaza: J daca z=d; o altfcl. *1


{

: operator

(double

d)

complex
(

operator

(double

d , complex&

z2)

II r

d/z2;

0 daca z2 ~ 0

complex r; double dm = z2.real*z2.real ifldm==O) Ilz2=0 return r; r.rea] = .real*d/drn; r. imag 22. imag·'d/dm; return r;

+ z2.imag*z2.i.maSJ;

return

real

d && imag

0;

complex
(

complex::

operator

(int

i ) II r ~ z**i; r

0 daca z ~ 0

inline int operator /* rcturncaza: I daea d=z2; o allfe!' *1


(

(double

d,complex&

z2)

c ompl ex r;

double if Ie!

d
0)

II rcnl illlag 0 mo du I ( ); II rnodulul obicctului curcnt r e t ur n r , II obicctul curcnt cstc nul; ridicat la putcrca i II rczulta obicctul nul i: i; II n

return

z2.real

&& z2.imag

0;

int n =i < O"? i£


(n

= abs(i)

inl ine double complex:: retreal () /* rctumcaza partca rcala a obicctului complex curcnt
(

*/

return == 0) Ilz**O= I return complex(l,O); if(i == 1) Ilz**l=z return *thisi i£ Ii == ~l) /Iz**(-I) liz r = *this; i£(n> 1)( d = pow(d, (double)n); Ild=d**n double a z; a r o I); // a = argumentul obiectului a' = n; 1/ a urgumcnt+n II rcduccrc la prirnul cere

real;

inl .irie double complex:: retimag () /* rcturncaza partca imaginara a obicctului complex
(

curcnt */

return

imag;

complex

curcnt

23.2 Sa sc scrie un program care rezolva ccuatii de gradul intii eu cocficienti cornplecsi: ax+b = 0 (a si b sint numere cornplexe) Programul citeste numerele complexe a si b ~iafiseaza valoarea lui x daca a != O. Se pot rezo1va mai multe ecuatii de aceasta forma. Pentru a intrerupe executia programului se tasteaza sfirsitul de fisier. PROGRAMUL
#include

double doipi=2*PI; long x = a/doipi; a ~= x*doipi; r.real d*cos(a); r.imag = d*sin(a); i£li<O) r
1'0 LUI"ll

BXXIII2
CPP"

"BXXIIIl.

l/x**i~l/z**n .01 r ; 1/ opcratorul r:

/ csrc supraincarcat

pcntru double/complex

main () 1* rczolva

ccuatii de gradul

I cu coeficicnti

complccsi

de forma:

160

161

ax + b
- prcgrarnul *1 complex for I;;

= 0;

complex la tastarca sfirsitului de fisicr.

a;

sc tcrmina

a,b,x;

( (a c it cornp Lex t va e ") == 0) exitIO); iflb.citcomplexl"b= ") == 0) exitll); ifla 0.0 && b == O.O){ printf I "ecuatie nedeterminata\n"); continue;
i

for I; ;) ( ifla.citcomplcxl"") 0) exitIO); a++; II incremcntcnza partca reala a lui a a. a£iscomplex I"") ; ) II sfirsu for
)

Observatil: 1. Functia citcomplex este apclata cu sirul vid. in acest caz se afiscaza textul: Partea reala == si dupa tastarca numarului rcspcctiv se afiscaza textul: Partea imaginara Partea reala a numarului complex se incremcnteaza apelindu-se operatorul unar++ supraincarcat pentru numere complexe. In program s-a folosit forma postfixata, Se poate utiliza la fel de bine forma prefixata: ++a; obtinindu-se acelasi efect.
Mentionam

ifla I "ecuatia continue; -b/a; x.afiscomplexl"x ) II sfirsit for


X

nu are

solutie\n");

2.
%g+i* I%g) \n") ;

Observatii: 1. Instructiunea: X = -b/a; coniine doi opera tori supraincarcati: - operatorul unarsi - operatorul binar I Operatorul unar este prioritar celui binar. La Iansarea programului se afiseaza: a= apoi, se asteapta tastarea cornponentelor numarului complex a. Daca nu se tasteaza EOF, dupa tastarea cornponentelor nurnarului a, se va afisa: b= apoi, se asteapta tastarea componentelor numarului complex h. Sa se scrie un program care citeste numere complexe si le afiscaza cu partea reala marita cu I.

ale operatorilor abstracte. 23.4

ell nu sc face nici 0 diferenta intre formele postfixate ;;i prefixate de incremcntare si decrernentare suparaincarcati pentru tipuri care rezolva
0

Sa se scrie un program plecsi.

ecuatii

binome cu coeficienti

com-

Prin ecuatie binoma mtelcgem a*x**n+b = unde: n a si b

ecuatie de forma:

2.

- Este un numar natural pozitiv. - Sint nUl11ere complexe.

23.3

Pentru n > I, solutia ecuatiei este radacina de ordinul n din numarul complex -b/a. Radacina de ordinul n dintr-un numar complex se determine din forma trigonornetrica a acestuia, Fie: z=x+i*y un nurnar complex
~I

PROGRAMUL BXXIII3
#include "BXXIII1.CPP"

z=r*(cos(alfa)+i*sin(alfa))
ell

forma lui trigonornetrica. din


z

main! ) 1* - citcstc numcrc complexe si Ie afiscaza eu partca rcala maritu - programul sc tcrmina la intilnirea sfirsitului dc fisicr. *1

I;

Atunci radacinile de ordinuln

se calculeaza

ca mai jos:

zk = r**(l/n)*(eos«alfa+2*k*PI)/n)+ i*sin«alfa+2*k*PI)/n)), pentru

k=0,1,2, ... ,n-1. 163

162

Expresia

Valoarea

r**( lin) are ca valoare radacina de ordinuln din numarul rational r. ci se deterrnina Cll ajutorul functici pow.

PROGRAMUL BXXI1I4
"HXXII 1.CPP"

II ccuatie de gradul intii sau solutic nulu x. afiscomplex ( "x=%g+i I%g) \n") ; II sfirsit for else

main ()
- rczolva ccuutii prograrnul

23.5
binomc(a*x**n + b 0); sc termina la lastarca sfirsitului de fisicr. *1

Sa se scrie un program care rezolva cornplecsi. BXXII15

ecuatii de gradul 2 cu coeficienti

PROGRAMUL
comp l o x a , b , x :

int

[1;

#include

"BXXIII1.CPP"

for(;;)( ci t c ompLex t va e ") =c, 0) exit(O); if(b.citcomplex("b= "I' == 0) exit( ); if ta 0.0 && b == 0.0) ( p ri n t f I "ecuatie nede te ruu na t a vn vt . continue;
i.f r a
i

main() 1* rczolva ccuatii de gradul 2 a *x *x + b*x + c = ()

Cll

cocficicntii

cornplccsi:

*1
{

complex

a,b,c,x;

ifla

0.0) ( print£I"ecuatia exit 11);

nu are

solutie\n");

II a int

1=

0 i;

for I;; I ( if(a.citcomplex("a= .i f t b c i t.c omp Le x Lvb> if(c.citcomplex("c= ifla == 0.0 && b == printf("ecuatie continue;
i

01 exit 101; 0) exit(l); 0) exit (1 I; "I 0.0 && c == 0.0l{ nedeterminata\n"l;


"I

"I

ifla

for I; ; ) ( printf(j'gradul ecuatlei = "); iflli=scanf("%d",&n)) == EOF)! printfl"s-a t.a s t.a t; EOF\n"); exit(l); iii 1 printfl"nu fflushlstdin)
&&

== 0.0 &&b == O.O){ printf("ecuatia nu are continue;

solutie\n"l;

n > 0) break; s-a tastat un intreg ;

pozitiv\n");

ifla==O.O){ printf("ecuatie de gradul l\n"l; x = -c/b; x a f i s comp Lex t "x %g+i* (%g) \n"); continue;
i

II a 1= 0: ccuatic de gradul 2 1111> 0


x

if(n> 1 && !(x == 0)) ( Ii ccuauc de grad mai marc ca 1 double r = x.modull); double teta = x.argl); r pow Ir , 1 . 0 I n I ; forlint k = 0; k < n; k++1 ( double a Lf a ( t e t a + 2*PI*kl In; c ornpLex xk(r*coslalfal ,r*sin(alfa) print! I "x%d=,",.I<I; x k . a f: s comp l ox ("") ;

-b/a;

complex doia = 2.0*a; complex delta = b*b-4.0*a*c; del ta =! del ta; II radacina patrata din delta x = (-b+deltal/doia; x.afiscomplexl"xi = %g+i*l%g)\n"); x = l-b-delta)/doia; x.aEiscomplex("x2 = %(J+i*(%gl\n"l; ) II sfirsit for
}

I;

23.6

Sa se scrie un program care citeste numere cornplexe si afiseaza puterea a 5-a a ficcarui numar citit, adunata eu 1. 165

164

Programul foloseste operatorul 1\ care a fost supraincarcat ell functia putere pcntru numcre cornplexe. Daca z este numarul complex citit, atunci programul afiscaza numarul complex definit de expresia: z*z*z*z*z+ 1 care, ell ajutorul operatorului
(zI\5)+1
1\

FI$IERUL BXXII17.H
cl a ss vb ( double el,c2;

se serie:

public: II constructor vb(double

vl=O,
J

double

v2=O);

PROGRAMUL
#include

BXXII16

II surna a doi vcctori: vb operator +

-vb+vb ; (vb& vb2);

'BXXlll1.CPP'

main( ) 1* - citcste nurncrc complcxc; - afiscazn putcrca a 5-a a ficcarui numar citit adunata

II diferenta a doi vcctori: r=vb-vbz vb operator (vb& vb2); cu 1 II produsul dintrc un vector si un numar: r=vb=a vb operator * (double a); II produsul dintrc un numar si un vector: r=a*vb2 friend vb operator * (double a, vb& v2);

*1
(

complex

z ,v ,
'''') == 0) exit (0);

for (;;) ( if (z.eitcomplex( v =(z 5) +1; z.afiscomplex("z v.afiscomplex("


A

II ncgativarca unui vector: r = -vb vb operator -(I; Illlillgimca vcctorului curcnt double lungime(); II produsul scalar a 2 vcctori r=(vb,vb2l double operator * (vb& vb2);

= %g+i*(%g)"); z**5+1 = %g+i*(%g)\n");

Observatie: in absenta parantezelor, expresia:


zI\5'!-1

1* - citcstc componcntclc

ridica pe 23.7

la puterea a sasea, deoarece operatorul

+ este mai prioritar decit

1\.

unui vector, dupa afisarca - rcturncaza: 0- la sfirsit de fisicr: I altfcl. "text);

unui text:

*1
int eitvb(char 1* afiscnza componcntclc void afisvb ();

N umirn vector n-dimensional un sistem ordonat de n numere reale, Se cere sit se implementeze eonceptul de vector bidimensional. in acest scop, vern presupune ca vectorul bidimensional este un sistem ordonat de 2 numere de tip double.

unui vector cu Ull format standard:

(e I ,c2l

*1

Asupra vectorilor vom defini urmatoarele operatii: suma a doi veetori; diferenta a doi vectori; produsul dintre un vector si un numar; negativarea unui vector; lungimea unui vector; produsul scalar a doi vectori; citirea si afisarea componentelor vectorului; returnarea componentelor unui vector.

1* afiscaza componcntclc void afisvb(char

unui vector cu un format dar *1 *format); a vcctorului a vcctorului

II rcrurncaza prima componcnta double retel(); II rcturncaza a doua componcnta double retc2();
};

Functiile membru si opcratorii se definesc in fisierul de mai jos, de cxtensic cpp,

166

167

FI~IERUL BXXII17
STDIO Ii II f nde f i #include <stdio.h> Hdefine STDIO Ii #endif 11 f ndo f _MAT!-! i H #include <math.h> #define NATH_H Ilendif # i fnde f STTUNG_H #include <string.h> #def ine STlUNG __ H lIendif #ifndef BXXIII7 __ H #include "BXXIII7.H" BXXIII7 Ii #define #endif .i nl i.rie vb: :vb(double c1
}

1* opcratorul * cstc supraincarcat pcntru produsul un numar prin functia prcccdcnta *1

dintrc un vector si

vb vb: :operator vb vtemp; vtemp.cl = -el; vtemp.e2 = -c2; return vtemp;

-I)

1/ ncgativarca

unui vector r = -vb

inline return

double

vb:: lungime ()

Illungimca

vectorului

curcnt

sqrt(cl*el+e2*c2);

inl .ine x,double y) Ilconslruclor return

double

vb: :operator"

(vb& vb2) II produsul

scalar a doi vcctori

cl*vb2.el+e2*vb2.c2;

x; c2 = y; int vb: :eitvb(ehar *text) 1* _ citcstc cornponcntclc unui vector dupa afisarca unui text dcfinit - rcturncaza: () - la intilnirea 1 - altfcl. *1 char t.[255]; double d; II diferenta a doi vcctori r=vb-vb? for (;;) if(strlen{text)) printf(text); printf("\n prima componenta a veetorului if(gets(t) == 0) return 0; Ils-aintilnitEOF if(sscanf{t, ''%If'',&d) != 1) { p r i n t f ("nu s-a tastat un numar\n"); printf("se reia citirea\n"); continue; cl = d; printf("cornponenta a doua a vector1.llui = if (gets (t ) == 0) return 0; 1/ s-a intilnit EOF if(sscanf(t, ''%If'',&d) == 1)( c2 = d : return 1; printf("nu printf("se s-a tastat un n1.lmar\n"); reia eitirea\n"); sfirsitului de fisicr: de paramctru;

vb vb: :opera tor + (vb& vb2)


vb v romp :

II surna a doi vcctori r

vb+vb2

c1 + vb2.cl; vtemp.cl c2 + vb2.c2; vtemp.c2 return v r ernp:

vb vb: :operator
{

- (vb& vb2)

vb vtemp; cl - vb2.c1; vt.emp.c1 c2 _.vb2. c2; vtemp.c2 return vtemp;

") ;

vb vb: :operator
(

" (double

a) II produsul

dintre un vector si un numar

");

vb vtemp; a*cl; vtemp. cl vternp.c2 a*c2; return vtemp;

i n li ne

vb operator"

(double a,vb&

vb2) IlprodllsuldinIrclInnumarsiullveclor

168

169

inline void vb: :afisvb() '* afiscaz» componcntclc vcctorului curent folosind
p ri nt.f
)

un format standard */

vb a,b; char ('rl]

~a intilnit a
xn")

EOF\n"; 01 (

("vb

(%g,%g)\n',cl,c2)

void vb::afisvb(char "format) 1* afiscaza componcntclc vcctorului curcnt folosind


(

.i f t a .«: tvb("vc'ctorul pr.intf ('o'x) ; exit t L) : formatul dcfinit de paramctru *f


)

if(forma~&& strlen(foxmat)) printf(format,cl,c2); else /* a fisarca cu format standard dcoarccc paramctrul format cstc fie nul, tic poirucaza sprc simi vic! */ a f isvb (); // afiseaza cu format standard

if lb.citvb( "vectorul printf( I; exi til) ;

b vn ")

01 (

// afiscuza lungimi!« vcctorilor printf('lungime(a) print ("lUllqirne{b)

%g\n', %q\n",

a.lungime()); b.lunqime());

inline return

double cl;

vb: :retcl () // rctumcaza prima cornponcnta a vcctorului

1/ afiscaza valorilc cclorlalte cxprcsii vb c; c=a+b; c.afisvb('a+b - %g\t %q\n");


c:::a-b;

inline return

double c2;

vb:: retc2 () // rcturncaza components a doua a vcctorului

23.8

Sa se scrie un program care citeste 2 perechi de numere componentele vectorilor a si b, apoi calculeaza si afiseaza: lungimea fiecarui vector; suma: a+b;
difcrcnta: a-b;

ce reprezinta

%q\t C6q\n"); c.afisvb("a-b c=3*a+7*b; c.afisvbl"3*a+7*b = %g\t %g\n'); c=-a-b; c.afisvb{'-a-b = %g\t %g\n"); /1 afiscaza produsul scalar printf I" (a , b) = %g\n", a"b);

surna: 3 *a+ 7*b; suma: -a-b; produsul scalar al celor doi vectori: (a.b), PROGRAMUL BXXII18
#ifndef #include #define #endif #include STDLIB_H <stdlib.h> STDLIB __ H "BXXIII7.CPP·

23.9

Sti se defineasca tipul abstract care implcmcnteaza ordinul2.

conccptul de rnatricc de

main I I 1* ~ citcstc cornponcntclc vcctoriior ~calculcaza si afiscaza: lungimca vcctorilor a si b; suma: a+b;

si b;

~difcrcnta: a-b;
~ suma: }*a+7*b;

-a-b: ~ produsul scalar: (a.b).


~ Slll1la:

*/

La definirea unci matrice patratice de ordinul doi se poatc proccda in mai multe moduri: tablou bidimensional de ordinul 2*2; tablou unidimensional de doua clemente, fiecare clement f ind un obicct de tip vector bidimensional; doua obiecte de tip vector bidimensional. In exercitiul de fata, rnatricea se implementeaza printr-un sistem ordonat de dona obiecte de tip vector bidimensional. Primul obiect defineste prima linie a matricei, iar eel de al doilea obiect defineste linin a doua a matricei. Asupra matricelor patratice de orelinul doi se definesc urmaroarcle operatii: suma a doua matrice; diferenta a doua matrice; produsul a doua matricc; inversa unei matrice; negativarea unei matrice; 171

170

prcdusul unci rnatricc cu un numar; calculul dctcrminantului unci rnatricc; prcdusul dintrc 0 matricc si un vector bidimensional. Altc funcrii mcrnbru: citirca clcmcnrclor unci matricc: afisarca elcrnentclor unci matrice; rcturnarea liniilor unci matrice, FI~IERUL BXXIII9.H
#ifndef # inc 1udo #define !fendi! class BXXIII7 11 "BXXJ I 17 . H" Ii clasa vb dclincsrc vcctorii bidimcnsionali BXXIII7. H
}

II invcrsa unci matricc mpdoi opera tor

! () ;

II ncgativarca unci matricc mpdoi operator -(); II produsul unci matricc eu un numar mpdoi operator * (double a); II produsul unci rnatricc cu lin vector vb operator * (vb& vb2); II calculul double
;

dctcnninantului unci matricc operator -();

mpdoi vb linial; vb linia2; public: II constructor mpdoi(double cl1=0,double double e22=0);

Functiile rnembru :;;i supraincarcarea operatorilor se definesc intr-un fisier separat, de extcnsie cpp. Amintim ca inversa matricei de ordinul 2:
c12=0,double c21=0,

all al2 a21 a22 estc matricea: a22/d -a2l/d -a 12/d a l l/d

1*

funcui mcmbru circstc clcmcntclc unci matricc: rcturncaza: () -Ia intilnircu sfirsitului de fisicr; I - alttcl,

*1 inr. ci t.rru.do i (chaT 'text); i* afiscaza clcmcntc!c matricci curcntc folosind a f i smpdo i ();
Ull

format standard *1

uncle prin d s-a notat determinantul matricei initiale. in comentariile functiilor definite mai jos vorn folosi urrnatoarele notatii: r - matricea rczultat; mpdoi - matricea curenta, FI~IERUL BXXI1I9
STDIO_H #ifndef #include <stdio.h> #define STDIO_H Ifendif BXXIII'l CPP hfndef #inelude "BXXIII7.CPP" #define BXXIII'l_CPP #endif #ifndef _BXXIII9_H #inelude "BXXIII9.H" #define BXXIII9_H tl·endif I I constructor inline mpdoi: :mpdoi(double ell,double e12,double c2.1, doub 1e c 2. 2.) : 1 in ia 1 (e 11 , c 12) ,Ii n ia 2. (c 2 1 , c 2 2 )

i* afiscaza cicmcntclc mairicci curcntc folosind formatul format I pcntru linin unu si format? pcntru linia doi *1 void afismpdoi(char "format1, char "format2); // rcturncaza linia iruiiu a matricci vb tli nlt i : // rcturncaza linia a doua a matricci vb rc,(:lin2(); ilopcralori a doua matricc rnpdoi operator +

// SUI11Cl

(mpdoi& mpdoi2);

difcrcnta a doua matricc mpdoi operator (mpdoi& mpdoi2); ii produsul a doua matricc mpdoi o pora t o r (mpcioi&

rnpdoi2);

172

173

II functii mcmbru int. rnpdoi: : ci t.mpdo i (char *text) /* - afiscaza tcxtul sprc care poinrcaza paramctrul . citcstc clcmcntclc matricci curcntc; ~ rcturncazn: O· la intilnirca sfirsitului de fisicr; 1 . altfcl. *1

rnpdoi
{

rnpdoi:

:otx,rator

Impc1oi& mpcloi2)

Ilroolllpdlli·mpdoi2

mpdo i r t ernp : text; rternp.linial rtemp.linia2


return rtempi

Li.n.i a.l+mpdoi? .1inial; I. i n i.a z "mpdoi2 . lini.a2;

ifltext && strlen{text)) printfltext); ifllinial.eitvb{"\n prima 1inie\n") if(linia2.eitvb{"\n 1inia a doua\n")
}

rnpdoi
==

rnpdoi.: :operat.or rtemp;


=

* Idouble

a)

/Ir·cmpdoi*a

0 ) return == 0 ) return

0; 0;

rnpdoi

void rnpdoi: :afismpdoi() 1* afiscaza matricca curcnta folosind un format standard *1


{

rternp.linial rternp.linia2 return rtemp;

Li n i a Lva , linia2*a;

linial.afisvbl) linia2.afisvb();
}

vb rnpdoi:
(

: opera

tor

* (vb& vb2)

II r

mpcioi*vb2

vb rtempllinial*vb2,linia2*vb2); *forrnat2)
return rtempi

void mpdoi::afismpdoilehar *formatl,char 1* afiscaza matricea curenta folosinclformatclc: formatl - pcntru prima linic; fonnat2 " pentru linia a doua

rnpdoi
(

rnpdoi::

operat.or

* Irnpdoi& rnpdoi2)

II r 0= mpdoi+mpdoi?

*1
(

linial.afisvb(forrnat1) linia2.afisvblforrnat2)
}

; ;

II coloana intii a matricci mpdoi2 vb co11(mpdoi2.1inia1.retc11) II coloana a doua a matricci mpdoi2 vb co12 (rnpdo iz . 1ini211. ret.c2 II(rll,r21)=mpdoi *coll vb rvbl; rvbl = "this'coll; II (rI2,r22) vb rvb2; rvb2 = *this'co12;

,mpdoi2.1inia2

. .retcll));

I ) ,mpdoi2

. I inia2.

retc2

I)) ;

in1i.ne vb mpdoi: : retlin1 () II rcturneaza prima linic a matricci curcntc


(

return

linial;

inline vb rnpdoi: :ret.lin21) II rcrurncaza linia a doua a matricci curcntc


(

return

linia2;

Ilopcratori
rnpdoi
(

II matricca produs rnpdoi rtemp (rvbl . rete 1 I ) , rvb2 . rete rvbl.retc2(),rvb2.retc2()); return rternp; operator ,. (mpdoi& rnpdoi2) If r = mpdoi+mpdoi2 inline linia1+rnpdoi2.1inia1; linia2+rnpdoi2.1inia2;
}

1 () ,

rnpdoi:: rtemp;

rnpdoi

double

mpcio i ::operator-

() II calculcaza dctcrnunantul m.uricci curcntc

rternp.1inial rt.ernp.linia2 return rt.ernp;

return linia1.retcl()*linia2.retc2() linial.retc2()*linia2.retcll)

mpdo i rnpcloi:: op o r a t.or


(

- ()

II r = -rnpdoi

174

175

mpdoi

rtemp; -linial;

rtemp.linial rtemp. Linia2 r e t.u rn r t orup :

lldefine #endif #include


ma in

STDLIB_H "BXXIII9.CPP"

-lini.a2;

t) 1* - citcstc clcmcntclc

mpdoi mpdo i ::op e ra t o r ! () Ii rcturncaza invcrsa matricci curcntc double d = -* this; II calculcnza dcterminanrul matricci curcntc if (d I 0) ( rnpdoi rtemp(linia2.rete2()/d, -linial.rete2()/d, -1inia2. retel ()Id, Li.ni.a l .ret.cl()Id) ; return rtemp; printf("matricea are determinantul rnpdoi rternp; r o t urn r t ernp : II matricca nul a n~l\n");
=]

matricclor a si b; - calculcaza si afiscaza solutia sistcmului: ax b - calculcaza si afiscaza vcctorul rcziduu: r = ax b

rnpdoi a; vb b,x,r; char err]

"S-a tastat

EOF\n";

II citeste rnatrieea a if(a.citmpdoi("matricea printf (er) ; ox i. t (1) ;


dOLHI

a\n")

0)

23.1 0

S~l

dOLHI

sc scric un program necunoscute.

care rezolva

lin sistem de

ecuatii

liniarc eu

if (-a

== 0) ( // determinantul printf("determinantul exi t (1) ;

nul sistemului

este nu1\n");

Fie sistcrnul:

(I) ax
undc: a

c=

b
Estc - Este
0 0

matrice matrice

patratica coloana

de ordinul 2. de ordinul 2* I.

1/ citcste vcctorul b if(b.citvb("termenul p r i.n t.f (e ri : exit (1);

liber\n")

0)

Matrieea b corcspunde conccptului de vee tor bidimensional, implementat eu ajutorul clasei vb, definita in exercitiul Z'I.". Solutia sistcmului (1) cxista si este unica daca determinantul matricci a este difcrit de zero. Daca notam ell inva invcrsa matricci a, atunci solutia sisternului (I) se poatc exprima astfel: (2) x = inva*b Programul din acest exercitiu citeste elcmcntele matricelor a si b, calculcaza solutia x cu ajutorul relatiei (2) si afiscaza solutia respective. Apoi.sc determina vectorul rcziduu r ell ajutorul rclatici: (3) r = ax-b unde:
}

II calculcaza
X :::

!a

*bi

solutia sistcmului /1 x = inva*b

II afiscaza solutia sistcrnului x.afisvb("xl = %.15g\t /1 calculcaza vcctorul rcziduu r := a=x+b ,

x2

%. 15g\n" );

II afiscaza vcctorul rcziduu printf ("vectorul r ez i duu vn vl : r.afisvb("linial %.16g\t linia2

'1; .16g\n") ;

- Este solutia determinata In final, se afiseaza vectorul reziduu.

mai sus.

23.1. Supralncarcarea operatorilor new sl delete


In capitolul 20 s-a ararat ca_:::E~ra.:~<:lrii new;;i delc:t<:J~2!.fl_.l!.ti!j~.atLP_e}lt.~~ alocarca dinamica a datelor in melll0riilheap. Operatorulnew aloca, la executie, ~ datil in l11eiilor;-;l/;e~/p, Openi'torul delete dezaloca (distruge) 0 data care a fost
177

PROGRAMUL BXXI1I10
ffifnde #include STDLIB H <stdlib.h>

176

alocata, in prealabil, prin operatorul new. Acesti operatori pot fi utilizati atit pentru it gestiona date de tipuri prcdefinite cit si date de tip abstract, adica obiecte. Operatorul /Jew are ca operand numele tipului datei pentru care se aloca memorie: new nume tip Printr-o expresie de aceasta forma se aloca in memoria heap 0 zona de memorie necesara pentru a pastra 0 data de tip nume _tip. Rezultatul aplicarii operatorului new este adresa de inceput a zonei de memorie alocate. Aceasta adresa este un pointer spre tipul nume _tip. Exernple: I.
int *p

Amintim ca la distrugerea cbiectelor se apeleaza destructorul clasei (eel dcfinit de utilizator sal! ccl implicit daca Ill! cxista un astfcl de destructor). Operatorul new sc. poatcutiliza nu numai p~ntru a ..aloca mcmoric J1C}ltrt!_5_l Q~U\,_~Lilpentr!Jaini\ializa data rcsr~~ti\'~1. Exemple:
int *p
c;

new

int(lO);

in zona alocata in memoria heap sc pastrcaza valoarea lOde tip int, iar p pointeaza spre zona respectiva, 2.
class vb { double public: vb( )
(

cJ., c2;

Se aloca 0 zona de memorie necesara pentru a pastra 0 data de tip into Adresa de inceput a acestei zone reprezinta un pointer spre int si se atribuie lui p. 2.
double *q

new

inti

c1 c2 vb(double
{

0; 0; v1,double v1; v2; v2)

Se aloca 0 zona de memorie necesara pentru a pastra 0 data de tip double. Adresa de ineeput a acestei zone reprezinta un pointer spre double ~i se atribuie lui q. 3.
class vb ( double public: vb( )
{ };

new double;

c1 c2

c1,c2;

vb *pvb = new vb (1 ,2) ;,_,::.--.

c1 c2

0; 0;

In zona alocata in memoria heap se pastreaza un obiect care arc cornponentele: cl=l$ic2=2 in acest caz, se apeleaza in mod automat constructorul care are parametri si care realizeaza initializarea componentelor obiectului insrantiat. Pointerul pvb pointeaza spre obiectul instantiat in acest fel. Operatorii !!"?Yl!_5i di?letepemlitalocarea si respectiv dezalocarea deta?louri memoria heap. In acest caz, se utilizeaza constructii de felul celor de mal JOS.

};

vb *pvb = new vb;

7f

Se aloca zona de memorie pentru a pastra un obiect de tip vb. Adresa de ineeput a acestei zone reprezinta un pointer spre vb $i se atribuie lui pvb. La alocare, se automat constructorul

Qperatoruillew ".se poate aplica ..pentru tipurile suprainc,irc.?re gIobiIii. Aceasta suprai~carcareglobala
i!Tf!dejinitd.

estcnluTllt[lsia~cia;~ds;;u

abstracte

el ~lVind

In mod analog, operatorul 4c:lelf!..[\J:_~_(l_s_llprainc~\rcaregIobala ~i cl poatc fi utilizat pentru a dezaloca (distruge) datele pentru care s-a alocat rnemorie cu ajutorul lui new. Astfel, pentru a distruge datele alocate in exemplele de mai sus, nu avem decit sa utilizam expresiile: - delete p; pentru data alocata in exemplul 1; delete q; pentru data alocata in exemplul 2; - delete pvb; pentru obiectul alocat in exemplul 3.
178

Exemple:
int *p

new

int[lO];

Se aloca 0 zona de mcmoric capabila pentru a mcmora IOdate de tip in! (IO*sizcof{illt)). . Adresa de inceput a acestei zone sc atribuie lui p. l:.'~~lementelc resp_ectlve neputcm referi prin cxpresii de forma:
p[O], p[lJ, ,p[9J

sau
"p, *(p+1), ,*(p+9).

Zona respectiva

sc clibercaza

aplicind opcratorul

delete in mod obisnuit:

179

delete

p;

;i:
char[lOO];

Amintim
*t

ell in instructiunea:

2.

char

*q

= new

vb(i,i

Se rezerva 0 zona de mernorie de 100 de octeti si adresa de inceput respective sc atribuie lui if. Dczalocarea se realizcaza printr-o instructiunc de forma:
del(~te q;

a zonei

3.

class

vb ( double 1,c2; public: vb( ) (el = 0; c2

O;) y)

din partea dreapta defineste un?~i.~~~_::~:<::~~~ (fara nume). El ~~ princonstructorul c1asei vb,apoi obic:cl:tlU(':§P9_C.!i\,"§(.: ()QL':l.~l__iJ1_ __ e zOI~aspr_e_~'1~9-QQiI1t~itZ<i"0 1J1(i_~tlllari911iJri~~it_e_(_ji;'t[lJl'-'!lJtg}11~.L (, rezumat, operatorul new poate fi apelat pentru a rezerva memorie atit pentru date de tip uri predefinite, cit si pentru tipuri abstraete. Datele alocate in acest fel pot f initializate. _ Se pot aloca tablouri, dar in acest caz nu se mai pot face initializari. In cazul obiectelor trebuie sa precizam urrnatoarele:

cxpresia

initializeaza

----tn·

vb(double x,double (ei = x; e2 = y;)


};

1.
2.

Nu este obligatoriu sa existe constructor definit de programator. D;~a exista un constructor tara parametri definit de utilizator, atunci el se aplica automat Ia alocari prin expresii de forma:

new nume clasa


3. Daca se fac alocari cu initializare:

Sc rczerva zona de mcmorie pcntru 100 de obicctc dc tip vb. j n accst scop se utilizeaza supraincarcarea standard a operatorului new. In acest caz, se apelcaza constructorul implicit de 100 de ori. Adrcsa de inceput a zonei rczervatc pentru cdc 100 de clemente se atribuie

vb 'ptvb; ptvb = new vb[lOO);

new nume clasa(parl,par2, ... ,parn)


atunci clasa trcbuie sa aiba un constructor respcctiva. Daca se fac alocari de forma: care sa poata realiza initializarea

4.

pointerului

ptvb.
alocata in accst fcl se clibereaza

new nume clasa[nr elemente]


atunci se utilizeaza la
0

Zona de mernorie forma:


delete pLvb;

printr-o instructiune

de

new. Daca clasa are un constructor


se apeleaza

standard (predefinita) a operatorului implicit definit de programator, acesta astfel de alocare de nr_elemente ori. ajlltorllLoperat()fullli

supraincarcarea

La obiectele

alocatc mai sus ne putem rcferi prin constructii (--

de fOrl1J(l:

"ptvb, "(ptvb+ 1), ... , *(ptvb+99).

.4(;le_£~.In
unde: p

Obiectele alocate cu .ajutorul lui new sc di~trllg_gu aeest~cop seutilizeazilo;;:;-sti~ictiune de forma:


delete p;

La alocarca tablourilor cu ajutorul operatorului new nu se pot face initializari. De exernplu, daca sc dorcste intializarea elcmentclor tabloului de mai
sus in asa fel incit elementul: *(ptvb+i) sa aiba valoarea initiala (i.i), se poate apela definita ca mai jos.
void vb: :initab(int
{

- Este un pointer

spre obiectul

care se distruge. atunci instructiunea de

Daca clasa arc un destructor definit de programator, mai sus implica apclul destructorului respectiv.
0

functic membru

sau pricten

a clasei,

Obiectele tablou,alocatC:l'E~11_tr-()_~:x.presiect.cforl11a:
p = new Ilume_clasa[nr_elemente]

n)

vb *t; t = this;
for (i
}

0;

i < n; i + +

t + +)

*t

sau
vb (i ,i) ;

Pentru a initializa
ptvb

tabloul de mai sus, vorn apela functia membru

astfel:

.> .i ni tab t IOu j :

Prima .instructiunc . . ... in mod. automat destructorul clas~iG:ii!j~a ~l'<lt~\~ sprc ·c.leoscbirc - de -eea-de a--dol.la:-c-a~~-dist~:g~=~~~0~f· apelil1(L_de

180

181

C;~~fc;mc~te! ori destructorul clasei. . =Utiliza·t~nilpoatesupri'iliicarcii acesti operatori in cazul in care supraincarcarea standard nu este suficienta, Supraincarcarea operatorilor new ~i delete prezinta uncle diferente fata de supraincarcarea celorlalti operatori. o prima diferenta consta in aceea ca, SllF.~<lj11CarCarcaoperatorilor neH'...i'.i d c le te_sc.rc(ll i!~a~Lc::tlajtltoruUilflC;Iii!ol: 111e!1!!J!_u~:tatice,·spt:e-deosd;lre de cellalti operatori care se supraincarca prin functii memb;:i.i 'care nu sint statice sau prin functii prieten. Functiile care supraincarca operatorii new ~i delete sint asirnilate.in mod implicit, ca functii membru statice, asa ca nu mai este nevoie sa specificam explicit acest lucru. o alta particularitate a supraincarcarii accstor operatori este <l.1}tGtuLf1!!1ftiiJQL prin <':<lr~t>ele<lliz('!~zasl!PI"lm:;.~H:cllrea .. Pentruoperatoml new se utilizeaza urmatorul prototip:

constructori, De aceea, la aplicarea operatorului neH', pot sa fie pre7:~21ti paramctri pentru constructorii clasei. In general, operatorulnew se aplica la un operand folosind urrnatorul format: new Ill/me_clasa(par / ,par2, ...,parn) unde: parl.pari, ....parn - Sin! expresii ~i reprezinta constructor al clasei: Illlttl.C _ clasa. paramcrri pentru apelul unui

·L.Y()i.d.*~pera to.!_.f!~:~~.(S_iz_e.=cJlll~.g); .... \

Functia returneaza un pointer universal a carui valoare este adresa de inceput a zonei de mernorie rezervata in memoria heap. Tipul size _t este definit in fisierele de biblioteca stddef.h ~i stdlib.h astfel: typedef unsigned size .t. Tipul size _t trebuie sa fie prezent in antetul functiilor pentru supraincarcarea operatorului ncw (el desi este un alt nume pentru unsigned, nu poate fi inlocui prin unsignedi. Antetul functiei pentru supraincarcarea operatorului new este de forma: void *nume_clasa::operator new(size_t lung)
t

~_l:ll~:ainca_r~areapredefinita(globala) a operatorului cazuLJI1.~~r.e __ac~sta este supraincarcat de utilizator, r:('!zOl~lti~,Astfel, 0 expresie de forma: ::new nume clasa ..?--aplica operatorul new predefinit, ca re, asa cum s-a supraincarcare standard, globala. Pentru ,operatoruJ delete, de asemenea exista Prototipul functiei pentru supraincarcarea opcratorului astfel: void OP~C9!~~'~~Ie.te(\,oid*p);J
!

new poate fi apelata si in folosind operatorul de

a finnat mai sus, are 0 irmat particularitati specifice. delete se poatc specifica

Ca si in cazul operatorului new, functia pentru supraincarcarca este in mod implicit 0 functie membru staticd. Antetul functiei este de forma: ---

operatorului

l.".Oi~ 111/:1!~=~~(I~~(I::()perat()r~el~!e (void*p)

Operatorul are ea operand l_!!.!.p_oillterspre obiectul care se dezaloca, Valoarea acestui pointer trebuie sa fie eea def'ii1ita' prin aplicarea operatorului new la construirea obiectului. Exemplu:
nume __ clasa
*p

Parametrullung areca valoare dimensiunea in ()c_t<:ti_~'lzon.<:i_cle.f!1:<:I11orie.~are ~(:xe!(!1:ya.ill.n1~J!l()£\_~~~l?ap.. .. ... . . . .. - . o alta partieularitate a supraincarcarii operatorului new este faptul ca la ~pl~(;_~!.(!nuiuu sei11.dica nici 0 valoare pentruparametrul I forJ11al lung,j.._ceasta, d..5:2.<lr(!c(!_c()mpilatorlilcalculeaza, .. in..... m()ci.~~!1t.9IJ1.llt.>._.dimemitlnGa_.Cl.bi(!(!_tului Qentru Gan.~ se. rezerva zona de. memorie si aceasta dimensiune. se atribuie pj;~~~rtllu-i~h;'.;i~ --- .... .... . ...----,.--- ..- ----.- ----- -- - -.. -In felul acesta, operatorulnew expresii de forma: new nume clasa unde: nume clasa - Este numele clasei pentru care este supraincarcat, supraincarcat se utilizeaza in mod obisnuit in

= new nume_clasa; alocata sc atribuic lui P */

/* - sc aloca zona de mcrnorie pcntru un obicct de tip numcclasa;


- adrcsa de inccput a zonei de mernoric delete
p;

/* sc clibcrcaza zona de mcmoric alocata prin new */

La apliearea operatorului delete sc apeleaza in mod automat destructorul clasei daca ~xista un de~tructor defi~it de utilizator. In eaz contrar, se apeleaza destructoruJ implicit definit de cornpilator, Ca ~~ in cazul operatorului new, daca operatorul delete a fost supraincarcat pentru tlpu.l abstract nume jclasa, atunci ~E~~~toruldeletepredefinit (global) E.~t.e!i:_aphcat precedindu-l de operatorul de rezoluiie"" .. .. ::delete numejclasa; Operatorii
!1C1V

Aplicarea _()p<:ratomllii new .supraineareat.cieutilizator_apeleazci in mod automat construetorul corespuilzator .clasei, daca exista c0l1s·ttl:lctorr-aefjl11ti pentmclasa respectiva sau pc eel implicit definit de compilator daca clasa nu are 182

~idelete supraincarcati

de utilizator

nu se folosesc la aJocarea 183

si dezalocarca

'-ll1~;;~lII(;I~lC'I;·ii ~idistrllgei:ii

tablourilor

de obiecte. ' tablourilor

de obicctc

sc utili~c.(llCiloper,~t~l:ii

new ~i delete standard (globaliL . -Opel'atorii /lew si delete definiti de utilizator au un avantaj fata de cei standard si anume ei sint mai cconornici din punct de vcdcre al timpului de cxecutie si al
memoriei consumate pentru gestiunea obiectclor dinamicc, In corpul functiilor pentru definirea supraincarcarii operatorilor new si delete se pot utiliza vcrsiunile standard pentru accsti operatori. in incheierc amintim ca, functia pentru supraincarcarca operatorului delete are un al doilea pararnetru facultativ, de tip size _t,care este gestio nat automat de compilator. El nu este obligatoriu sa apara in antetul functiei pentru supraincarcarea operatorului delete. Antetul general al functici pentru supraincarcarea operatorului
"_'

Declaratia a treia este analoga eu a doua, deosebirea consta in aceea ca, in accst caz, sc aloca 1OO*sizeof( double) octet: in loc de 100 deocteti. La declaratia a patra se aloca zona pentru un obiect de tip nume clasa. La alocare se apcleaza eonstructorul implicit al clasei, definit d; utilizato;· . Alocarea sc face apelindu-se operatorulnew supraincarcat de utilizator. Adresa de ineeput a zonei de mernorie alocata in acest fel se atribuie lui

pnume.
Zona respcctiva de utilizator:
delete pnume;

sc elibereaza

aplicind

operatorul

delete supraincarcat

definit

--.'~ .

delete este urrnatorul: *p,si~<!=tung) l

void nume _elasa: :operalg..':<lt:let~(void Exemplu:

Fie clasa de mai jos, pentru care s-au supraincarcat operatorii

new ~i delete:
sau

Aceasta instructiune apeleaza destructorul clasei, La ultima declaratie se aloca zona pentru 100 de clemente de tip nume _clasa. S~(lpeleaza operatorul new standard. < Adresa de inceput a zonei rezervate se atribuie pointerului tnume. La alocare se apelcaza constructorul implicit de 0 suta de ori. Zona respectiva se elibereaza aplicind operatorul delete standard:
delete[lOO] tnume;

class nume _.clasa ( public: I1wne_ elasaO; void * operator new(size _t); void operator deiete(void *); =nume _elasaO; }; Consideram urmatoarele declaratii:
l.
char char *pcar *tc new char; new char [100] ; new double[100];

delete

tnume;

In primul caz, se apeleaza destructorul destructorul se apeleaza 0 singura data.

de

sura de ori. In eel de al doilea caz,

Exercitii: 23.11 Sa se defineasca tipul abstract tnod care are urmatoarele date mernbru: - cuvint: pointer spre un sir de caractere; - frecv: intreg utilizat ca numarator de cuvinte; - urm: pointer spre tnod; - ind: indicator pentru citirea sfirsitului de fisier,
Clasa care implementeaza tipul abstract tnod are realizeaza urmatoarele: - constructor; destructor; afiseaza datele membru cuvint si frecv; - retumeaza valoarea lui ind; - supraincarca operatorii new si delete; - operatorul pentru incrementarea numaratoruluij-ecv, Clasa slist este clasa prieten pentru clasa tnod. functii membru care

2. 3.
4.

doublektd

5.

nume clasa "pnume = new nume _clasa; nume clasa "tnume = new nwne_elasa[lOOJ; In cazul primei declaratii se aplicd operatorul new standard.
lui pear.

Se rezerva zona pentru un caracter (un octet) ~i adresa ei se atribuie Accasta zona se clibereaza aplicind operatorul delete standard:
delett:! pear;

La declaratia a doua se aplica operatorulnew standard pentru a aloca 0 zona de 100 de octeti, Adresa de inceput a acestei zone se atribuie lui tc, Zona respective se clibereaza aplicind operatorul delete standard:
do l e te tc;

184

185

FI~IERUL BXXIII11.H
STDLIB_H #ifndef #include <stdlib.h> #def ine __ STDLIB_H #endif Boolean #ifndef Boolean #define enum Boolean {false,true};

pastrcaza euvintul eitit in memoria - rcalizcaza initializarile: frccv I; urm=O.

heap;

*1
(

char t[255]; int sf; 0; cuvint if(tnod: :ind false) { while ((sf ~ scanf ("%s", t)) ! ooEOF)( char *p = t; int c; II salt peste caractcrc care nu sin! litcrc while( (c oo* p)&& (c < 'A' II c <'a' II c> 'z')) p++; II nu sint litcre if(c oo= 0) continue; II pastreaza inccputul char *q = p; cuvintului

#endit class tnod char *cuvint; int frecv; tnod *urm; static Boolean ind; friend class slist; public: tnod() ; -tnod() ; void afistnod(); void *operator new(size_t); void operator delete (void *); void operator++(); static Boolean retind();

c>

'Z'

&&

};

II caura sfirsitul cuvintului while( (C=kp)&&(C >oo 'A'&&c <= c >oo 'a'&&c <oo 'z'))
P++i

'z'll
cuvintului

Functiile membru ale clasei (nod se definesc in fisierul de extensie CPP, de mai jos. Indicatorul ind are valoareaflllse atit timp cit nu s-a intilnit sfirsitul de fisier. FI~IERUL BXXIII11
STDIO_H #ifndef #include <stdio.h> #define STDIO_H #endif #ifndef S1'RING_H #include <string.h> lfdefine _STIUNG_H #endif BXXIIIll_H #ifndef #include "BXXIIIll. H" #define BXXIIIll H #endif II Initializarca Boolean variabilei ind false;

*p =

'\ 0 ';

II caracrerul

NUL In sfirsitul heap

II rezerva zona pcntru cuvint in memoria II sc apclcaza opcratorul new standard

printf("tnod: :tnod %lu\n",coreleft()); if I (cuvint = new char[strlen(q)+l]) == 0) ( printf("memorie insuficienta\n"); exi t (1) ; printf ("tnod: :tnod %lu\n", coreleft ()) ; II sc transfcra cuvintul in zona rczcrvata strcpylcuvint,q) ; II intializari frecv = 1; urm = 0; II pointerul nul break; II sfirsit while if (s f == EOF) tnod::ind false; } II sfirsit constructor II s-a inrilnit EOF = true;

tnod:: ind

tnod: :tnod()

1* - citcstc cuvintul eurcnt daca ind

186

187

inline
(

tnod: :-tnodl)

Pcntru

Sl' <lpCIc<l/Oi opcr.uorul delete standard printfl"\ndestru~ tnod %lu\n",coreleftl)); delete cuvint; p rin t f tvvndes t ruc to r tnod %lu\n",coreleftl));

/1

ultim care sin! pointcri

.in I i flf_' vo id Lnod::

f i s r.riod ()

II afiscaza

cuvintul si Irccvcnta

print£("cuvintu]=%s\t

are

frecveTlta=%d\n",cuvint,frecv);

void tnod

*tncld:

:opera

nE'WI sizE,_.tlung) II supraincarcarca

opcraiorului

new

*p;

II sc aplica opcratorul new standard printfl" operator new lu\n",coreleftl)); p=ltnod ")new char[lung]; printfl" operator new %lu\n",coreleft{));
ro tu r n p;

listelor simplu inlantuitc s-au folosit dOU[1 variabile prim si sprc primul si respcctiv ultimul nod al listei. Accstc valori se vor utiliza si in cazul de lata cu acelasi scop. Elc sint datc mcrnbru protejatc ale tipului abstract slist. Avantajul implernentarii tipului abstract slist estc acela ca, se pot dcfini simultan ~i simplu oricite obiecte de tip lista, Functiile mcmbru ale tipului abstract slist sint: constructor implicit; destructor; adaugarca unui nod dupa ultimul nod al listci; inscrarea unui nod inaintea prirnului nod allistci; stergcrca primului nod allistci; stcrgerca ultimului nod al!istei; cautarca in lista a unui nod; afisarea datelor aflate in nodurile listci. Nodurilc !istei sint obiecte de tip [nod, tip definit in exercitiul 23.11. gestiunea

FI~IERUL BXXIII12.H
opcratorului delete #ifndef BXXlllll H #include 'BXXIIIll.CPP" #define __ BXXIIIll_H #ondif class slist tnod *prim; tnod ·'ulLim; public: slist I) ; II constructor -slist (); II destructor tnod * adauga (tnod *); II adaugn un nod dupa eel spre care pointeaza ultim tnod *inseroaza (tnod *p); /1 insereaza un nod inaintea celui sprc care 1/ pointcaza prim void sprim I); // sterge primul nod din lista void s u Ltim I); /1 sterge ultirnul nod al listci tnod *cautaltnod *p); /* - cauta nodul din Jista pcntru care p -> cuvint pointcaza sprc un sir identic cu eel sprc care poinleaza cuvint din nod; rcturncaza pointeruJ sprc nodul rcspectiv sau zero daca nu cxista un astfcl de nod */ void
};

void

tnoel::opera

do Ie te I vo id *p) /1 supraincarcarca

Ii sc aplica opcratorul delete standard printfl" operator delete %lu\n",coreleftl)); ::delete p; p ri.n: fl" opora t or delol.c 's l.u vi c ore le Ltt l) : vn
)

void
(

tnod:: opera tor+ + I)

II incrcmcntcaza

frccv

frecv++;

Boolean return

tnod: :r e tind I) Lnod: :ind;

/1 rcturncaza valoarca

ind

Observatie: Functia core/elf rctumcaza dimensiunea, in octeti, a mcmorici libere in momcntu\ apclului. Ea a Iost apclata in mai multo functii pcntru a putca urmari momcntelein care sc aloca si dezaloca obicctele care sint instantieri ale clasei tnod. 23.12 Sci se dcfincasca inlantuitc. simplu tipul abstract slist pcntru au fosr implcrncntatc irnplementarca in limbajul listci simplu II.

afislist I);

II atiscaza date Ie din uodurile

listci

Functiile membru ale clasei slist se definesc in fisierul de cxtensic mai jos. FI~IERUL BXXIII12
#ifnc1ef #include BXXIII12_H 'BXXIII12.H'

CPP, de

Listclc 188

inlautuitc

C in capiiolul

189

#define #endif inline prim

_BXXIII12_H

// P - pointcaza prim; p

sprc nodul curcnt

slist: :slist() ~ ultim = 0;

/1 constructor

1
slist: :-slist ()
(

II pi - pointcaza sprc nodul precedent pI 0; while(p !~ ultim) Ilparcurgelista pI ~ p; P ~ P -> urm; toatc nodurilc listci // P - pointcaza sprc ultirnul nod; /1 pi - pointcaza sprc nodul precedent if (p I =~ 0) ( II lista nrc un singur nod si devine vida delete p; II se apliea operatorul supraincarcat prim = ultim = 0; return;

II destructor; distrugc

tnod

*p, *q;

for(p=prim;p;p=q) ( q=p->urm; II pointer spre nodul urrnator delete p; II operarorul delete supraincarcat prim
)

~ ultim

b;

tnod
(

*s I is t ::adauga (tnod *p) 1/ adauga un nod dupa ultimul nod allistci

1/ nodul sprc care pointcaza pl -> urm = 0; ultim pl;

p I devine ultimul nod allistci

if(prim ~oo 0) Illistavida prim p; else ultim -> urm = p; ultim = p; return p;

/1 sc stcrgc nodul sprc care pointcaza p


delete p; II se aplica operatorul supraincarcat lelse printf("lista vida\n");

tnod *slist: :insereaza(tnod'p) /1 inscrcaza un nod inaintca celui sprc care pointcaza prim
(

tnod *slist: :cauta(tnod *p) /* " cauta nodul pcntru care cuvint pointcaza sprc un sir identic cu eel sprc care pointcaza p -> cuvint: _ rcturncaza pointcrul spre nodul rcspcctiv sau 0 daca IlU cxista un astfcl de nod. */ tnod *q;

if (pr i.m=e O) II lista vida ultim p; else p -> urm prim; prim = p; return p;

for(q=prim;q;q=q->urm) if(stricmp( P -> cuvint, return 0; J

q -> cuvint)

0) return

q;

vo id s1 is t ::spr im ()

II stergc primul nod din lista

if (prim) ( tnod *p prim -> urm; delete prim; lIse aplica operatorul delete supraincarcat prim = p; 0; II lista a devenit vida if(prim == 0) ultim lelse printf("lista vida\n");

void slist: :afislist() /* - afiscaza pcntru ficcarc nod:

- cuvint
si - frccv. */
(

int nrlin

= 1; p -> urm) {

void

s 1 ist ::s u L t im ()

1/ stcrgc ultimul nod allistci

if (prim) { tnod *p, *pl;

for(tnod 'p = prim; p; p p -> afistnod(); nrlin++; if(nrlin%23==0) ( printf("Actionati

tasta

pentru

a continua\n");

190

191

(jetch ();

23.2. Supralncarcarea operatorului


in limbajul c++ se pot face atribuiri acclecasi clasc, Exemplu: Fie instantierile: nume _ clasa obiect 1,obiect2; de obiectc

=
ale

care sint instantieri

23.13

Sa sc scrie un program care citestc un text si afiscaza frccvcuta de .aparitic a ficcarui cuvint din text. Nu se face distinctie mtre literele man ~l rmci. problema a fest rczolvata 11 se da in mai multo
0

Accasta

moduri folosind

in capitolele listelc simplu

prcccdcntc in particular,
inlantuite.

in capitolul

rezolvare

Prograrnul de fata utilizcaza aceeasi metoda. BXXIJI13


<alloc.h>
CONIO_H

o atribuire de forma:
obiect2 = obiect 1; este acceptata de cornpilator. La atribuirea de obiecte, in mod implicit, se atribuie datele mernbru ale obicctului din dreapta operatorului = la datcle mernbru corespunzatoare ale obiectului din stinga aceluiasi operator. Astfcl de atribuiri se pot utiliza si in dcclaratii. Exemplu:

PROGRAMUL
#include #ifndef .include #def.i ne #endi f #include

<conio.h>
,CONIO_H "BXXIII12.CPP"

main () 1* citcsic un text si aliseaza s lLs t, lista; tnod *nod,*p;


pr

Irccvcnta

cuvinlclor

cititc *1

class

complex double real; double imag; public: complex(double


{

x=O,double

y=O)

[( "~,]u\n",coreleft: ()); while(tnod: :retind() =.~ false) II nu s-a ajuns la stirsitullcxtului


{

real imag new slipraincarcal

x'
y;

nod

c:

new

tnod;

II se aplica opcratorul

II cauta nodul in lista if(tnod: :retind()==false) if(p = lista.cauta(nod)){ II cuvintul cxista deja in lista (*p) + + ; II incrcl11enteaza frecv de 1e t e nod; II scapl ica operatorul

};

complex complex complex delete xupraincarcut z2

z (1, 2); zl = z; 22;

/lz=J+2i IlzJ=I+2i

Jelse lista.adauga(nod) ; 1* nodul spre care pointeaza nod coniine un cuvint ncgasit in lista; sc adauga la lista *1 else delete nod; printf("pentru a continua
getch{) ;

zl;

Ilz2=J+2i

actionati

tasta\n");

II sfirsit while II listcaza nodurilc listci Li.s ta . afislist () ;

Atit in cazul dcclaratiei lui zl , cit si in cazul instructiunii de atribuire pentru z2, se copiaza componentele date ale obiectului complex din dreapta caracterului "=" in zona de memorie alocata componentelor date ale obiectului aflat in stinga aceluiasi caracter. In cazul declaratiei lui z 1, caracterul "=" se utilizeaza pentru a realiza 0 initializarc, iar in cazul instructiunii:
z2

z1;
0

acelasi caracter se utilizeaza pentru a realiza

atribuire. 193

192

Ambele operatii sint definite in mod implicit si se realizeaza asa cum s-a indicat mai sus, adica prin simpla copiere a date lor membru. B. Stroustrup numeste "bitwise copy" (copiere la nivel de biti) eopierile de acest fel. In cazul obieetelor clasei complex, eopierea din cadrul operatiei de initializare este identica cu cea utilizata in cadrul operatiei de atribuire. In general, cele doua operatii nu sint identice. De asemenea, eopierea de tip "bitwise copy" nu este totdeauna suficicnta. Acest fapt rezulta imediat daca reluam exemplul pentru implementarea tipului abstract string (vezi 22.9) sau sir (vezi exercitiul 22.12.). Consideram clasa sir, definita ca mai jos:
class sir ( char *psir; int lung;

Utilizatorul (2)

foloseste

astfel de declaratie pentru a obtine acelasi efect ca si


un C mai bun");

cind ar utiliza dcclaraiia:


sir sir2 ("C++ este

In realitate, cele doua declaratii nu realizeaza acelasi lucru. In cazul dcclaratiei (I), la instantierea lui sir2 se apeleaza constructorul:
sir(int nrcar

70)

public: sir{char *s); 70) ; sir{int nrcar int retlung () ; II returneaza iungimca siruiui void afsir(); /I afiscaza sind definit de psir int citsir(); /I citeste un sir de caractere =s i.r () (delete psir;}
};

Functiile membru de mai sus, sint definite in exercitiul Fie declaratia:


sir sirl ("C++ este un C mai bun");

22.12.

care rezerva 0 zona de memorie de 70 de octeti in care se pastreaza sirul vid. Adrcsa de inceput a acestei zone se atribuie lui sirl.psir, apoi se copiaza bit cu bit (bitwise copy) valorile componentelor obiectului sir} (sir I.psir si sir 1.lullg) in zonele de memorie alocate cornponentelor corespunzatoare ale obiectului sir2. in fclul acesta, sir2.psir are aceeasi valoare ca si sirl.psir. Zona de memorie de 70 de octeti alocata in memoria heap este pierduta si nu se mai poate face acces la ea. De asemenca, textul de initializarc este pastrat intr-un singur exemplar, situatie care, de obicei, va conduce la erori in prelucrarea ulterioara a obicctclor sir I t'i sir2. De asemenea, la distrugerea obieetclor sir 1 si sir2 ar urrna ca textul de initializare, pastrat intr-un singur exemplar, sa fie eliberat din memoria heap de doua ori. De aceea, copierea implicita bit cu bit a obiectelor nu cste 0 solurie corecta pentru obiectelc clasci sir. Instantierea lui sir2 eu ajutorul declaratiei (2) nu are nici 0 legatura CLl instantierea lui sirl ~i se rezerva 0 zona de memorie in memoria heap distincta fata de cca rezervata pentru acelasi text la instantierca lui sir I. De aceea,
sirl.psir

La instantierea obiectului sir 1 se apeleaza constructorul:


sir (char *s) sir2.psir

Acesta rezerva zona de rnemoriein memoria heap pentru textul: C++ este un C mai bun si atribuie adresa de inceput a acestei zone pointerului:
sirl.psir

au valori diferite. Acelasi lucru este valabil si in cazul atribuirilor,


sir sirl("C++ sir sir2; este un C mai bun");

Fie de exernplu instantierile:

Atribuirea: se atribuie datei membru:


sir2

De asemenea,
sirl.lung

sirl;

valoarea 21 (numarul

de caractere din cornpunerea textului de initializare a obiectului sirl, fara a considers si caracterul NUL). Sa consideram declaratia pentru instantierea obiectului sir2 cu initializarea acestuia folosind obiectul sir l : (I)
sir sir2

sirl;

realizeaza 0 copiere bit cu bit, deci sir l.psir ~i sir l.psir devin egale ~i pointeaza spre aceeasi zona de memorie din memoria heap care a fost rezervata la instantierea lui sir 1. Ca si in cazul declaratiei (2), zona de memorie din memoria heap alocata la instantierea lui sir2 este pierduta in Ul111aatribuirii, deoarece ea devine inaccesibila, Din cele de mai sus, rezulta ca pentru obiectele care sint instantieri ale c1asei sir nu este suficienta copierea implicita bit cu bit. In astfel de cazuri este nevoie ca utilizatorul sa defineasca copieri specifice, care sa tina scama de natura 195

194

componcntclor in general,

obicctelor.

opcratia

de initializarc

prin copicrc

difcra de cca de arribuirc,

deoarcce initializarca de copicri, una care

cste insotita de alocare. De accca, sint nccesarc doua tipuri S,\ se reali~eze la initializarc prin copicrc, adica la dcclaratii

de forma:
(3)numc_clasa obiect2

obiectl;

~i una pcntru atribuiri de obicctc:


(4)obi(0ct = obiect1;

Initializarca prin copierc se rcalizcaza care a fost definit in paragrafuI22.8.


Un astfel de constructor nume __ cfasa(colIsl arc un prototip numeciasa

cu ajutorul de forma:

constructorului de copiere

cornponente pointeri spre date din memoria heap, este ncccsar sa avern constructor de copiere in clasa respective. Acosta se va apela automat atit la transferul prin parametri a obiectclor, cit si in cazul in care functia returneaza un obiect. in absente constructorului de copierc, transferul prin pararnetri a obiectelor precum si return area de obiecte, se realizeaza aplicindu-se copierea implicita, adica copierea bit cu bit. Un exernplu in care se utilizeaza copicrea bit cu bit, la returnarea de obiecte, este clasa complex, implemcntata in excrcitiul 22.1. in legatura cu supraincarcarea operatorului de atribuire este necesar sa amintim urmatoarele: • supraincarcarea operatorului de atribuire functie membru care nu este statica; se poate realiza numai printr-o

& obicctv.


obiectclc
obiectul

operatorului
din

se pot transfcra prin valoare sau rcferinta;


de atribuire, daca are componente

Mentionam ca, un astfcl de constructor se apclcaza automat la instantierea unui obiect printr-o declaratie de forma (3). Copierea bit cu bit sc rcalizeaza numai daca clasa nu arc un astfel de constructor. Clasa sir, definita in exercitiul
sir& s)

sting a operatorului

pointeri spre zone alocate in memoria heap, trebuiesc eli berate inainte de
a se aloca zone noi in obiectului din dreapta ca obiectul din stinga de a sc atribui valorile vedcrca copierii elernentelor corespunzatoare ale operatorului respectiv; se obisnuieste sa se spuna operatorului de atribuire trebuie "curatat'' inainte obiectului din dreapta operatorului de atribuire.

22.12., arc un constructor

de copiere

dcfinit ca

mai jos:
sir: :sir(const lung s .Luriq :

II sc copiaza lungirnca sirului

II sc aloca zona pcntru sir psir new chnrllung+1J; II sc copiaza simi in zona rczcrvata strcpylpsir, s.psir); I

De obicei, functia pentru supraincarcarca operatorului de atribuire arc un pararnetru de tip referinta si returncaza 0 referinta la obiectul curent. Aceasta dcoarece transferul prin referinta este mai eficient decit transferul obiectelor, Avind in vedere acest fapt, se recornanda urmatorul antet pentru supraincarcarea operatorului de atribuire:

mane _clasa& nume _clasa: .operator

(const Ilume_clasa & operand _drept)


atribuirilor de forma:

Acest constructor se va apela automat la intilnirca declaratiei (1) ~i rezultatul lui consta in aceca C,I declaratia (I) are acelasi efcct ca si declaratia (2). Constructorul de copiere nu se apelcaza la atribuiri. Pcntru a solutiona in mod eoreet atribuirilc de obiccte de fclul celor de mai sus, estc ncccsar 'sa supraincarcam in mod corespunzator operatorul de atribuire

o astfel
obiect2
uncle:

Obiectul

curent este operandul sting al atribuirii. de functie se apeleaza automat pentru realizarea
=

obiect 1;
ale clasei numeclasa.

obiectl si obiect2 - Sint instantieri


Atribuirile
obiectl

(=).
In principiu, constructorii de copiere si supraincarcarca operatorului de atribuirc sint nccesari pcntru clasele care au ca date mernbru pointed sprc zone alocate in memoria heap (alocate dinamic). Un alt caz in care este nevoie de copierea obiectelor este acela cind sc apeleaza functii care au ca parametri obieete sau care returncaza obiecte, In asrfcl de cazuri se aloes obiecte temporare pc stiva si de aceea intervin operatii similare cu cele de la initializare. Pentru ca acestc trnnsfcruri de obiecte sil se fuca corcct pentru obiccte cu

de forma:
obiectl;

nu au nici un efect, De aceea, atribuirile de acest fel se vor elimina, In acest scop, in corpul functiei pcntru supraincarcarea operatorului de atribuire se testeaza daca operatorul eurent este diferit de eel referit prin parametru si nurnai in acest caz se executa corpul functiei, Folosind antetul de mai sus, un astfel de test se poate realiza astfel:
if(this
!=

&operand_drept)

1/ opcranzi difcriti

196

197

}else return

/1 opcranzi
*this;

identici

Operatorul de atribuire are si 0 alta forma care se utilizeaza pentru a face prescurtari. Este yorba de formatul: op= unde: op - Este un operator binar aritmetic sau logic pe biti.

=s i r (); II destructor int retlung (); II returneaza lungimca sirului void afsir () ; II afiseaza simi int citsir(); II citeste un sir de caructere sir& operator (const sir&); Iislipraincarca= sir operator+ (sir&); 1* rerurncaza un obiecr de tip sir obtinut prin concatcnarea paramctrului la sfirsitul obicctului curent *1 sir& operator += (sir&); I*concateneazapararnetrullasfirsitul obicctului curcnl *1

Aceste variante pot fi si ele supraincarcate in mod corespunzator. Mentionam ca, daca operatorii op si = sint supraincarcati, nu decurge ca este supraincarcat si operatoruJ op=. Acesta trebuie supraincarcat separat in mod corespunzator. Operatorul op= se supraincarca folosind functii mernbru nestatice care au un prototip similar cu functiile pentru supraincarcarea operatorului de atribuire. Exercltii: 23.14 Sa se implementeze tipul abstract sir pentru instantierea sirurilor de caractere.

i.

Fisierul de mai jos este de extensie .cpp membru.

~l

el contine definitiile

functiilor

FI~IERUL BXXIII14
#ifndef #include #define # end if #ifndef #include #define #endif #ifndef #include #define lIendif sir: __ STDIO H <stdio.h> STDIO_H

Tipul sir a fost definit in exercitiul 22.12. in exercitiul de fata, se schimba functia membru atribsir a clasei sir cu functia care supraincarca operatorul de atribuire. in plus, se supraincarca operatorii + si += pentru concatenarea sirurilor de caractere. Expresia:
sirl

STRING_H <string.h> STRING_H SIR_H "BXXIII14.H" SIR_H

sir2+sir3

este legala pentru obiectele clasei sir si ea atribuie lui sir 1, sirul obtinut prin concatenarea lui sir3 la sfirsitul lui sir2. Expresia:
sirl += sir2

1* constructor

:sir(char *8) utilizat la inirializarca obicctului eu pointcrul in memoria heap a sirului sprc care pointcaza s *1

sprc copia

lung = strlen (s); Illllngirneasirului ps ir=new char [lung+l J; II rezerva zona in memoria strcpy (ps ir, s); II transfera simi in memoria heap
}

heap

este legals pentru obiectele clasei sir si ea are ca efect concatenarea lui sir2 la sfirsitul lui sir 1.

FI~IERUL BXXI1I14.H
class sir { char *psir; int lung; public: sir (char *s);

sir: :sir(int dim) /* - constructor utilizat pcntru a rczcrva in memoria - pastreaza sind vid in zona rcspcctiva. *1 lung = dim; II pastreaza lungimea ps i r = new char [1uno+ 1 J; II rczerva *psir = '\0';

heap

zona de dim+ I octcii;

zona

pentru initializarea obiectului cu pointerul spre copia in memoria heap a sirului spre care pointeaza s *1 sir (int nrcar=70); 1* constructor care rczerva zona de mernorie in memoria heap si pastrcaza in ca sirul vid *1 sir ( const sir&); 1* constructorde copiere *1

1* constructor

sir:
(

:sir(const

sir&

s)

II constructor de copicrc

1ung c; s. 1uriq : II pastreaza lungimea sirului psir = new char[lung+l); II rczcrvazona strcpy(psir,s.psir); Ilcopiazasirlil

198

199