Kliknite tukaj, da si ogledate profil, kot ga vidijo drugi

Objekti in razredi

Delite vsebino na Facebooku
Delite vsebino na Twitterju
  V tej lekciji se bomo naučili osnovne sintakse in uporabe razredov v programskem jeziku C++.
 
 
1
 
 

C je procedualni jezik, njegov naslednik pa je C++, katerega glavna prednost je objektna usmerjenost.

Za enostaven problem si vzamimo kopico točk, katere ležijo na 2D površini. Točke se lahko premikajo in zanimajo nas razdalje med točkami.

Kako bi se lotili problema na procedularni način (funkcijsko)?

Primerek možne (neobjektne) rešitve:

#include < iostream >
#include < cmath >

using namespace std;

void izpisiTocko(int tockeX[],int tockeY[],int index_tocke)

{

cout<<"x:"<<tockeX[index_tocke]<<" y:"<<tockeY[index_tocke]<<endl;

}

double izracunajRazdaljo(int tockeX[],int tockeY[],int index_tocke1,int index_tocke2)

{

int razdaljaTockeX = tockeX[index_tocke1]-tockeX[index_tocke2];

int razdaljaTockeY = tockeY[index_tocke1]-tockeY[index_tocke2];

return sqrt(razdaljaTockeX*razdaljaTockeX+razdaljaTockeY*razdaljaTockeY);

}

void spremeniTocko(int tockeX[],int tockeY[],int index_tocke,int novX,int novY)

{

tockeX[index_tocke] = novX;

tockeY[index_tocke] = novY;

}

 

int main()

{

int tockeX[]={1,-1,3,4,5,0};

int tockeY[]={1,-4,-2,4,2,0};

spremeniTocko(tockeX,tockeY,5,2,2);

izpisiTocko(tockeX,tockeY,0);

izpisiTocko(tockeX,tockeY,5);

cout<<izracunajRazdaljo(tockeX,tockeY,0,5);

cin.get();

return 0;

}

 
 
2
 
 

Prejšna rešitev seveda deluje, ampak kaj se zgodi če želimo dodati novo dimenzijo točke (Z)? Spet novo polje podatkov. To še mogoče ne deluje kritično, ampak zamislimo si še nove dodatke k naši točki. Na primer barva, velikost, lastnik točke in še in še... s tem, ko smo dodajali lastnosti se je naš glavni program zasul s polji in nadzor, urejanje kode in vzdrževanje postane težko in nadležno.

Tukaj vlogo prevzame objektno usmerjeno programiranje. Zgornji problem bomo zato "preuredili" v objekten in skozi korake razložili kodo.

Objektna rešitev:

#include < iostream > 

#include < cmath >

using namespace std;

class TOCKA

{

private:

int x,y;

public:

TOCKA()

{

 x = this->y = 0;

}

TOCKA(int x,int y):x(x),y(y){}

void izpisiTocko()

{

cout<<"x:"<<x<<" y:"<<y<<endl;

}

void spremeniTocko(int x,int y)

{

this->x = x;

this->y = y;

}

double izracunajRazdaljo(const TOCKA& tocka)

{

int razdaljaTockeX = this->x-tocka.x;

int razdaljaTockeY = this->y-tocka.y;

return sqrt(razdaljaTockeX*razdaljaTockeX+razdaljaTockeY*razdaljaTockeY);

}

};

 

 

int main()

{

TOCKA tocka[6]; //uporabi se privzeti konstuktor ( x = y = 0 )

tocka[0].spremeniTocko(1,1); //klicanje METODE in ne FUNKCIJE.

tocka[1].spremeniTocko(-1,-4);

tocka[2].spremeniTocko(3,-2);

tocka[3] = TOCKA(4,2); //klicanje konsturkotjra

tocka[4].spremeniTocko(5,2);

tocka[5] = TOCKA(); //ne bi bilo potrebno

 

tocka[0].izpisiTocko();

tocka[5].izpisiTocko();

cout<<tocka[0].izracunajRazdaljo(tocka[5]);

 

cin.get();

return 0;

}

 

 
 
3
 
 

Lotimo se razlage od vrha do dna.

Z rezervirano besedo class naznanimo, da bomo pisali razred.

Besedi class sledi ime razreda, v našem primeru TOCKA. Uporaba velikih/malih črk ni važna, jaz uporabljam velike, da razlikujem objekte in razrede (razlaga sledi kmalu).

Imenu razreda sledi telo razreda. Podobno kot pri funkcijah ga začnemo in končamo z zavitim oklepajem ({, };) . Na koncu ne smemo pozabiti na
PODPIČJE.

 
 
4
 
 

Sedaj opazimo dve rezervirani besedi: 
-private:

-public:

