laborator 2 - incapsularea · 2017. 12. 25. · laborator 6 – redefinirea ... trebuie declarate...

13
Programare Orientată pe Obiecte - 1 - Laborator 6 – Redefinirea operatorilor Tema 6.1 Analizaţi programul din fişierele EX6.CPP, EX6.H, CLASE.CPP, CLASE.H Consideraţii teoretice 6.1 Pentru inserarea unui element într-o poziţie oarecare într-un vector completat parţial există următoarele posibilităţi: 0 1 2 3 4 5 6 7 8 A B C D E F A B C nou D E G F G V V Mutare element cu element. Pentru exemplul din figură avem 7 poziţii completate şi dorim să inserăm în poziţia de indice 3. Codul ar putea fi: for(k=6;k>=3;k--) v[k+1]=v[k]; v[3]=nou; Pentru a evita suprascrierea accidentală este esenţială copierea de la dreapta la stânga. Utilizarea funcţiei de bibliotecă memmove. Aceasta are următorul prototip: void *memmove(void *dest, const void *src, size_t n); Funcţia copiază n octeţi de la adresa src la adresa dest. Rezultatul este corect chiar dacă src şi dest se suprapun. Pentru exemplul prezentat anterior copierea s-ar face cu apelul: memmove(&v[4],&v[3],4*sizeof(v[0])); v[3]=nou; Indicaţii 6.1 Atenţie la clasa nou apărută MULTIME şi metodele acesteia. Atenţie la ordinea figurilor de pe ecran. Tema 6.2 Să se definească printr-o metoda şi să se utilizeze pentru clasa MULTIME operatorul unar “++” cu funcţionalitate trecerea la următorul element din mulţime. Consideraţii teoretice 6.2 Funcţii friend Necesitatea mecanismului de “friend” provine de la imposibilitatea unei metode de a fi membră în mai multe clase. S-a impus existenţa unei soluţii ca o funcţie ne-membră să poată accesa membrii ne-publici ai unei clase. Acest lucru se realizează prin prefixarea declaraţiei cu cuvântul cheie “friend”.

Upload: others

Post on 09-Dec-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Laborator 2 - Incapsularea · 2017. 12. 25. · Laborator 6 – Redefinirea ... trebuie declarate în cadrul clasei, deci de către proiectantul clasei. Clasa îşi stabileşte funcţiile

Programare Orientată pe Obiecte

- 1 -

Laborator 6 – Redefinirea operatorilor

Tema 6.1

Analizaţi programul din fişierele EX6.CPP, EX6.H, CLASE.CPP, CLASE.H

Consideraţii teoretice 6.1

Pentru inserarea unui element într-o poziţie oarecare într-un vector completat parţial există

următoarele posibilităţi:

0 1 2 3 4 5 6 7 8

A B C D E F

A B C nou D E

G

F G

V

V

Mutare element cu element. Pentru exemplul din figură avem 7 poziţii completate şi dorim să

inserăm în poziţia de indice 3. Codul ar putea fi:

for(k=6;k>=3;k--)

v[k+1]=v[k];

v[3]=nou;

Pentru a evita suprascrierea accidentală este esenţială copierea de la dreapta la stânga.

Utilizarea funcţiei de bibliotecă memmove. Aceasta are următorul prototip:

void *memmove(void *dest, const void *src, size_t n);

Funcţia copiază n octeţi de la adresa src la adresa dest. Rezultatul este corect chiar dacă src

şi dest se suprapun. Pentru exemplul prezentat anterior copierea s-ar face cu apelul:

memmove(&v[4],&v[3],4*sizeof(v[0]));

v[3]=nou;

Indicaţii 6.1

Atenţie la clasa nou apărută MULTIME şi metodele acesteia.

Atenţie la ordinea figurilor de pe ecran.

Tema 6.2

Să se definească printr-o metoda şi să se utilizeze pentru clasa MULTIME operatorul unar “++” cu

funcţionalitate trecerea la următorul element din mulţime.

Consideraţii teoretice 6.2

Funcţii friend

Necesitatea mecanismului de “friend” provine de la imposibilitatea unei metode de a fi membră

în mai multe clase. S-a impus existenţa unei soluţii ca o funcţie ne-membră să poată accesa

membrii ne-publici ai unei clase. Acest lucru se realizează prin prefixarea declaraţiei cu cuvântul

