Detyrë: Të tregohet dalja në ekran për kodin në vazhdim.
int v[4] = { 6, 2, 7, 4 };
cout << *(v + 1) + 1;
Detyrë: Të tregohet dalja në ekran për kodin në vazhdim.
int v1[3] = { 1, 2, 3 };
int v2[3] = { 4, 5, 6 };
int *p[2] = { v1, v2 };
cout << 2 * *(*(p + 1) + 1);
Supozojmë një strukturë të të dhënave Pika e cila paraqet dyshën e numrave (x,y):
struct Pika {
double x;
double y;
};
Shpesh kemi funksione të cilat ndërveprojnë me këtë strukturë:
bool baraz(Pika p1, Pika p2) {
return p1.x == p2.x && p1.y == p2.y;
}
double distanca(Pika p1, Pika p2) {
return sqrt(
pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2)
);
}
double distanca_nga_qendra(Pika p) {
return sqrt(pow(p.x, 2) + pow(p.y, 2));
}
string toString(Pika p) {
stringstream ss;
ss << "(" << p.x << ", " << p.y << ")";
return ss.str();
}
Pika konstrukto(double x, double y) {
Pika p = { x, y };
return p;
}
Pika p1 = konstrukto(6.0, 3.5);
Pika p2 = konstrukto(4.2, 7.1);
cout << "Distanca mes pikes p1=" << toString(p1)
<< " dhe pikes p2=" << toString(p2)
<< " eshte d=" << distanca(p1, p2)
<< endl;
if (baraz(p1, p2)) {
cout << "Pikat jane te barabarta.";
} else {
cout << "Pikat jane te ndryshme.";
}
Stili i tillë i programimit njihet si programim procedural.
Ekziston një stil tjetër i programimit i cili grupon të dhënat dhe funksionet mbi to në një njësi të vetme që quhet klasë.
Stili i programimit me klasa quhet programimi i orientuar në objekte (POO).
Klasa përshkruan strukturën e të dhënave si dhe ofron funksione të cilat veprojnë mbi ato të dhëna.
Të dhënat e klasës njihen si fusha, ndërsa funksionet e klasës njihen si metoda.
Të dhënat e klasës deklarohen sikur te strukturat:
class Pika {
double x;
double y;
};
Realisht, në C++ nuk ka dallim teknik ndërmjet strukturës dhe klasës.
Kontrollimi i qasjes (private, public)
Fushat private mund të lexohen vetëm nga funksionet brenda klasës.
Fushat publike mund të lexohen nga cilido bllok.
class Pika {
public: double x;
private: double y;
};
int main() {
Pika p;
p.x = 5.0; // OK.
p.y = 3.5; // Gabim, ndalohet leximi nga blloku i jashtëm.
return 0;
}
Në disa raste dëshirojmë t’i mbajmë fushat private me qëllim të ndalimit të qasjes nga blloqet e jashtme.
Kjo është një veçori kritike për arritjen e enkapsulimit.
Nëse nuk ceket, klasat e kanë qasjen e nënkuptuar private, ndërsa strukturat e kanë publike.
Nuk ka dallim tjetër ndëmjet strukturave dhe klasave.
Funksionet e klasës deklarohen bashkë me të dhënat:
class Pika {
private:
double x;
double y;
public:
double distanca_nga_qendra() {
return sqrt(pow(x, 2) + pow(y, 2));
}
};
Thirrja e metodës bëhet përmes operatorit të qasjes sikur te fushat:
Pika p = ...;
cout << p.distanca_nga_qendra();
Në këtë rast funksioni merr vlerat e pikës p.
class Pika {
private: double x, y;
public: bool baraz(Pika tjeter) {
return x == tjeter.x && tjeter.y == tjeter.y;
}
};
int main() {
Pika p1 = ..., p2 = ...;
if (p1.baraz(p2)) cout << "Te njejta";
else cout << "Te ndryshme";
return 0;
}
Vini re se si parametri i parë i funksionit sikur p1 në baraz(p1,p2) tani bëhet implicit duke marrë formën p1.baraz(p2).
Argumenti implicit që paraqet referencën kontekstuale të objektit aktual në POO quhet this.
Vlera kontekstuale this është pointer për objektin aktual.
class Personi {
private:
string emri;
int mosha;
public:
void shtyp_infot() {
cout << "Emri: " << this->emri << endl;
cout << "Mosha: " << this->mosha << endl;
}
};
Nëse kemi 2 variabla p1 dhe p2, me funksione të zakonshme kemi shënuar:
shtyp_infot(p1);
shtyp_infot(p2);
Me metoda (stili i POO) e shkruajmë:
p1.shtyp_infot();
p2.shtyp_infot();
Edhe pse po duket se thirrja p1.shtyp_infot() nuk po merr parametra,
ajo realisht mban referencën e variablës p1 gjatë thirrjes së funksionit.
Thirrjet p1.shtyp_infot() dhe p2.shtyp_infot() japin rezultate të ndryshme
pasi që ekzekutohen në kontekste të ndryshme.
Variablat tipi i të cilave është klasë i quajmë objekte ose instanca.
Konstruktori është një funksion i veçantë i cili thirret gjatë krijimit të instancës.
Zakonisht përdoren për të inicializuar gjendjen e klasës duke i dhënë vlera fushave.
Konstruktori shkruhet si metodë e cila ka emrin e klasës dhe nuk ka tip kthimi.
class Pika {
private:
double x;
double y;
public:
Pika(double x, double y) {
this->x = x;
this->y = y;
}
};
Konstruktorët mund të mbingarkohen.
Konstruktori thirret gjatë krijimit të instancës.
Thirrjet e mëposhtme janë ekuivalente:
int main() {
Pika p1 = Pika(2.5, 3);
Pika p2(2.5, 3);
return 0;
}
Konstruktori më së shpeshti përdoret për të vendosur vlera në fusha.
class Studenti {
private:
int mosha;
double notaMesatare;
public:
Studenti(int mosha, double notaMesatare) {
this->mosha = mosha;
this->notaMesatare = notaMesatare;
}
}
Vini re se dykuptimësinë e identifikatorëve e tejkalojmë përmes qasjes eksplicite me this.
Copy constructor
Në C++ secila klasë ka një konstruktor special për kopjim të objektit.
Zakonisht kjo mund të shkaktojë sjellje të papritura, prandaj shpesh do ta ndalojmë.
class Studenti {
public:
// Konstruktori i kopjimit.
Studenti(const Studenti&) { ... }
// Operatori i shoqërimit.
Studenti& operator=(const Studenti&) { ... }
};
Destruktori është bllok kodi që thirret:
Zakonisht përdoret për lirim të resurseve.
Shkruhet në formën ~Klasa() { ... }.
Nuk merr parametra e as nuk kthen asgjë.
class Klasa {
private:
int* data;
public:
Klasa() { // Konstruktori
this->data = new int { 0 };
}
~Klasa() { // Destruktori
delete this->data;
}
};
Enkapsulimi i fushave private
Zakonisht e kontrollojmë qasjen në fusha me dy metoda publike getX() dhe setX(x).
class Studenti {
private:
int mosha;
public:
int getMosha() {
return this->mosha;
}
void setMosha(int mosha) {
this->mosha = mosha;
}
};
Detyrë: Të shkruhet klasa Studenti e cila ka:
emri, mbiemri, mosha, notat[5]nota(i) e cila merr notën në pozitën i.notaMesatare().emriPlote() e cila kthen emrin dhe mbiemrin e bashkuar.shtyp() e cila shtyp në ekran të dhënat e studentit.Detyrë: Të shkruhet klasa Pika e cila ka:
x dhe y (nr. real).Pika(x,y) dhe metodat mbështjellëse të fushave.distanca(Pika tjeter).shtyp() që shtyp në ekran kordinatat në formën (x,y), psh. (4,3).Detyrë: Të shkruhet klasa Rrethi e cila ka:
rrezja (nr. real) dhe qendra (e tipit Pika nga detyra e kaluar).Rrethi(qendra,rrezja).siperfaqja() dhe perimetri().distanca(Rrethi tjeter) e cila llogarit distancën mes qendrave të rrathëve.shtyp() që shtyp në ekran qendrën dhe rrezen e rrethit.Detyrë: Të krijohet një varg me 5 instanca të tipit Rrethi nga detyra e kaluar.
shtyp().Detyrë: Të shkruhet klasa NumerKompleks me veçoritë private
re dhe im si dhe anëtarët në vijim:
NumerKompleks(re,im)shto(k), zbrit(k), shumezo(k), ku k është NumerKompleks.shto(re,im), zbrit(re,im), shumezo(re,im).shtyp(), toString().Në main të deklarohen disa instanca të tipit
NumerKompleks dhe të kryhen llogaritje të ndryshme.