Programovanie v jazyku C++
Objektovo orientované programovanie
Trieda a objekty
Základnou vlastnosťou
objektovo-orientovaných jazykov je možnosť tvorby nových dátových typov
nazývaných triedy. Trieda z filozofického pohladu abstrahuje spoločné vlastnosti
jej inštancií, objektov. Za triedu by sme mohli prehlásiť aj napríklad
dátový typ int a všetky čísla typu int za inštancie tejto triedy. C++ je
ale na rozdiel od napr. Javy alebo Smalltalku hybridným jazykom a na to,
aby sme mohli nejaký dátový typ prehlásiť za triedu musia byť splnené niektoré
podmienky.
Základnými vlastnosťami triedy sú
-
abstrakcia
-
zapúzdrenie (encapsulation)
-
modularita
-
hierarchia
-
typovosť
-
perzistencia
-
súčinnosť (concurrency)
Objekt ako inštancia triedy musí mať nasledujúce vlastnosti
-
Identita: jednoznačné ‘zaradenie’ objektu, odlišujúce ho od iných objektov
-
Atribúty: vlastnosti popisujúce informácie vo vnútri objektu
-
Chovanie: odozva objektu na operácie, ktoré sú mu priradené alebo na ktorých
sa zúčastňuje
-
Stav: aktuálny mód chovania sa objektu, ktorý závisí od jeho predchádzajúcej
histórie
-
Asociácie: predlohy pre vzťahy objektu s inými objektami
-
Klasifikácia: k akému druhu vecí objekt patrí
Je zrejmé, že jednoduchý dátový typ, ako napr. int tieto požiadavky nespĺňa.
Na tomto mieste treba spomenúť, že niektoré programovacie jazyky hlavne
z databázovej oblasti o sebe prehlasujú, že sú objektovo orientované, napriek
tomu nemajú vyššie spomenuté vlastnosti. Pre takéto jazyky sa zaužívalo
označené object based.
Vytvorme
triedu Ratio reprezentujúcu množinu racionálnych
čísel. Trieda Ratio musí obsahovať dva atribúty
- čitatela a menovatela a metódy na manipuláciu s atribútmi. Od triedy
Ratio
budeme požadovať, aby bola kompatibilná s ostatnými štandardnými dátovými
typmi C++. Pre znázornenie tried a vzťahov medzi triedami budeme používať
sémantiku OMT. Trieda Ratio v sémantike OMT potom bude mať tvar podla obrázka.
Od triedy Ratio budeme vyžadovať, aby mala
také isté vlastnosti, ako ktorýkoľvek iný dátový typ. Musíme vedieť vytvoriť
jednotlivé objekty, polia objektov, vytvárať objekty staticky aj dynamicky.
Požadované
vlastnosti triedy Ratio
Ratio ra; // racionalne cislo 0/1
Ratio rb(3); // racionalne cislo 3/1
Ratio rc(3,4); // racionalne cislo 3/4
Ratio rd[10]; // pole 10 racionalnych cisel 0/1
Ratio *re; // smernik na racionalne cislo
Deklarácia triedy Ratio sa v C++ podobá deklarácii
štruktúry. Okrem atribútov triedy obsahuje trieda ešte metódy triedy a
metódy inštancií. Metódy triedy patria triede objektov, typickými metódami
triedy sú metódy na vytváranie a mazanie objektov - konštruktor a deštruktor.
Metódy objektov sú určené na manipuláciu s objektami, v objektovo orientovanej
terminológii je tento pojem zhodný s pojmom správy posielanej objektu.
Deklarácia
jednoduchého prototypu triedy Ratio
class Ratio {
protected:
int numerator; // citatel
int denominator; // menovatel
public:
Ratio(); // konstruktory
Ratio(int);
Ratio(int, int);
int numerator(); // pristupove metody k atributom
int denominator();
};
Deklarácie
tried sú zvyčajne umiestnené v hlavičkových súboroch (header file).
Je vhodné pomenovať hlavičkový súbor podla triedy, ktorá je v ňom deklarovaná.
Prípona hlavičkového súboru závisí od operačného systému počítača, zvyčajne
býva .hpp alebo .H. Implementácia metód býva v zdrojových súboroch (source
file) s označením .cpp alebo .C.
Deklarácia triedy začína klúčovým slovom class
nasledovaným menom triedy. Riadok
protected:
vymedzuje viditelnosť časti deklarácie triedy v dedičnej štruktúre. Atribúty
a metódy ktoré nasledujú za týmto klúčovým slovom budú viditelné pre eventuálnych
potomkov triedy Ratio, nie sú ale prístupné
pre objekty iných tried. Je to akási forma rodinného vlastníctva. Okrem
tohoto typu môže byť deklarované výhradné súkromné vlastníctvo typu private
- atribúty a metódy sú prístupné len tým objektom triedy, v ktorej sú deklarované
alebo komunistické vlastníctvo typu public
- ktokolvek môže manipulovať s atribútmi a používať metódy.
Časť deklarácie
int numerator;
int denominator;
deklaruje atribúty triedy. Je potrebné vedieť, že okrem užívatelom deklarovaných
atribútov triedy pridáva kompilátor k atribútom ešte jeden atribút, pomocou
ktorého je definovaná identita objektov triedy. Je ním smerník takého
dátového typu, ako je trieda sama a jeho meno je this.
Pri vytvorení inštancie triedy - nového objektu obsahuje tento smerník
adresu začiatku pamäťového priestoru, kde je objekt umiestnený.
Za deklaráciou "verejnej" časti triedy nasledujú deklarácie metód.
Prvými troma sú konštruktory. Konštruktor sa od bežnej metódy alebo funkcie
odlišuje tým, že nevracia žiadnu hodnotu. Naše tri konštruktory nám zabezpečujú
vytváranie rôznych druhov objektov podla našich požiadaviek
Ratio();
Ratio(int);
Ratio(int, int);
C++ nám umožňuje tvorbu funkcií alebo metód s rovnakým menom a rôznymi
typmi argumentov a návratových hodnôt. Toto je nazývané preťaženie (overloading)
mena funkcie. Za týmto zázrakon sa v skutočnosti skrýva jednoduchý mechanizmus
zámeny mien funkcií kompilátorom. Kompilátor si vytvára pred procesom kompilácie
nové mená funkcií, ktoré pozostávajú z pôvodného mena a prefixov resp.
postfixov, ktoré závisia od argumentov funkcie, jej eventuálnej príslušnosti
k nejakej triede a návratovej hodnoty.
Pretože naše tri konštruktory v podstate realizujú tú istú operáciu
- inicializáciu racionálneho čísla rozličným množstvom argumentov, je vhodné
konštruktory zlúčiť do jedného. V C++ môžeme funkciu deklarovať s prednastavenými
(default) argumentami:
Ratio(int=0, int=1);
Pokial použijeme
prednastavené argumenty funkcie, nemôžeme už pre danú kombináciu argumentov
použiť preťaženie mena funkcie, pretože nám kompilátor vyhlási nejednoznačnosť
mena funkcie.
Trieda môže
mať neobmedzené množstvo konštruktorov (za podmienok uvedených výššie),
ale najviac jeden deštruktor.