cheie “friend”.

Page 2: Laborator 2 - Incapsularea · 2017. 12. 25. · Laborator 6 – Redefinirea ... trebuie declarate în cadrul clasei, deci de către proiectantul clasei. Clasa îşi stabileşte funcţiile

Programare Orientată pe Obiecte

- 2 -

Chiar dacă sunt declarate în cadrul clasei, ele nu sunt metode, deci nu li se transmite pointerul

ascuns this. Esenţial este că ele au acces la membrii ne-publici ai clasei cu care sunt prietene.

Evident, funcţiile friend încalcă (controlat) principiul încapsulării. Nefiind membre ale clasei,

accesibilitatea lor nu este afectată de secţiunea public, protected sau private în care sunt declarate

(fapt aparent surprinzător). Încălcarea controlată a încapsulării se referă la faptul că funcţiile friend

trebuie declarate în cadrul clasei, deci de către proiectantul clasei. Clasa îşi stabileşte funcţiile care

îi sunt prietene şi nu funcţiile clasele cu care să fie prietene, adică nu putem fi prieteni cu o clasă

decât dacă proiectantul acesteia consimte acest lucru.

În exemplul următor prezentăm modul de declarare a unei funcţii Multiply de înmulţire a unui

vector cu o matrice, funcţie declarată ca şi funcţie friend:

class CMatrice;

class CVector

{

int v[10];

friend CVector Multiply(CMatrice &m,CVector& v);

// . . . . . .

};

class CMatrice

{

int m[10][10];

friend CVector Multiply(CMatrice &m,CVector& v);

// . . . . . .

};

CVector Multiply(CMatrice &m,CVector& v)

{

CVector rez;

for(int i=0;i<10;i++)

{

rez.v[i]=0; // membrul v privat

for(int j=0;j<10;j++)

rez.v[i]+=m.m[i][j]*v.v[j]; // membrii v si m privati

}

return rez;

}

În lipsa mecanismului funcţiilor friend, înmulţirea ar fi putut fi făcută doar prin:

punerea variabilelor membru ale matricii şi vectorului publice, ceea ce ar fi impus renunţarea

completă la avantajele încapsulării (inacceptabil).

dotarea claselor cu metode de acces la membri (citire şi scriere a lor) fapt care ar fi compromis

eleganţa şi performanţele de viteză (orice acces la o variabilă însemnând apeluri suplimentare

de metode).

Cum ambele soluţii prezintă dezavantaje majore mecanismul funcţiilor friend este justificat.

Remarcăm şi faptul că funcţiile friend au acces la membrii ne-publici ai tuturor obiectelor de tipul

respectiv, nu doar la variabilele primite parametru (cum, eronat, s-ar putea trage concluzia din

exemplul anterior). De cele mai multe ori însă, se folosesc parametri pentru a suplini lipsa lui this.

Redefinirea operatorilor - generalități

Pentru tipurile predefinite semnificaţia operatorilor este binecunoscută, de exemplu este evident ce

înseamnă + pentru întregi. O caracteristică importantă a programării obiectuale este aceea că

Page 3: Laborator 2 - Incapsularea · 2017. 12. 25. · Laborator 6 – Redefinirea ... trebuie declarate în cadrul clasei, deci de către proiectantul clasei. Clasa îşi stabileşte funcţiile

Programare Orientată pe Obiecte

- 3 -

permite programatorului să îşi definească propriile clase, în fapt propriile tipuri de date. În sensul

comportării cât mai naturale a noilor tipuri introduse, devine evidentă utilitatea definirii şi pentru

aceste noi tipuri a unor operatori.

Termenul original este acela de “Operators Overloading”, adică supraîncărcarea operatorilor,

pentru a indica dreptul programatorului de a atribui sensuri noi operatorilor existenţi. Din această

cauză se foloseşte de multe ori termenul de redefinire a operatorilor pentru a indica acest fapt.

În limbajul C++ nu există, de exemplu, un tip număr complex, cu toate că, în matematică, acest tip

este bine definit. Putem declara o clasă complex pentru care să avem definită adunarea astfel:

class complex

{

double real, imag;

// . . . . .

complex Adunare(complex &arg); // prima varianta

complex operator+(complex &arg); // a doua varianta

};

în care ambele metode adună separat partea reală şi cea imaginară. cu posibilele utilizări:

