Download - Laborator 2 - irinaterfaloaga.files.wordpress.com fileProgramare orientata pe obiecte – limbajele C++/Java Laborator nr. 2 1 Laborator 2 1. Constructori si destructori 2. Membri

Transcript

Programare orientata pe obiecte – limbajele C++/Java

Laborator nr. 2

1

Laborator 2

1. Constructori si destructori

2. Membri statici ai claselor

3. Funcţii membre constante

4. Funcţii care returnează referinţe

5. Supraîncărcarea operatorilor

5.1. Supraîncărcarea operatorilor folosind funcţii membre

5.2. Supraincarcarea operatorilor folosind functii prietene

1. Constructori si destructori

1. Definiti si implementati clasa Carte, având ca date membre: Nume, Autor, Nrpag,

Pret, şi ca funcţii membre: citeste_carte si afiseaza_carte.

#include<iostream.h>

#include<conio.h>

#include<string.h>

int i = 1;

class carte{

public:

char nume[40];

char autor[40];

int nrpag;

double pret;

void citeste_carte(char *numecarte, char *autorcarte, int *np, double *p);

void afiseaza_carte();

};

void carte::citeste_carte(char *numecarte, char *autorcarte, int *np, double *p)

{

strcpy(nume, numecarte);

strcpy(autor, autorcarte);

nrpag = *np;

pret = *p;

}

void carte::afiseaza_carte()

{

cout<<endl<<"Cartea nr. "<<i<<" : "<<nume<<endl;

cout<<endl<<"Autor : "<<autor<<endl;

cout<<endl<<"Nr. pagini : "<<nrpag<<endl;

cout<<endl<<"Pret : "<<pret<<endl;

}

Programare orientata pe obiecte – limbajele C++/Java

Laborator nr. 2

2

int main(void)

{

carte cartecitita;

char c_nume[40], c_autor[40];

int c_nrpag;

double c_pret;

char optiune = 'd';

clrscr();

while(optiune == 'd')

{

cout<<"Dati denumirea cartii ";cin>>c_nume;

cout<<"Dati numele auorului ";cin>>c_autor;

cout<<"Dati numarul de pagini ";cin>>c_nrpag;

cout<<"Dati pretul cartii ";cin>>c_pret;

cartecitita.citeste_carte(c_nume, c_autor, &c_nrpag, &c_pret);

cout<<"Informatiile citite sunt "<<endl;

cartecitita.afiseaza_carte();

getch();

cout<<endl<<"Continuati ? [d/n] = ";cin>>optiune;

i++;

}

}

2. Prezentăm în continuare un exemplu de clasă care implementează, o structură de tip

listă, în mod special - o structură de tip coadă - FIFO (First In First Out).

#include<iostream.h>

#include<conio.h>

//lista de tip coada = FIFO (First In First Out) cu 100 de elemente

class fifo{

// declaratii de tip privat

int tab[100]; // vectorul de 100 de elemente

int nrcrt; // numarul curent de elemente din lista

int prim; // primul element din lista

public:

// declaratii de tip public

int adaug(int); //adauga un element la sfarsit

int extrag(int&);//extrage un element de la inceput

// functii inline

void init() //initializez lista

{

nrcrt=prim=0;

}

int lista_vida() // verific daca stiva este sau nu vida

{

return(nrcrt>0);//daca nrcrt=0 atunci lista este vida

}

int lista_plina()

{

return(nrcrt<100);//daca nrcrt=100 atunci lista este plina

}

};

Programare orientata pe obiecte – limbajele C++/Java

Laborator nr. 2

3

int fifo::adaug(int k) //definitia functiei membru este in afara declaratiei

{ //clasei resp. si deci trebuie specificat ca apartine

// clasei fifo prin folosirea operatorului de

// rezolutie ::

if(lista_plina())

{

tab[(prim+nrcrt)%100]=k;

nrcrt++;

cout<<"Lista are "<<nrcrt<<" elemente"<<endl;

return 1;

}

else

{

cout<<"Lista este plina"<<endl;

return 0;

}

}

int fifo::extrag(int &k)

{

if(lista_vida())

{

k=tab[prim];

prim=(prim+1)%100;

nrcrt--;

cout<<"Lista mai are "<<nrcrt<<" elemente"<<endl;

return 1;

}

else

{

cout<<"Lista este vida"<<endl;

return 0;

}

}

int main(void)

