Documente Academic
Documente Profesional
Documente Cultură
Lab2 POO
Lab2 POO
class NumeClasa {
private:
[tip1] membruPrivat1;
[tip2] membruPrivat2;
...
public:
[tip1] membruPublic1;
[tip2] membruPublic2;
...
};
Modul de acces poate fi definit prin unul din cuvintele cheie public, private sau
protected. Acesta indică dreptul de acces la membrii definiţi după el.
Membrii declaraţi cu private sunt accesibili doar membrilor din cadrul aceleiaşi clase. Membrii
declaraţi cu public sunt accesibili atât membrilor din cadrul aceleiaşi clase cât şi membrilor altor clase,
de oriunde, din interiorul sau din afara acelor clase. Membrii declaraţi cu protected sunt accesibili
atât membrilor aceleiaşi clase cât şi membrilor claselor derivate din ea.
În mod implicit, toţi membrii unei clase au modul de acces private.
De exemplu:
class Dreptunghi {
int lungime, latime;
public:
void setLungime (int);
void setLatime (int);
int arie (void);
};
Exemplul declară o clasă (adică un tip de dată abstractă) numită Dreptunghi. Aceasta conţine
cinci membri: două câmpuri de tip int (lungime şi latime) cu modul de acces privat şi trei metode cu
modul de acces public: setLungime(int), setLatime(int) şi arie(). Pentru moment am inclus
doar declaraţia acestor metode, nu şi definiţia lor.
Pentru a declara un obiect (o variabilă) cu numele dr, vom folosi următoarea instrucţiune:
Dreptunghi dr;
unde Dreptunghi reprezintă numele clasei, iar dr obiectul instanţiat. Prin această instrucţiune,
se alocă obiectului dr o zonă de memorie corespunzătoare membrilor de tip dată (câmpuri) de lungime
2 * sizeof(int) = 8 octeţi, câmpurile nefiind iniţializate.
În afara clasei, cu ajutorul acestui obiect putem accesa membrii publici, folosind următoarea
sintaxă:
numeObiect.numeMembru;
Accesul la membrii unei clase este foarte asemănător cu accesul datelor dintr-o structură. De
exemplu:
dr.setLatime(10);
dr.setLungime(20);
valArie = dr.arie();
Singurii membri ai obiectului dr pe care nu-i putem accesa în corpul programului nostru, din
afara clasei, sunt lungime şi latime, deoarece au accesul privat.
În continuare, vom completa clasa Dreptunghi cu definiţia metodelor membre:
// exemplu de clasa
#include <conio.h>
#include <iostream>
using namespace std;
class Dreptunghi {
int lungime, latime;
public:
// metode definite in corpului clasei
void setLungime (int L)
{
lungime = L;
}
int main()
{
Dreptunghi dr;
dr.setLatime(10);
dr.setLungime(20);
cout << "arie: " << dr.arie() << endl;
_getch();
return 0;
}
Ieşire
arie: 200
În afara corpului clasei, în definirea metodei arie(), se observă utilizarea unui operator nou,
numit operator de rezoluţie, fiind simbolizat prin două perechi de două puncte ( :: ). Acest operator
arată domeniul (în cazul de faţă clasa), căruia îi aparţine metoda. Menţionăm că este obligatorie
utilizarea operatorului de rezoluţie pentru definirea unei metode în afara clasei. Declaraţia (prototipul)
metodei definite în afara clasei, trebuie să fie în mod obligatoriu în corpul clasei.
Remarcăm definiţiile metodelor setLungime(int) şi setLatime(int)care au fost incluse
direct în corpul clasei Dreptunghi, datorită faptului că acestea sunt foarte simple.
Membrii lungime şi latime au modul de acces privat. Declarandu-i privaţi, interzicem
accesarea lor directă de către orice funcţie din afara clasei. Iniţializarea câmpurilor din interiorul
obiectului este posibilă, deoarece am definit metodele membru setLungime(int) şi
setLatime(int), care setează valorile câmpurilor lungime şi latime. Datorită lor, în restul
programului, nu este necesar (dar nici posibil) să se acceseze direct câmpurile clasei.
Observaţie
În cadrul exerciţiilor ce vor fi rezolvate la laboratorul de POO, toate declaraţiile de clase se vor
face în fişierele antet (header), la fel ca şi declaraţiile de alte tipuri. Tot aici vom declara şi eventualele
funcţii globale. Definiţia metodelor se va face în fişierul (fişierele) .cpp asociate antetului.
Posibilitatea de a ascunde utilizatorului unei clase detaliile ei de realizare, se numeşte
încapsulare sau abstractizare a datelor. Utilizatorului îi este oferit doar un set de membri publici,
suficienţi pentru a utiliza clasa. Aceşti membri publici constituie interfaţa clasei. Membrii inaccesibili din
exterior sunt declaraţi privaţi sau protejaţi şi realizează implementarea clasei.
Încapsularea sau abstractizarea datelor este unul dintre cele trei principii de bază ale
programării orientate pe obiecte. Celelalte două principii: moştenirea şi polimorfismul, le vom studia în
laboratoarele următoare (6 şi 7).
Putem avea mai multe obiecte instanţiate din aceeaşi clasă. Dezvoltând exemplul anterior,
putem declara al doilea obiect drept de tip Dreptunghi:
// exemplu: o clasa, doua obiecte
#include <conio.h>
#include <iostream>
using namespace std;
class Dreptunghi {
int lungime, latime;
public:
void setLungime (int L) {lungime = L;}
void setLatime (int l){ latime = l;}
int arie (void);
};
int main()
{
Dreptunghi dr;
dr.setLatime(10); dr.setLungime(20);
Dreptunghi drept;
drept.setLatime(5); drept.setLungime(6);
cout <<"arie obiect dr: "
<< dr.arie() << endl;
cout <<"arie obiect drept: "
<< drept.arie() << endl;
_getch();
return 0;
}
Ieşire
arie obiect dr: 200
arie obiect drept: 30
În acest caz, avem două instanţe de tip Dreptunghi: dr şi drept. Fiecare obiect are propriile
valori pentru câmpuri şi poate accesa metodele clasei. Se explică astfel de ce rezultatele sunt diferite,
deşi este apelată aceeaşi metodă: arie().
3. Referinţe
În C++ o funcţie poate primi parametri în două feluri – prin valoare sau prin referinţă.
Transmiterea parametrilor prin valoare este cea obişnuită, cunoscută până acum din limbajul C. Un
parametru transmis prin valoare, dacă este modificat în funcţie, nu îşi va păstra valoarea modificată în
funcţia apelantă. De exemplu, în programul de mai jos, funcţia schimba() este greşită şi nu va avea nici
un efect asupra parametrilor primiţi:
int main() {
int a = 2, b = 3;
cout << a << " " << b << endl;
schimba(a,b);//a si b raman neschimbate
cout << a << " " << b << endl;
_getch();
return 0;
}
Ieşire:
2 3
2 3
Însă în limbajul C++, putem să transmitem parametrii prin referinţă. În acest caz, modificările
efectuate în funcţie, asupra parametrilor, vor rămâne şi în funcţia apelantă. Pentru a transmite un
parametru prin referinţă, în declaraţia funcţiei vom pune operatorul & în faţa numelui parametrului. De
exemplu, funcţia schimba() cu parametri referinţă va fi declarată astfel:
void schimba(int &a, int &b);
Putem utiliza o astfel de funcţie într-un algoritm de sortare, în locul funcţiei cu pointeri
cunoscute din semestrul trecut, de la Programarea Calculatoarelor:
void schimba(int *pa, int *pb) {
int aux = *pa;
*pa = *pb;
*pb = aux;
}
4. Exerciţii
1. Să se scrie o clasă Punct care reprezintă un punct din plan. Clasa va conţine:
2. Să se implementeze clasa Multime, care să păstreze o mulţime de întregi. Clasa trebuie să aibă
următoarele metode publice:
• void init() care iniţializează câmpurile private ale mulţimii;
• void adauga(int)care adaugă un element în mulţime. În cazul în care elementul deja
există, mulţimea rămâne nemodificată;
• void extrage(int) care extrage un element din mulţime. În cazul în care elementul
nu este prezent, mulţimea rămâne neschimbată;
• void afisare() care afişează mulţimea.
Folosiţi următorul program pentru a testa mulţimea:
int main() {
Multime m;
m.init();
m.adauga(4);
m.adauga(3);
m.afisare();
m.extrage(4);
m.afisare();
m.adauga(9);
m.adauga(2);
m.afisare();
_getch();
return 0;
}
3. Să se scrie o clasă Data care să reprezinte o dată calendaristică. Clasa va conţine următorii membri:
• câmpurile zi, luna, an întregi, privaţi;
• metoda setValori(int z, int l, int a) care să seteze valorile celor trei câmpuri;
• metoda afisare() care afişează data la consolă.
Puteţi adăuga şi alţi membri dacă este cazul.
Pe baza clasei Data să se implementeze cerinţele de mai jos:
3.1
• Să se scrie un program care să citească şi să afişeze
un vector de n date.
3.2
• Să se adauge metoda int maiMare(Data data2),
care realizează compararea dintre două date. În această metodă sunt accesibile două obiecte de tip
Data. Unul este obiectul curent, iar celălalt parametrul data2. Metoda returnează 1 dacă data curentă
(din obiectul curent) este mai mare decât data2 şi 0, în caz contrar.
• Să se determine data cea mai mare din vector. Pentru
compararea datelor se va folosi metoda maiMare .
3.3
• Să se adauge metoda afisareLunga() care afişează
data în formatul „29 august 2008”. Să se afişeze datele citite în ambele formate: normal (zz.ll.aaaa) şi
lung.
• Să se adauge metoda ziDinSaptamana() care să
returneze ziua din săptamână pentru obiectul curent de tip Data. De exemplu, pentru luni va returna 1,
iar pentru duminică 7. Pentru simplitate, pentru orice an, să se considere zilele din săptămână la fel ca
pentru anul 2008, ştiind că acest an începe marţi.
De exemplu, pentru datele:
03.09.2008
21.10.2008
Rezultatul va fi:
3 septembrie 2007, miercuri
peste 365 zile –
3 septembrie 2008, miercuri
peste 48 zile –
21 octombrie 2008, marti