complex a,b,c;

c = a.Adunare(b); // foarte incomod

c = a.operator+(b); // ceva mai clar, dar tot incomod

c = a+b; // in sfirsit natural

În exemplul anterior remarcăm forma incomodă cu apel explicit de metodă (mai ales în cazul unor

expresii complicate, cu adunări multiple) şi ultima formă, în sfârşit naturală (ultimele două forme de

scriere sunt echivalente). A doua formă indică faptul că avem de a face de fapt cu funcţii (metode)

cu nume de operator ("operator" este cuvânt cheie al limbajului).

Un exemplu mai complet este prezentat în continuare:

#include <stdio.h>

class complex

{

public:

double real;

double imag;

complex(double re,double im){real=re;imag=im;}

complex(){real=0;imag=0;};

complex operator+(complex &arg)

{

complex rez;

rez.real=real+arg.real; // rez.real=this->real+arg.real

rez.imag=imag+arg.imag; // rez.imag=this->imag+arg.imag

return rez;

}

};

void main()

{

complex c1(1,2),c2(5,7),c3;

printf("\nc1 ( %lf , %lf )",c1.real,c1.imag);

printf("\nc2 ( %lf , %lf )",c2.real,c2.imag);

Page 4: Laborator 2 - Incapsularea · 2017. 12. 25. · Laborator 6 – Redefinirea ... trebuie declarate în cadrul clasei, deci de către proiectantul clasei. Clasa îşi stabileşte funcţiile

Programare Orientată pe Obiecte

- 4 -

c3 = c1 + c2; // asta ne interesa !!!

printf("\nc3 ( %lf , %lf )",c3.real,c3.imag);

}

care produce următorul rezultat:

c1 ( 1.000000 , 2.000000 )

c2 ( 5.000000 , 7.000000 )

c3 ( 6.000000 , 9.000000 )

În mod evident adunarea este acum mult mai naturală astfel încât programul poate fi înţeles mult

mai uşor şi ne putem concentra asupra prelucrării propriu-zise. Pentru o implementare reală, utilă

clasa complex trebuie completată cu o mulţime de alţi operatori.

Redefinirea operatorilor prin metode sau prin funcţii friend - echivalări

Deşi nu a fost amintit anterior, redefinirea operatorilor se poate face atât prin metode cât şi prin

funcţii friend. Apelul funcţiilor şi metodelor operator se face de către compilator conform

următoarelor echivalări:

aritate sintaxa apel pentru operator

implementat prin metodă

apel pentru operator

implementat prin funcţie friend binar xy x.operator(y) operator(x,y)

unar x x.operator() operator(x)

în care am notat generic prin orice operator binar (cu doi operanzi) şi prin orice operator

unar (cu un singur operand).

Deoarece redefinirea operatorilor are de fapt la bază funcţii (metode) cu nume de operator putem

beneficia de supraîncărcarea numelui funcţiilor, adică putem defini diferit acelaşi operator

pentru argumente (operanzi) de tipuri diferite (putem, pentru o clasă, defini adunarea într-un fel

pentru al doilea operand întreg şi în alt fel pentru al doilea operand de tip long). Această posibilitate

este valabilă, evident, doar pentru operatorii binari, unde avem libertatea alegerii tipului unuia din

operanzi, un operand fiind impus a fi de tipul clasei pentru care redefinim operatorul.

Cu toate că funcţiile operator îmbunătăţesc versatilitatea programelor, trebuie respectate anumite

restricţii:

nu se pot defini operatori noi (de aceea se şi numeşte redefinirea operatorilor).

se pot redefini toţi operatorii existenţi în C++ cu excepţia următorilor:

. selecţie directa a membrilor

.* dereferenţiere pointeri la metode

:: “scope access” / rezoluţie

?: operatorul condiţional

nu se poate schimba aritatea şi prioritatea (precedenţa) operatorilor. Operatorii unari

trebuie să rămână unari, operatorii binari trebuie să rămână binari iar precedenţa operatorilor

nu poate fi schimbată, (adică, de exemplu, * rămâne prioritar lui +).

comportamentul operatorilor pentru tipurile predefinite nu poate fi schimbat, adică un

operand al operatorului redefinit trebuie să fie o clasă (cea în discuţie).