{

int k,i;

fifo lista; //declaratia unui obiect de tip fifo avand numele lista

fifo *plista; // declaratia unui pointer la lista

lista.init(); //initializeaza lista respectiva

plista=&lista; //pointerul primeste adresa obiectului lista

cout<<"Dati un element care se va adauga in lista ";

cin>>k;

plista->adaug(k); // adauga elementul cu valoarea k in lista;

//afisarea elementelor din lista:

for(i=prim;i<nrcrt;i++) cout<<tab[i]<<" ";

getch();

}

Programare orientata pe obiecte – limbajele C++/Java

Laborator nr. 2

4

3. Definiţi şi implementaţi clasa Cerc, având ca dată membră Raza, un constructor şi ca

funcţii membre Aria şi Circumferinta.

#include<iostream.h>

#include<conio.h>

#define PI 3.14

class cerc{

float raza;

public:

cerc();

float aria();

float circumferinta();

};

cerc::cerc()

{

cout<<"Raza cercului este = ";

cin>>raza;

}

float cerc::aria()

{

return (PI*raza*raza);

}

float cerc::circumferinta()

{

return (2*PI*raza);

}

int main(void)

{

cerc c;

clrscr();

cout<<"Aria cercului este = "<<c.aria()<<endl;

cout<<"Circumferinta cercului este = "<<c.circumferinta()<<endl;

getch();

}

Programare orientata pe obiecte – limbajele C++/Java

Laborator nr. 2

5

4. Definiţi şi implementaţi clasa Cilindru, având ca date membre Raza şi Inaltimea

cilindrului şi ca funcţii membre: un constructor, Aria şi Volumul.

#include<iostream.h>

#include<conio.h>

#define PI 3.14

class cilindru{

float raza;

float inaltimea;

public:

cilindru();

float aria();

float aria_totala();

float volum();

};

cilindru::cilindru()

{

cout<<"Dati raza cilindrului = ";cin>>raza;

cout<<"Dati inlatimea cilindrului = ";cin>>inaltimea;

}

float cilindru::aria()

{

return (2*PI*raza*inaltimea);

}

float cilindru::aria_totala()

{

float a;

a=aria();

return(a+2*PI*raza*raza);

}

float cilindru::volum()

{

return (PI*raza*raza*inaltimea);

}

int main(void)

{

clrscr();

cilindru c;

cout<<"Aria cilindrului este = "<<c.aria()<<endl;

cout<<"Aria totala este = "<<c.aria_totala()<<endl;

cout<<"Volumul cilindrului este = "<<c.volum()<<endl;

getch();

}

Programare orientata pe obiecte – limbajele C++/Java

Laborator nr. 2

6

2. Membri statici ai claselor

În fiecare obiect, pentru datele membre nestatice se crează copii. Pentru funcţiile

membre există o copie unică.

Pentru datele membre statice există o singură copie care va fi partajată de către

toate obiectele.

Funcţiile membre statice sunt accesibile numai în fişierul în care sunt definite,

fiind independente de obiecte (instanţele claselor).

O funcţie statică poate fi apelată:

ca funcţie membră a unui obiect

independent de obiect, folosind operatorul de rezoluţie.

Pointerul this nu poate fi folosit de către funcţia statică, deoarece nu îi este

transmis, aşadar funcţia statică nu poate accesa decât date membre statice şi date globale.

Clasa Data depinde de variabila statică azi. Aceasta va aparţine clasei, dar nu şi

obiectelor clasei.

class Data{

int a, l, z;

static Data azi; //data membra statica

public:

Data(int aa=0, int ll=0, int zz=0);

. . .

static void set_data_crta(int aa, int ll, int zz);

};

Data::Data(int aa, int ll, int zz){

a = aa? aa : azi.a;

l = ll? ll : azi.l;

z = zz? Zz : azi.z;

};

Funcţia set_data_crta() permite modificarea datei curente, care iniţializează un

obiect neiniţializat. La definirea unui membru static nu se mai repetă cuvântul static.

void Data::set_implic(int a, int l, int z){

azi = Data(a, l, z);

};

Programare orientata pe obiecte – limbajele C++/Java

Laborator nr. 2

7

3. Funcţii membre constante

Funcţiile membre care nu modifică starea obiectului se declară ca funcţii

constante (funcţii const), punând după lista de parametri cuvântul cheie const.

Compilatorul va sesiza orice încercare de modificare a obiectului din funcţia const.

Funcţiile membre apelate din obiectele constante pot fi numai funcţii constante.