Bolj kot samemu poteku programa služita ti dve programerjem, da si "zaščitijo podatke". Ker sta celo-šteivlčna tipa x in y pod določilom private lahko njuji manipuliramo samo v telesu razreda TOCKA iz main-a pa nista dosegljivi. Prevajalnik bi javil napako.

Kar pa sledi po določilu public pa je javno dosegljivo, in se lahko kliče v razredu ter izven njega.

Razred tako tvorimo z besedo class ali struct.

Med njima je majhna razlika:
Če uporabimo class, je brez uporabe določil public ali private vse privzeto PRIVATE.
Pri struct pa privzeto PUBLIC.
Obstaja še tretjo določilo (protected), vendar se ta uporablja v konceptu dedovanja, kar pa ta vodič ne posega.

 
 
 
 
 
5
 
 

Opazimo "funkcijo" TOCKA().
Njene lastnosti so:
-Da to ni funkcija, ampak je PRIVZETI konsturktor

-Ne vrača vrednosti (ni funkcija)


Konstruktor mora imenovati enako kot RAZRED.

Služi temu, da ko ustvarimo objekt (oziroma instanco razreda), priredimo njegovim spremenljivkam vrednosti.

TOCKA t;
ali
TOCKA t();
ali
TOCKA t = TOCKA();

/*
ustvarimo objekt tocka iz razreda TOCKA in pokliče se privzeti konsturuktor TOCKA();
Zadnji primer je eksplicitno klicanje konstruktorja.
Potek v času izvajanja:
1. Ustvarimo objekt t iz razreda TOCKA.
2. Poklicemo PRIVZETI konsturktor iz razreda TOCKA
3. Konsturktor ustvari objekt in ga priredi objektu t.

Da pa to ni nič posebnega je tukaj primer iz celih števil:
int a = int(3.5);
*/

V konstruktorju lahko opazimo rezervirano besedo

this z dodatkom ->

Preberi slednje če poznaš delo s kazalci, sicer preskoči:

this je kazalec na objekt zato ga je potrebno dereferencirati (da pridemo iz lokacije pomnilnika na dejanski tip). Sedaj ko smo ga dereferencirali imamo dejanski objekt katerega manipuliramo. iz njega pokličemo objektno spremenljivko y.

Če ste preskočili berite tukaj naprej:

Z oznako this-> preprosto povemo. da zahtevamo spremenljivko iz razreda katerega trenutno obdelujemo. 

Če ste pozorno opazovali spremenljivka x ni poklicana preko določila this->. Tudi pri y ne bi bilo potrebno. saj prevajalnik ne vidi vhodnih parametrov, ki bi bili enakega imena kot objektne spremenljivke.
Koristnost besede this-> sledi čez par korakov. 


Ob koncu konstruktorja TOCKA(),
se ustvari objekt ki ima x in y nastavljen na 0.




Opazimo nov konstruktor, ki sprejme dva parametra X in Y.

Zanj sem uporabil drugačno sintakso (inicializacijsko), ki je hitrejša v času izvajanja od prejšne.

/*
Primer uporabe konstruktorja:

TOCKA t(0,0);
ali
TOCKA t = TOCKA(0,0);
*/

Njegova sintaksa je sledeča
TOCKA(int vhodnix,int vhodniy)
:xOdRazreda(vhodnix),yOdRazreda(vhodniy){}

X-u iz objekta TOCKA priredi vhodni x.
Y-u iz objekta TOCKA priredi vhodni y.

V zavitih oklepajih, če hočemo, lahko izvedemo dodatne operacije.


Seveda gre ustvariti objekt brez konstruktorja, vendar to lahko vodi v težave. če mu v času izvajanja pozabimo nastaviti vrednosti.
Naprimer: izracunaj razdaljo med dvema točkama, ki nimata definiranih vrednosti?

 
 
6
 
 

Sedaj se lahko lotimo dejanskih "funkcij". Funkcijam v razredu pravimo METODE. Saj so vezane neposredno na sam objekt.

tako nam bo:

/*

void izpisiTocko(){
 cout<<"x:"<<x<<" y:"<<y<<endl;
}

*/

izpisalo x in y objekta na katerem je bila metoda klicana.

klic pa zgleda takole:

/*
   t.izpisiTocko();
*/

Ker smo prej objekt t že inicializirali s konstruktorjem

/*
  TOCKA t(0,0);
*/

ima že privzeto vrednost x in y objekta t vrednost 0.

tako nam bo izpiši točko vrnil da sta x in y enaka 0.




Pojdimo na naslednjo metodo:

void spremeniTocko(int x,int y)

{

this->x = x;

this->y = y;

}

Tukaj sedaj vidimo konkretno uporabo kazaca na sam objekt (this->).