Page 5: Laborator 2 - Incapsularea · 2017. 12. 25. · Laborator 6 – Redefinirea ... trebuie declarate în cadrul clasei, deci de către proiectantul clasei. Clasa îşi stabileşte funcţiile

Programare Orientată pe Obiecte

- 5 -

redefinirea unor operatori nu redefineşte şi operatorii aparent combinaţi, adică

redefinirea lui + şi a lui = nu redefineşte şi +=. Dacă îl dorim şi pe cel combinat, trebuie să îl

redefinim explicit.

operatorii =, [ ] şi -> trebuie să fie funcţii membru ne-statice.

Scopul acestor restricţii este acela de a asigura că:

compilatorul de C++ nu trebuie să îşi modifice regulile sintactice.

semnificaţia operatorilor predefiniţi nu poate fi schimbată.

Indicaţii 6.2

Warning-ul legat de forma postfixată sau prefixată se va neglija.

Tema 6.3

Să se definească printr-o metodă şi să se utilizeze pentru clasa MULTIME operatorul binar “+” care să

permită inserarea unei figuri în mulţime.

Indicaţii 6.3

Utilizaţi atât folosind forma a.operator+(b) cât şi forma a+b.

Tema 6.4

Să se modifice operatorul “+” definit anterior astfel încât să permită şi utilizarea cascadată (de

forma: m + cerc + patrat).

Consideraţii teoretice 6.4

Să considerăm o expresie de genul:

operand1 + operand2 + operand3

Avem în expresie doi operatori + care se evaluează (conform asociativităţii operatorului +) de la

stânga la dreapta. În momentul evaluării primului operator se apelează metoda respectivă. Ca şi

prim operand al celui de al doilea operator se consideră rezultatul întors de această metodă. Acesta

trebuie să aibă un asemenea tip încât să permită aplicarea următorului operator din expresie (fie el

operator standard sau redefinit).

Atragem atenţia că, în evaluarea expresiilor, se păstrează regulile privind aritatea, prioritatea şi

asociativitatea operatorilor.

Lucrurile se petrec asemănător în ceea ce priveşte rezultatul întors şi în cazul operatorilor redefiniţi

prin funcţii friend.

Pentru a evita mecanismul laborios (şi uneori periculos) de copiere a obiectelor întoarse prin valoare

de cele mai multe ori un operator redefinit întoarce rezultatele (obiectele rezultat) prin referinţă.

Indicaţii 6.4

Atenţie la ce se întâmplă dacă operatorul întoarce mulţimea prin valoare.

Pentru referirea obiectului curent (în scopul întoarcerii) ar putea fi folosit pointerul this.

Page 6: Laborator 2 - Incapsularea · 2017. 12. 25. · Laborator 6 – Redefinirea ... trebuie declarate în cadrul clasei, deci de către proiectantul clasei. Clasa îşi stabileşte funcţiile

Programare Orientată pe Obiecte

- 6 -

Tema 6.5

Să se verifice funcţionarea unui apel de genul: m = m + new CERC şi să se justifice.

Consideraţii teoretice 6.5

Un operator de o importanţă deosebită este operatorul = (de atribuire). El trebuie să primească

parametru o referinţă la un obiect de acelaşi tip pe care îl copiază în obiectul curent. Prezintă

următoarele particularităţi:

dacă nu este definit de către programator compilatorul generează implicit un operator =

care copiază membru cu membru (“bit cu bit”) conţinutul obiectelor.

este folosit în cazul atribuirii de obiecte de acel tip (inclusiv a obiectelor întoarse de către

funcţii/metode).

Apare un pericol datorită copierii membru cu membru a unor membrii a căror semnificaţie nu este

doar valoarea lor propriu zisă, ci ea reprezintă “identificatorul” unei resurse (de exemplu zonă de

memorie alocată, fişier deschis, etc.). Pentru a nu pierde / duplica asemenea resurse se impune

redefinirea operatorului = în cazul în care obiectul are în componenţă asemenea membri. Operatorul

= astfel redefinit trebuie să elibereze resursa veche şi să duplice resursa nouă (de obicei prin

alocarea uneia noi şi copierea caracteristicilor acesteia).

De asemenea, dacă nu este definit de către programator un constructor de copiere, compilatorul

generează implicit un constructor de copiere care copiază membru cu membru (“bit cu bit”)

conţinutul obiectelor.

Pericol asemănător (datorate copierii membru cu membru) apare şi la constructorul de copiere