Dacă funcţia membră const este definită în afara clasei, este necesar sufixul const

în definiţie. Exemplu:

class Data{

int a, l, z;

public:

int zi()const {return z;};

int luna()const {return l;};

int an()const;

};

inline int Data::an()const{ return a;};

Nu este posibilă declararea unei constante simbolice în interiorul unei clase.

Astfel:

class Vector{

const int N=10;

double x[N];

. . .

}

nu funcţionează corect deoarece declararea clasei descrie obiectul, dar nu îl crează. Sunt

posibile două soluţii:

- se declară o enumerare în interiorul clasei, care furnizează la nivelul clasei nume

simbolice pentru constante întregi :

class Vector{

enum{ N=10 };

double x[N];

. . .

}

- se crează o constantă statică, partajată de toate obiectele Vector

class Vector{

static const int N=10;

double x[N];

. . .

}

Programare orientata pe obiecte – limbajele C++/Java

Laborator nr. 2

8

4. Funcţii care returnează referinţe

Pentru clasa complex, am definit funcţiile care asigură accesul partea reală,

respectiv imaginară a unui număr complex,:

double real(){ return re; };

double imag(){ return im; };

Dacă am dori modificarea părţii reale a unui număr complex printr-o atribuire de

forma:

z.real()=5.;

constatăm că funcţia astfel definită nu poate apărea în partea stângă a unei atribuiri (nu

este o L-valoare). Acest neajuns se remediază impunând funcţiei să returneze o referinţă

la obiect, adică:

double& real(){ return re; };

Funcţiile de actualizare a datei ad_a(), ad_l(), ad_z() nu întorc valori. Pentru

asemenea funcţii este util să întoarcem o referinţă la obiectul actualizat, astfel încât

operaţiile să poată fi înlănţuite de forma:

d.ad_a(1).ad_l(1).ad_z(1);

Funcţiile se declară cu valoare de întoarcere referinţă la Data:

class Data{

Data& ad_a(int);

Data& ad_l(int);

Data& ad_z(int);

};

Data& ad_a(int n){

if(z==29 && l==2 && !bisect(a+n)){

z=1;

l=3;

};

a += n;

return *this;

}

Într-o funcţie membru nestatică this este un pointer la obiectul din care s-a apelat

funcţia membru. Nu este posibil să preluăm adresa lui this şi nici să o modificăm.

Cele mai multe referiri la this sunt implicite. Orice referire la un membru nestatic

din interiorul clasei foloseşte în mod implicit pe this pentru a obţine membrul din acel

obiect.

O clasă conţine în mod uzual: un constructor, funcţii pentru examinarea obiectelor

(funcţii de acces), funcţii pentru manipularea obiectelor, operaţii de copiere, etc.

Programare orientata pe obiecte – limbajele C++/Java

Laborator nr. 2

9

Probleme propuse spre rezolvare

1. Proiectaţi şi implementaţi clasa Complex care să permită lucrul cu numere

complexe.

Constructorul clasei va avea ca argumente partea reală, respectiv imaginară a

numărului complex (în mod implicit aceste valori se iau 0).

Se va asigura un constructor de copiere.

Se vor prevedea funcţii membri pentru:

- accesul la partea reală, respectiv imaginară a numărului complex

- modulul numărului complex

- argumentul numărului complex

2. Proiectaţi şi implementaţi clasa Raţional care să permită lucrul cu numere raţionale.

Constructorul clasei va avea două argumente: număratorul, respectiv numitorul

numărului raţional (constructorul poate avea şi un singur argument,caz în care al doilea

se ia implicit 1,sau nici un argument, caz în care se iau valorile implicite 0 şi 1).

Se va asigura un constructor de copiere.

Se vor prevedea funcţii membri pentru accesul la număratorul, respectiv

numitorul numărului raţional.

3. Proiectaţi şi implementaţi clasa Vector care să permită lucrul cu vectori de elemente

reale.

Constructorul clasei va avea un argument - dimensiunea vectorului şi va aloca

emorie

pentru vector (în lipsa argumentului se ia implicit dimensiunea 10)

Se va asigura un destructor şi un constructor de copiere.

Se vor prevedea funcţii membri pentru:

- determinarea dimensiunii vectorului

- determinarea lungimii vectorului

Programare orientata pe obiecte – limbajele C++/Java

Laborator nr. 2

10

5. Supraîncărcarea operatorilor