Ker kot vhodni parameter ze sprejmemo x in y. Prevajalnik ne bi znal razlociti kateri x priredi kateremu x-u.

Tako pa mu povemo da x-u in y-u iz razreda priredi vhodna parametra x in y.

/*
   t.spremeniTocko(-1,-4);
*/

objekt t ne bo več nosil vrednosti za x in y enake 0, temveč bo x=-1 in y=-4!



Zadnja metoda se malce razlikuje od drugih, saj vrača vrednost in kot vhodni parameter sprejme objekt razreda TOCKA.

double izracunajRazdaljo(const TOCKA& tocka){...}

(
Ni potrebno brati:

Zaradi optimizacijskih postopkov pošljemo sam objekt TOCKA po referenci, kar pomeni da se v vhodni parameter nebodo skopirali podatki (trati čas) ampak se bo prenesla samo njegova lokacija v pomnilniku. Z besedo const pa dodatno najavimo, da se tocka ne sme spreminjati.
)

V tej metodi, zračunamo razmik med x in y objekta ki klice metodo in vhodnega objekta.

this->x-tocka.x;

Beseda this-> nam je že poznana. Vendar kako lahko kličemo iz objekta tocka, točko x če pa je ta private?

Spomnimo se začetka vodiča:
"
Ker sta celo-šteivlčna tipa x in y pod določilom private lahko njuji manipuliramo samo v telesu razreda TOCKA iz main-a pa nista dosegljivi.
"

Ker je tocka iz razreda TOCKA, prav tako pa je metoda izracunajRazdaljo iz razreda TOCKA, se x in y nahajata v telesu razreda TOCKA in ju lahko varno kličemo


Na koncu pa metoda vrne evklidovo razdaljo

/*
  double razdalja = t.izracunajRazdaljo(t2);
*/

 
 
7
 
 

Vredno omembe:
kadar se inicializra polje objektov se vedno kliče PRIVZETI KONSTRUKTOR (če obstaja).

/*
 TOCKA tocka[6];
*/

Torej vsaka instanca razreda TOCKA  ima x in y nastavljen na 0 po pravilih konstruktorja TOCKA()


S tem smo zaklučili osnove o razredih in objektiv v programskem jeziku C++.

Sledi še en korak, katerega si oglejte po želji.

 
 
8
 
 

Kaj če imamo v razredu kazalce? Kako jih pobrisati ko objekt neha obstajati?

V te namene imamo zraven konstruktorja tudi DESTRUKTOR.


Njegova sintaksa je sledeča:

~IMERAZREDA()
{
  //koda
}

Od konstruktorja se razlikuje v tem, da lahko obstaja samo EN in ne sprejme nobenega vhodnega parametra. Pred njim pa opazimo še znak '~' (tilda). Destruktor se izvede, ko razred neha obstajati (to je ob klicu operatorja delete nad objektom razreda ali ob koncu obsega objekta v katerem je definiran).

{
  if(nekaj)
  {
    TOCKA t;
  }
  //sedaj se pokliče DESTRUKTOR objekta t
}

Dodana koda na sliki v razred:

/*
 
private:

int x,y;

int *polje;

public:

TOCKA()

{

 polje = new int[5];

 x = this->y = 0;

}

~TOCKA()

{

if(polje) //ali polje!=NULL; preverimo ce lokacija v pomnilniku obstaja

delete []polje;

}

TOCKA(int x,int y):x(x),y(y){

 polje = NULL; //ce ne prirejamo ne pozabimo na NULL!!!

}

*/


 
 
Komentiraj
 
 
 
 
 
10.5.2014, 7:48
Supr lekcija, res lepo narejena :D. +1
 
 
 
 
13.5.2014, 22:43
Hvala !
Če so kakšna vprašanja, bom na njih z veseljem odgovoril.
 
Prijava in registracija
 
 
 
Zmaga.com ponuja brezplačno in razumljivo učenje računalniških programov, vas na enkraten način spozna z različnimi svetovnimi jeziki, s podrobno obrazloženimi recepti prikaže čare kulinarike in vam prežene strahove pred domačimi opravili.
 
 
Poleg tega lahko prebirate poučne članke, ki so namenjene širjenju naše splošne razgledanosti ter preverite svoje znanje z priljubljenim in enostavnim sistemom za preverjanje znanja. Če med vsebinami, ki se dodajajo vsak dan, ne najdete želenega znanja, je za vaša vprašanja na voljo dobro obiskan forum, kjer lahko tudi aktivno sodelujete. V primeru, da bi radi svoje praktično znanje delili z ostalimi, pa to lahko storite preko preprostega vmesnika za dodajanje vsebin. Zmagajte z znanjem z Zmaga.com!