soluţia fiind identică (doar că “resursa” veche nu este încă alocată deci nu trebuie întâi eliberată –

fiind constructor abia acum se alocă prima dată).

Atragem atenţia asupra diferenţei între constructorul de copiere (utilizat când = apare chiar la

definirea variabilei „destinaţie”) şi operatorul de atribuire (când = apare ulterior definirii

variabilei „destinaţie”).

Indicaţii 6.5

Dacă se copiază un obiect în el însuşi pericolul amintit anterior nu apare.

Tema 6.6

Să se introducă operatorul “+=” care să permită adăugarea unei figuri în mulţime folosind pentru

implementare o funcţie friend.

Consideraţii teoretice 6.6

Vezi consideraţiile teoretice 6.2.

Indicaţii 6.6

Atenţie că ordine parametrilor funcţiei friend este importantă.

Tema 6.7

Să se introducă şi să se utilizeze operatorul “--” care să elimine elementul curent din mulţime.

Implementarea se va face prin funcţie friend.

Page 7: Laborator 2 - Incapsularea · 2017. 12. 25. · Laborator 6 – Redefinirea ... trebuie declarate în cadrul clasei, deci de către proiectantul clasei. Clasa îşi stabileşte funcţiile

Programare Orientată pe Obiecte

- 7 -

Consideraţii teoretice 6.7

O problemă apărută în primele versiuni de C++ era imposibilitatea distingerii între formele

prefixate şi postfixate ale operatorilor unari. Problema s-a rezolvat în sensul că, prin convenţie:

varianta prefixată se redefineşte “normal” (majoritatea operatorilor unari au doar forma

prefixată).

varianta postfixată se redefineşte având suplimentar un parametru de tip întreg.

Parametrul suplimentar din forma postfixată nu este efectiv folosit, scopul său este doar de a asigura

o diferenţă de semnătură.

Considerând o clasă CX redefinirea operatorului ++ în formă prefixată şi în formă postfixată se fac

conform exemplului următor:

void CX::operator++(); //forma prefixata, metoda

void CX::operator++(int); //forma postfixata, metoda

friend void operator++(CX&); //forma prefixata, functie friend

friend void operator++(CX&,int); //forma postfixata, functie friend

Evident o anumită forma (prefixată / postfixată) nu se poate redefini prin ambele variante (şi prin

metodă şi prin funcţie friend) ci doar prin una dintre ele.

Indicaţii 6.7

Rezolvaţi şi eventuale warning-uri care apar.

Tema 6.8

Să se execute pas cu pas secvenţele de cod care se referă la operatori.

Consideraţii teoretice 6.8

A se revedea consideraţiile teoretice 3.7.

Page 8: Laborator 2 - Incapsularea · 2017. 12. 25. · Laborator 6 – Redefinirea ... trebuie declarate în cadrul clasei, deci de către proiectantul clasei. Clasa îşi stabileşte funcţiile

Programare Orientată pe Obiecte

- 8 -

Anexa 6

ex6.h

#define TAB 9

#define ESC 27

#define LEFT 75

#define RIGHT 77

#define UP 72

#define DOWN 80

#define UNU ’1’

#define DOI ’2’

#define TREI ’3’

#define PATRU ’4’

#define CINCI ’5’

#define SASE ’6’

// prototipuri de functii

void OurInitGraph(void);

ex6.cpp

#include <graphics.h>

#include <stdlib.h>

#include <stdio.h>

#include <conio.h>

#include "ex6.h"

#include "clase.h"

MULTIME m; // atentie la clasa MULTIME !!!!!!

void main()

//*********