5.1. Supraîncărcarea operatorilor folosind funcţii membre

5.2. Supraincarcarea operatorilor folosind functii prietene

5.1. Supraîncărcarea operatorilor folosind funcţii membre

O functie membra primeste in mod implicit adresa obiectului pentru care este

apelata. Functia operator+() va avea prototipul:

complex operator+(complex);

Expresia x+y, unde x si y sunt de tipul complex, va fi interpretata de compilator

ca un apel:

x.complex+(y)

Programul urmator prezinta o varianta mai simpla a clasei complex, cu operatorul

“+” supradefinit:

#include<iostream.h>

#include<math.h>

class complex

{

// date membru protejate(private)

double real;

double imag;

// functii membru neprotejate

public:

// constructor folosit la initializare

complex(double x=0,double y=0);

// constructor de copiere

void afiscomplex();

complex operator+(complex);

};

complex::complex(double x, double y)

{

real=x;

imag=y;

}

void complex::afiscomplex()

{

cout<<real<<" + i * "<<imag;

}

complex complex::operator+(complex x)

{

complex z;

z.real=real+x.real;

z.imag=imag+x.imag;

return z;

}

Programare orientata pe obiecte – limbajele C++/Java

Laborator nr. 2

11

int main(void)

{

double x,y;

cout<<"Dati primul numar complex "<<endl;

cout<<"Partea reala = ";cin>>x;

cout<<"Partea imaginara = ";cin>>y;

complex z1(x,y);

z1.afiscomplex();

cout<<"Dati al doilea numar complex "<<endl;

cout<<"Partea reala = ";cin>>x;

cout<<"Partea imaginara = ";cin>>y;

complex z2(x,y);

z2.afiscomplex();

complex t;

t=z1+z2;

cout<<endl<<"Suma celor doua nr. complexe ";

t.afiscomplex();

}

5.2. Supraincarcarea operatorilor folosind functii prietene

Putem adauga functia prietena operator+() care are urmatorul prototip:

complex operator+(complex,complex)

Expresia x+y va fi interpretata de catre compilator ca un apel al functiei operator+(x,y),

care este perfect echivalenta.

Exemplul urmator prezinta acest tip de supraincarcare a operatorului “+”:

#include<iostream.h>

#include<math.h>

class complex

{

// date membru protejate(private)

double real;

double imag;

// functii membru neprotejate

public:

// constructor folosit la initializare

complex(double x=0,double y=0);

// constructor de copiere

void afiscomplex();

friend complex operator+(complex,complex);

};

complex::complex(double x, double y)

{

real=x;

imag=y;

}

void complex::afiscomplex()

{

cout<<real<<" + i * "<<imag;

}

Programare orientata pe obiecte – limbajele C++/Java

Laborator nr. 2

12

complex operator+(complex x, complex y)

{

complex z;

z.real=x.real+y.real;

z.imag=x.imag+y.imag;

return z;

}

int main(void)

{

double x,y;

cout<<"Dati primul numar complex "<<endl;

cout<<"Partea reala = ";cin>>x;

cout<<"Partea imaginara = ";cin>>y;

complex z1(x,y);

z1.afiscomplex();

cout<<"Dati al doilea numar complex "<<endl;

cout<<"Partea reala = ";cin>>x;

cout<<"Partea imaginara = ";cin>>y;

complex z2(x,y);

z2.afiscomplex();

complex t;

t=z1+z2;

cout<<endl<<"Suma celor doua nr. complexe ";

t.afiscomplex();

}

Probleme propuse spre rezolvare

1. Adaugati clasei complex o metoda care scade doua numere complexe:

)(*** 2121221121 yyixxyixyixzz

2. Adaugati clasei complex o metoda care inmulteste doua numere complexe:

)**(***)*)(*(* 12212121221121 yxyxiyyxxyixyixzz

3. Adaugati clasei complex o metoda care imparte doua numere complexe:

2

2

2

2

21122121

2222

2211

22

11

2

1 )**(***

)*)(*(

)*)(*(

*

*

yx

yxyxiyyxx

yixyix

yixyix

yix

yix

z

z

4. Se citesc z1 si z2, numere complexe si n, numar natural. Se cere, ca prin utilizarea

clasei complex, sa se realizeze un program care calculeaza (z1/z2)n.

5. Adaugati clasei complex functii prietene prin care se pot calcula expresii de forma:

a*z, z*a, a/z, z/a, unde z este un obiect al clasei complex, iar a, un numar real.