{

int gata=0;

OurInitGraph();

m.Insert( new CERC );

m.Insert( new PATRAT(500,300,75,RED,"red") );

m.Insert( new CERC(100,100,25,BLUE,"blue") );

m.Insert( new PATRAT );

m.Insert( new PATRAT(400,200,100,YELLOW,"yellow") );

m.Insert( new CERC );

m.Afiseaza();

while(!gata)

switch(getch())

{

case ESC:

gata=1;

break;

case TAB:

Page 9: Laborator 2 - Incapsularea · 2017. 12. 25. · Laborator 6 – Redefinirea ... trebuie declarate în cadrul clasei, deci de către proiectantul clasei. Clasa îşi stabileşte funcţiile

Programare Orientată pe Obiecte

- 9 -

m.Urmatorul();

break;

case UNU: m.Get()->Creste( +10 ); m.Afiseaza(); break;

case DOI: m.Get()->Creste( -10 ); m.Afiseaza(); break;

case TREI: if(m.NrElem()<MAX_FIGURI){

if(m.NrElem()%2)

m.Insert(new CERC);

else

m.Insert(new PATRAT);

m.Afiseaza();

} break;

case PATRU: m.Elimina(); m.Afiseaza(); break;

case 0:

switch(getch())

{

case LEFT: m.Get()->Muta( -10, 0 ); break;

case RIGHT: m.Get()->Muta( 10, 0 ); break;

case UP: m.Get()->Muta( 0,-10 ); break;

case DOWN: m.Get()->Muta( 0, 10 ); break;

}

m.Afiseaza();

}

closegraph();

}

void OurInitGraph()

//*****************

{

int gdriver = DETECT, gmode, errorcode;

initgraph(&gdriver,&gmode,""); /* initialize graphics and local variables */

errorcode = graphresult(); /* read result of initialization */

if (errorcode != grOk) /* an error occurred */

{

printf("Graphics error: %s\n", grapherrormsg(errorcode));

printf("Press any key to halt:");

getch();

exit(1); /* terminate with an error code */

}

settextjustify(CENTER_TEXT,CENTER_TEXT);

}

clase.h

class POZITIE

{

public:

POZITIE ();

POZITIE (int x0,int y0);

void Muta(int dx,int dy);

protected:

int x;

int y;

};

class FIGURA : public POZITIE

{

protected:

int r;

Page 10: Laborator 2 - Incapsularea · 2017. 12. 25. · Laborator 6 – Redefinirea ... trebuie declarate în cadrul clasei, deci de către proiectantul clasei. Clasa îşi stabileşte funcţiile

Programare Orientată pe Obiecte

- 10 -

int c;

char *Nume;

public:

FIGURA();

FIGURA(int x0,int y0,int r0,int c0,char *n0);

~FIGURA();

void Muta(int dx,int dy);

void Creste(int dr);

virtual void Afiseaza()=0;

virtual void Sterge()=0;

};

class CERC : public FIGURA

{

public:

CERC();

CERC(int x0,int y0,int r0,int c0,char *n0);

void Afiseaza();

void Sterge();

};

class PATRAT : public FIGURA

{

public:

PATRAT();

PATRAT(int x0,int y0,int r0,int c0,char *n0);

void Afiseaza();

void Sterge();

};

#define MAX_FIGURI 20

class MULTIME //retine multimea de figuri

{

int NrFiguri;

int FiguraCurenta;

FIGURA *pe[MAX_FIGURI]; //adresele figurilor

public:

MULTIME();

void Afiseaza();

void Urmatorul();

int Insert(FIGURA* f);

void Elimina();

FIGURA* Get();

int NrElem();

};

clase.cpp

#include <graphics.h>

#include <string.h>

#include <alloc.h>

#include "clase.h"

//~~~~~~~~~~~~~~~~~~

// clasa POZITIE

//~~~~~~~~~~~~~~~~~~

POZITIE:: POZITIE ()

//******************

Page 11: Laborator 2 - Incapsularea · 2017. 12. 25. · Laborator 6 – Redefinirea ... trebuie declarate în cadrul clasei, deci de către proiectantul clasei. Clasa îşi stabileşte funcţiile

Programare Orientată pe Obiecte

- 11 -

{

x = 320;

y = 240;

}

POZITIE:: POZITIE (int x0,int y0)

//*******************************

{

x = x0;

y = y0;

}

void POZITIE::Muta(int dx,int dy)

//********************************

{

x += dx;

y += dy;

}

//~~~~~~~~~~~~~~~~

// clasa FIGURA

//~~~~~~~~~~~~~~~~

FIGURA::FIGURA():POZITIE ()

//*************************

{

r = 50;

c = WHITE;

Nume = (char*)malloc(strlen("FIGURA")+1);

strcpy(Nume,"FIGURA");

}

FIGURA::FIGURA(int x0,int y0,int r0,int c0, char *n0): POZITIE (x0,y0)

//*******************************************************************

{

r = r0;

c = c0;

Nume = (char*)malloc(strlen(n0)+1); //aloca memorie suplimentara

strcpy(Nume,n0);

}

FIGURA::~FIGURA()

//***************

{

free(Nume); //elibereaza memoria suplimenatra alocata

}

void FIGURA::Muta(int dx,int dy)

//******************************

{

Sterge(); //stergere

POZITIE::Muta(dx,dy); //mutare

Afiseaza(); //afisare in noua pozitie

}

void FIGURA::Creste(int dr)

//*************************

{

Sterge(); //stergere

r+=dr; //redimensionare

Afiseaza(); //afisare cu noua dimensiune

}

Page 12: Laborator 2 - Incapsularea · 2017. 12. 25. · Laborator 6 – Redefinirea ... trebuie declarate în cadrul clasei, deci de către proiectantul clasei. Clasa îşi stabileşte funcţiile

Programare Orientată pe Obiecte

- 12 -

//~~~~~~~~~~~~~~~

// clasa CERC

//~~~~~~~~~~~~~~~

CERC::CERC():FIGURA()

//*******************

{

}

CERC::CERC(int x0,int y0,int r0,int c0, char *n0):FIGURA(x0,y0,r0,c0,n0)

//**********************************************************************

{

}

void CERC::Sterge()

//*****************

{

setcolor(BLACK);

circle(x,y,r);

outtextxy(x,y,Nume);

}

void CERC::Afiseaza()

//*******************

{

setcolor(c);

circle(x,y,r);

outtextxy(x,y,Nume);

}

//~~~~~~~~~~~~~~~~

// clasa PATRAT

//~~~~~~~~~~~~~~~~

PATRAT::PATRAT():FIGURA()

//***********************

{

}

PATRAT::PATRAT(int x0,int y0,int r0,int c0, char *n0):FIGURA(x0,y0,r0,c0,n0)

//**************************************************************************

{

}

void PATRAT::Sterge()

//*******************

{

setcolor(BLACK);

rectangle(x-r,y-r,x+r,y+r);

outtextxy(x,y,Nume);

}

void PATRAT::Afiseaza()

//*********************

{

setcolor(c);

rectangle(x-r,y-r,x+r,y+r);

outtextxy(x,y,Nume);

}

//~~~~~~~~~~~~~~~~~

// clasa MULTIME

//~~~~~~~~~~~~~~~~~

Page 13: Laborator 2 - Incapsularea · 2017. 12. 25. · Laborator 6 – Redefinirea ... trebuie declarate în cadrul clasei, deci de către proiectantul clasei. Clasa îşi stabileşte funcţiile

Programare Orientată pe Obiecte

- 13 -

MULTIME::MULTIME()

//****************

{

NrFiguri=0;

FiguraCurenta=0; //initial multimea e vida

}

void MULTIME::Urmatorul()

//***********************

{

FiguraCurenta++;

FiguraCurenta%=NrFiguri; //trecere la urmatoarea figura din multime

}

void MULTIME::Afiseaza()

//**********************

{

int k;

for(k=0;k<NrFiguri;k++) //afiseaza toate figurile din multime

pe[k]->Afiseaza();

}

FIGURA* MULTIME::Get()

//********************

{

return(pe[FiguraCurenta]); //intoarce adresa figurii curente

}

int MULTIME::NrElem()

//*******************

{

return(NrFiguri); //intoarce numarul de figuri

}

int MULTIME::Insert(FIGURA* f) //insereaza o figura in pozitia curenta

//****************************

{

if(NrFiguri==MAX_FIGURI)

return(-1); //nu a fost inserat

memmove(&pe[FiguraCurenta]+1,&pe[FiguraCurenta],

(NrFiguri-FiguraCurenta)*sizeof(pe[0]) ); //facem loc

pe[FiguraCurenta]=f; //inserare figura noua

NrFiguri++;

return(FiguraCurenta);

}

void MULTIME::Elimina() //elimina figura din pozitia curenta

//*********************

{

if(NrFiguri==1)

return; //multimea sa nu devina vida

pe[FiguraCurenta]->Sterge(); //stergere de pe ecran

delete pe[FiguraCurenta]; //distrugere element

memmove(&pe[FiguraCurenta],&pe[FiguraCurenta]+1,

(NrFiguri-FiguraCurenta)*sizeof(pe[0]) ); //mutare in multime

NrFiguri--;

if(FiguraCurenta==NrFiguri)

FiguraCurenta--;

}