dedičnosť a spriatelené triedy

54
Dedičnosť a spriatelené Dedičnosť a spriatelené triedy triedy

Upload: galvin-hoffman

Post on 30-Dec-2015

66 views

Category:

Documents


11 download

DESCRIPTION

Dedičnosť a spriatelené triedy. Osnova prednášky. Princípy a typy dedičnosti Konštruktory, deštruktory a dedičnosť Viacnásobná dedičnosť Dedičnosť a smerníky Virtuálne funkcie Spriatelené triedy. Dedičnosť. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Dedičnosť a spriatelené triedy

Dedičnosť a spriatelené Dedičnosť a spriatelené triedytriedy

Page 2: Dedičnosť a spriatelené triedy

Osnova prednáškyOsnova prednášky

Princípy a typy dedičnostiPrincípy a typy dedičnosti Konštruktory, deštruktory a dedičnosťKonštruktory, deštruktory a dedičnosť Viacnásobná dedičnosťViacnásobná dedičnosť Dedičnosť a smerníkyDedičnosť a smerníky Virtuálne funkcieVirtuálne funkcie Spriatelené triedySpriatelené triedy

Page 3: Dedičnosť a spriatelené triedy

DedičnosťDedičnosť

V objektovo orientovanom programovaní môže mať každá trieda svojho potomka - odvodenú triedu, ktorá od nej preberie všetky - odvodenú triedu, ktorá od nej preberie všetky dáta a metódy (okrem konštruktora a deštruktora). dáta a metódy (okrem konštruktora a deštruktora).

Odvodená trieda môže mať okrem zdedených dát a metód svoje vlastné, ktorými sa odlíši od svojho rodiča. , ktorými sa odlíši od svojho rodiča.

Metódy, ktoré odvodená trieda zdedila, môže mať upravené podľa podľa svojich potrieb.svojich potrieb.

Programátor má možnosť ovplyvňovať prístup odvodenej triedy k dátam a metódam svojho rodiča. Teda aj keď odvodená trieda . Teda aj keď odvodená trieda niečo zdedí, nemusí jej byť dovolené to používať.niečo zdedí, nemusí jej byť dovolené to používať.

Každá trieda môže mať ľubovoľne veľa potomkov aj rodičov..

Page 4: Dedičnosť a spriatelené triedy

Chránené dáta a metódyChránené dáta a metódy Doteraz sme sa stretli len s dvomi typmi dát a metód: verejnými Doteraz sme sa stretli len s dvomi typmi dát a metód: verejnými

(public) a súkromnými (private). Vďaka možnosti dedenia ale (public) a súkromnými (private). Vďaka možnosti dedenia ale vzniká nová požiadavka – vzniká nová požiadavka – niektoré dáta a metódy by mali byť síce súkromné, ale odvodené triedy by k nim mali mať prístup. Takéto . Takéto dáta a metódy sa nazývajú dáta a metódy sa nazývajú chránené (protected)..

Ak sa teda v programe bude vyskytovať aj dedičnosť, vo Ak sa teda v programe bude vyskytovať aj dedičnosť, vo všeobecnosti bude štruktúra triedy vyzerať takto:všeobecnosti bude štruktúra triedy vyzerať takto:class meno_triedy{

private:...protected:...public:...

};

Page 5: Dedičnosť a spriatelené triedy

Typy dediTypy dedičnostičnosti Tak ako dáta a metódy, aj Tak ako dáta a metódy, aj dedičnosť môže byť troch rôznych

druhov::

1. 1. Súkromná (private) (private)

2. 2. Chránená (protected) (protected)

3. 3. Verejná (public) (public) Súkromná dedičnosť znamená, že všetky dáta a metódy znamená, že všetky dáta a metódy

zdedené od rodičovskej triedy budú v odvodenej triede súkromné.zdedené od rodičovskej triedy budú v odvodenej triede súkromné. Chránená dedičnosť znamená, že verejné a chránené dáta a znamená, že verejné a chránené dáta a

metódy rodičovskej triedy budú v odvodenej triede chránené. metódy rodičovskej triedy budú v odvodenej triede chránené. Súkromné dáta a metódy zostávajú súkromnými.Súkromné dáta a metódy zostávajú súkromnými.

Verejná dedičnosť znamená, že prístupnosť dát a metód sa znamená, že prístupnosť dát a metód sa presne zachováva – verejné budú verejnými, chránené presne zachováva – verejné budú verejnými, chránené chránenými a súkromné súkromnými.chránenými a súkromné súkromnými.

Štandardná dedičnosť v C++ je súkromná. Ak si programátor praje . Ak si programátor praje iný typ, musí to explicitne zadať.iný typ, musí to explicitne zadať.

Page 6: Dedičnosť a spriatelené triedy

Typy dedičnostiTypy dedičnosti Prehľad typov dedičnosti v C++:Prehľad typov dedičnosti v C++:

DEDIČNOSŤDEDIČNOSŤ SÚKROMNÉSÚKROMNÉ

ÚDAJEÚDAJECHRÁNENÉCHRÁNENÉ

ÚDAJEÚDAJEVEREJNÉVEREJNÉ

ÚDAJEÚDAJE

SÚKROMNÁSÚKROMNÁ

CHRÁNENÁCHRÁNENÁ

VEREJNÁVEREJNÁ

SÚKROMNÉSÚKROMNÉ SÚKROMNÉSÚKROMNÉ SÚKROMNÉSÚKROMNÉ

SÚKROMNÉSÚKROMNÉ

SÚKROMNÉSÚKROMNÉ

CHRÁNENCHRÁNENÉÉ

CHRÁNENCHRÁNENÉÉ

CHRÁNENCHRÁNENÉÉ

VEREJNÉVEREJNÉ

Page 7: Dedičnosť a spriatelené triedy

DedičnosťDedičnosť Vytvorenie odvodenej triedy:Vytvorenie odvodenej triedy:

class odvodená_trieda:typ_dedičnosti rodičovská_trieda{

...};

Príklad: Rodič a dieťa: Rodič a dieťa

Vytvoríme dve triedy – Vytvoríme dve triedy – RodičRodič a a DieťaDieťa, pričom , pričom DieťaDieťa bude bude potomkom triedy potomkom triedy RodičRodič. .

RodičRodič bude mať nasledujúce údaje: meno, priezvisko, bydlisko, bude mať nasledujúce údaje: meno, priezvisko, bydlisko, číslo účtu a stav účtu. číslo účtu a stav účtu.

DieťaDieťa bude mať všetky uvedené údaje a navyše ešte meno a bude mať všetky uvedené údaje a navyše ešte meno a priezvisko rodiča.priezvisko rodiča.

Na tomto príklade si vyskúšame rôznu prístupnosť dát a rôzne Na tomto príklade si vyskúšame rôznu prístupnosť dát a rôzne typy dedičnosti.typy dedičnosti.

Page 8: Dedičnosť a spriatelené triedy

DedičnosťDedičnosť Trieda Trieda RodičRodič::

class Rodic{

private: int stav_uctu;protected: string meno, priezvisko, bydlisko; string cislo_uctu;public: Rodic() {} Rodic(string m, string p, string b, string cu, int su):

meno(m),priezvisko(p),bydlisko(b),cislo_uctu(cu),stav_uctu(su) {} string Meno() {return meno;} string Priezvisko() {return priezvisko;} string Bydlisko() {return bydlisko;} string CisloUctu() {return cislo_uctu;} int StavUctu() {return stav_uctu;}

};

Page 9: Dedičnosť a spriatelené triedy

DedičnosťDedičnosť Trieda Trieda DieťaDieťa::

class Dieta:private Rodic{

private: string meno_rodica, priezvisko_rodica;public: Dieta(string m, string p, string b, string c_u,string m_r,string

p_r); string MenoRodica() {return meno_rodica;} string PriezviskoRodica() {return priezvisko_rodica;} void PredstavSa();

}; V tomto prípade je dedičnosť typu V tomto prípade je dedičnosť typu private, to znamená, že , to znamená, že všetko, čo

Dieťa zdedí od triedy Rodič, bude súkromné. To znamená, že mimo . To znamená, že mimo triedy (napr. v hlavnom programe), nemá triedy (napr. v hlavnom programe), nemá DieťaDieťa prístupné žiadne dáta, prístupné žiadne dáta, ale nemôže použiť ani metódy ale nemôže použiť ani metódy MenoMeno(), (), PriezviskoPriezvisko(), (), BydliskoBydlisko(), (), ČísloÚčtuČísloÚčtu() a () a StavÚčtuStavÚčtu(). Pre svoje súkromné účely však môže všetky (). Pre svoje súkromné účely však môže všetky tieto metódy použiť. Pridáme teda do triedy tieto metódy použiť. Pridáme teda do triedy DieťaDieťa metódu metódu PredstavSaPredstavSa(), (), pomocou ktorej pomocou ktorej DieťaDieťa oznámi svoje meno, priezvisko a bydlisko. Číslo oznámi svoje meno, priezvisko a bydlisko. Číslo účtu a ani jeho stav nebude môcť dieťa oznamovať.účtu a ani jeho stav nebude môcť dieťa oznamovať.Navyše, stav_účtu nie je pre Navyše, stav_účtu nie je pre DieťaDieťa vôbec prístupný, keďže je to vôbec prístupný, keďže je to súkromný údaj triedy triedy RodičRodič. . DieťaDieťa teda nemôže s ním nijako narábať. teda nemôže s ním nijako narábať.

Page 10: Dedičnosť a spriatelené triedy

DedičnosťDedičnosť Definujeme metódy triedy Dieťa:Definujeme metódy triedy Dieťa:

Dieta:: Dieta(string m, string p, string b, string c_u,string m_r,string p_r) {

meno=m;priezvisko=p;bydlisko=b;cislo_uctu=c_u;meno_rodica=m_r;priezvisko_rodica=p_r;

}

void Dieta::PredstavSa(){

cout<<"Volam sa "<<meno<<" "<<priezvisko<<endl;cout<<"Moje bydlisko je "<<bydlisko<<endl;

}Všimnime si, že Všimnime si, že stav_účtustav_účtu nie je v konštruktore vôbec nie je v konštruktore vôbec inicializovaný. inicializovaný. DieťaDieťa nemá v tomto prípade oprávnenie ho nemá v tomto prípade oprávnenie ho akokoľvek používať.akokoľvek používať.

Page 11: Dedičnosť a spriatelené triedy

DedičnosťDedičnosť Hlavný program:Hlavný program:

Rodic Otec("Pavol","Horvath","Piestany","012011/0100",150000);Dieta Syn("Misko","Horvath", "Piestany","012011/0100", "Pavol","Horvath");cout<<"Volam sa "<<Otec.Meno()<<" "<<Otec.Priezvisko()<<endl;cout<<"Moje bydlisko je "<<Otec.Bydlisko()<<endl;cout<<"Moje cislo uctu je "<<Otec.CisloUctu()<<endl;cout<<"Na ucte mam "<<Otec.StavUctu()<<" Sk"<<endl;Syn.PredstavSa();cout<<"Moj otec je "<<Syn.MenoRodica()<<" "<<Syn.PriezviskoRodica()<<endl;Výstup:Výstup:Volam sa Pavol HorvathMoje bydlisko je PiestanyMoje cislo uctu je 012011/0100Na ucte mam 150000 Sk

Volam sa Misko HorvathMoje bydlisko je PiestanyMoj otec je Pavol Horvath

Page 12: Dedičnosť a spriatelené triedy

DedičnosťDedičnosť Teraz na ten istý prípad použijeme dedičnosť typu Teraz na ten istý prípad použijeme dedičnosť typu public. To . To

znamená, že znamená, že DieťaDieťa nebude potrebovať metódu nebude potrebovať metódu Predstav_saPredstav_sa(), (), pretože bude môcť oznámiť údaje v hlavnom programe rovnako pretože bude môcť oznámiť údaje v hlavnom programe rovnako ako ako RodičRodič. Súkromné dáta triedy . Súkromné dáta triedy RodičRodič, teda , teda stav_účtustav_účtu, zostanú , zostanú však preň naďalej nedostupné. Môže síce použiť metódu však preň naďalej nedostupné. Môže síce použiť metódu StavÚčtuStavÚčtu(), nemá to však zmysel, keďže nemôže túto hodnotu (), nemá to však zmysel, keďže nemôže túto hodnotu inicializovať ani s ňou inak narábať.inicializovať ani s ňou inak narábať.

Trieda Dieťa bude teda vyzerať takto:Trieda Dieťa bude teda vyzerať takto:class Dieta:public Rodic{

private: string meno_rodica, priezvisko_rodica;public: Dieta(string m, string p, string b, string c_u,string

m_r,string p_r); string MenoRodica() {return meno_rodica;} string PriezviskoRodica() {return priezvisko_rodica;}

};

Page 13: Dedičnosť a spriatelené triedy

DedičnosťDedičnosť Hlavný program:Hlavný program:

Rodic Otec("Pavol","Horvath","Piestany","012011/0100",150000);Dieta Syn("Misko","Horvath", "Piestany","012011/0100", "Pavol","Horvath");cout<<"Volam sa "<<Otec.Meno()<<" "<<Otec.Priezvisko()<<endl;cout<<"Moje bydlisko je "<<Otec.Bydlisko()<<endl;cout<<"Moje cislo uctu je "<<Otec.CisloUctu()<<endl;cout<<"Na ucte mam "<<Otec.StavUctu()<<" Sk"<<endl;cout<<"Volam sa "<<Syn.Meno()<<" "<<Syn.Priezvisko()<<endl;cout<<"Moj otec je "<<Syn.MenoRodica()<<" "<<Syn.PriezviskoRodica()<<endl;cout<<"Moj otec ma cislo uctu "<<Syn.CisloUctu()<<endl;cout<<"Stav jeho uctu je "<<Syn.StavUctu()<<endl;

Page 14: Dedičnosť a spriatelené triedy

Konštruktor a dedičnosťKonštruktor a dedičnosť V predchádzajúcom príklade obsahovala trieda V predchádzajúcom príklade obsahovala trieda RodičRodič okrem okrem

konštruktora s parametrami aj prázdny konštruktor. Malo to svoje konštruktora s parametrami aj prázdny konštruktor. Malo to svoje opodstatnenie, ktoré si teraz objasníme.opodstatnenie, ktoré si teraz objasníme.

Stačí si uvedomiť, aký je mechanizmus vytvárania odvodenej Stačí si uvedomiť, aký je mechanizmus vytvárania odvodenej triedy. Keďže odvodená trieda má svojho rodiča, triedy. Keďže odvodená trieda má svojho rodiča, najprv sa zavolá koštruktor rodiča a až potom konštruktor potomka. Keďže . Keďže rodičovská trieda môže mať niekoľko konštruktorov, musíme rodičovská trieda môže mať niekoľko konštruktorov, musíme povedať, ktorý z nich sa má zavolať. povedať, ktorý z nich sa má zavolať. Ak priamo neuvedieme, ktorý konštruktor chceme, automaticky sa zavolá prázdny konštruktor, , ktorý musí byť k dispozícii.ktorý musí byť k dispozícii.

Ak do každého konštruktora pridáme výpis informácie, o ktorý Ak do každého konštruktora pridáme výpis informácie, o ktorý konštruktor ide, dostaneme takýto výstup:konštruktor ide, dostaneme takýto výstup:

Page 15: Dedičnosť a spriatelené triedy

Konštruktor a dedičnosťKonštruktor a dedičnosť Ako sme už naznačili, v Ako sme už naznačili, v konštruktore potomka môžeme využiť ľubovoľný

konštruktor rodiča.. Príklad: Konštruktor triedy : Konštruktor triedy DieťaDieťa s využitím konštruktora triedy s využitím konštruktora triedy RodičRodič

Keďže Keďže DieťaDieťa má niekoľko parametrov prebratých od svojej rodičovskej má niekoľko parametrov prebratých od svojej rodičovskej triedy, nemusíme ich priamo inicializovať v jeho konštruktore. Môžeme triedy, nemusíme ich priamo inicializovať v jeho konštruktore. Môžeme použiť takýto zápis:použiť takýto zápis:Dieta:: Dieta:: Dieta(string m, string p, string b, string c_u,string s_u,string m_r,string p_r): Rodic(m,p,b,c_u,s_u){{

cout<<"konstruktor dietata"<<endl;cout<<"konstruktor dietata"<<endl;meno_rodica= meno_rodica= m_rm_r;;priezvisko_rodica=priezvisko_rodica=p_rp_r;;

}} Týmto spôsobom sa nastavia všetky údaje, ktoré má aj Týmto spôsobom sa nastavia všetky údaje, ktoré má aj RodičRodič. Zostáva . Zostáva

nastaviť už len zvyšné údaje. Všimnime si, že týmto spôsobom sa podarí nastaviť už len zvyšné údaje. Všimnime si, že týmto spôsobom sa podarí nastaviť dokonca aj údaj nastaviť dokonca aj údaj stav_účtustav_účtu, keďže jeho inicializácia prebieha v tele , keďže jeho inicializácia prebieha v tele rodičovskej triedy.rodičovskej triedy.

Page 16: Dedičnosť a spriatelené triedy

Konštruktor a dedičnosťKonštruktor a dedičnosť

V tomto prípade dostaneme takýto výstup (pri použití dedičnosti V tomto prípade dostaneme takýto výstup (pri použití dedičnosti typu public):typu public):

Page 17: Dedičnosť a spriatelené triedy

Deštruktor a dedičnosťDeštruktor a dedičnosť Kým pri vytváraní objektu odvodenej triedy sa najskôr zavolá Kým pri vytváraní objektu odvodenej triedy sa najskôr zavolá

konštruktor rodičovskej triedy a až potom konštruktor podtriedy, konštruktor rodičovskej triedy a až potom konštruktor podtriedy, pri zániku objektu je postup presne opačný – pri zániku objektu je postup presne opačný – najskôr sa zavolá deštruktor potomka a až potom deštruktor rodičovskej triedy..

Schéma vytvárania a zániku objektu odvodenej triedy je teda Schéma vytvárania a zániku objektu odvodenej triedy je teda takáto:takáto:

konštruktor rodičovskej triedykonštruktor rodičovskej triedy

deštruktor rodičovskej triedydeštruktor rodičovskej triedy

konštruktor odvodenej triedykonštruktor odvodenej triedy

deštruktor odvodenej triedydeštruktor odvodenej triedy

Page 18: Dedičnosť a spriatelené triedy

Deštruktor a dedičnosťDeštruktor a dedičnosť Príklad: Triedy : Triedy RodičRodič a a DieťaDieťa s deštruktormi s deštruktormi

Do tried Do tried RodičRodič a a DieťaDieťa doplníme jednoduché deštruktory, ktoré len doplníme jednoduché deštruktory, ktoré len oznámia, že objekt zaniká:oznámia, že objekt zaniká:~Rodic() {cout<<"Zanika objekt triedy Rodic"<<endl;}~Dieta() {cout<<"Zanika objekt triedy Dieta"<<endl;}

Dostaneme výstup:Dostaneme výstup:

Page 19: Dedičnosť a spriatelené triedy

Viacnásobná dedičnosťViacnásobná dedičnosť Rozlišujeme dva typy viacnásobnej dedičnosti:Rozlišujeme dva typy viacnásobnej dedičnosti:

1. 1. Viacúrovňová dedičnosť – odvodená trieda sa stane rodičovskou – odvodená trieda sa stane rodičovskou triedtriedoou pre ďalšiu odvodenú trieduu pre ďalšiu odvodenú triedu

2. 2. Dedičnosť od viacerých rodičov – odvodená trieda dedí naraz od – odvodená trieda dedí naraz od dvoch alebo viacerých trieddvoch alebo viacerých tried

Samozrejme tieto typy dedičnosti môžu byť rôzne kombinovanéSamozrejme tieto typy dedičnosti môžu byť rôzne kombinované

Page 20: Dedičnosť a spriatelené triedy

Viacúrovňová dedičnosťViacúrovňová dedičnosť V tomto prípade sa odvodená trieda stane rodičom ďalšej triedy, V tomto prípade sa odvodená trieda stane rodičom ďalšej triedy,

pričom postup sa môže opakovať. pričom postup sa môže opakovať. Konštruktory sa spúšťajú od triedy, ktorá je v hierarchii najvyššie, po tú, ktorá je najnižšie. Deštruktory sa spúšťajú v opačnom poradí.

Príklad: Supermarket: Supermarket

Vytvoríme program, ktorý na základe kódu vyhľadá príslušný Vytvoríme program, ktorý na základe kódu vyhľadá príslušný tovar a podá o ňom informácie. Budeme uvažovať tri triedy: tovar a podá o ňom informácie. Budeme uvažovať tri triedy:

1. Trieda 1. Trieda TovarTovar – bude obsahovať kód tovaru, názov a cenu – bude obsahovať kód tovaru, názov a cenu

2. Trieda 2. Trieda PotravinaPotravina – bude potomkom triedy – bude potomkom triedy TovarTovar, bude navyše , bude navyše obsahovať dátum spotrebyobsahovať dátum spotreby

3. Trieda 3. Trieda ZeleninaZelenina – bude potomkom triedy – bude potomkom triedy PotravinaPotravina a navyše a navyše bude obsahovbude obsahovaať údaj o triede akostiť údaj o triede akosti

Aby sme mohli sledovať priebeh vytvárania a zániku objektov, Aby sme mohli sledovať priebeh vytvárania a zániku objektov, vytvoríme v týchto triedach aj deštruktory, ktorých úlohou bude vytvoríme v týchto triedach aj deštruktory, ktorých úlohou bude len informovať o tom, ktorý deštruktor sa práve spúšťa.len informovať o tom, ktorý deštruktor sa práve spúšťa.

Page 21: Dedičnosť a spriatelené triedy

Viacúrovňová dedičnosťViacúrovňová dedičnosť Naskôr definujeme triedu Naskôr definujeme triedu TovarTovar::

class Tovar{

protected: int kod; string nazov; float cena;public: Tovar(int k, string n, float c):kod(k),nazov(n),cena(c) {cout<<"Vytvara sa objekt triedy Tovar"<<endl;} ~Tovar() {cout<<"Zanika objekt triedy Tovar"<<endl;} int Kod() {return kod;} string Nazov() {return nazov;} float Cena() {return cena;}

};

Page 22: Dedičnosť a spriatelené triedy

Viacúrovňová dedičnosťViacúrovňová dedičnosť Trieda Trieda PotravinaPotravina::

class Potravina:public Tovar{

protected: string datum_spotreby;public: Potravina(int k, string n, float c, string

ds):Tovar(k,n,c),datum_spotreby(ds) {cout<<"Vytvara sa objekt triedy Potravina"<<endl;} ~Potravina() {cout<<"Zanika objekt triedy Potravina"<<endl;} string DatumSpotreby() {return datum_spotreby;}

};

Page 23: Dedičnosť a spriatelené triedy

Viacúrovňová dedičnosťViacúrovňová dedičnosť

Trieda Trieda ZeleninaZelenina::

class Zelenina:public Potravina{

private: int trieda;public: Zelenina(int k, string n, float c, string ds, int

t):Potravina(k,n,c,ds),trieda(t) {cout<<"Vytvara sa objekt triedy Zelenina"<<endl;} ~Zelenina() {cout<<"Zanika objekt triedy Zelenina"<<endl;} int Trieda() {return trieda;}

};

Page 24: Dedičnosť a spriatelené triedy

Viacúrovňová dedičnosťViacúrovňová dedičnosť Hlavný program:Hlavný program:

int main(){Zelenina z[3]={Zelenina(123,"Paprika",45,"12.9.2007",1), Zelenina(540,"Uhorka",17,"15.9.2007",2), Zelenina(673,"Kapusta",34,"22.9.2007",1)};int kod;cout<<"Zadaj kod: "<<endl;cin>>kod;for (int i=0;i<3;i++) if (z[i].Kod()==kod) break;if (i==3) cout<<"Tovar s takymto kodom nemame na sklade"<<endl;else{cout<<z[i].Nazov()<<endl<<z[i].Cena()<<" Sk/kg"<<endl;cout<<"Datum spotreby: "<<z[i].DatumSpotreby()<<endl;cout<<"Trieda: "<<z[i].Trieda()<<endl;}return 0;}

Page 25: Dedičnosť a spriatelené triedy

Viacúrovňová dedičnosťViacúrovňová dedičnosť Výstup:Výstup:

Page 26: Dedičnosť a spriatelené triedy

Dedičnosť od viacerých Dedičnosť od viacerých rodičovrodičov

V tomto prípade trieda dedí dáta a metódy od viacerých tried naraz.V tomto prípade trieda dedí dáta a metódy od viacerých tried naraz. Syntax:Syntax:

class odvodená_trieda:typ_dedičnosti1 trieda1, typ_dedičnosti2 trieda2 ...{

...}

Konštruktory sa v tomto prípade spúšťajú v poradí zľava doprava, deštruktory sprava doľava..

Príklad: Spiderman: SpidermanVytvoríme tri triedy:Vytvoríme tri triedy:

ČlovekČlovek – s údajmi meno, vek, zamestnanie – s údajmi meno, vek, zamestnanie

ZvieraZviera – s údajmi druh, počet končatín a informáciou o schopnostiach – s údajmi druh, počet končatín a informáciou o schopnostiach (lietanie, plávanie, lezenie po stenách)(lietanie, plávanie, lezenie po stenách)

SpidermanSpiderman – potomok tried Človek a Zviera, navyše s informáciou, či – potomok tried Človek a Zviera, navyše s informáciou, či bol hrdinom filmubol hrdinom filmu

Page 27: Dedičnosť a spriatelené triedy

Dedičnosť od viacerých Dedičnosť od viacerých rodičovrodičov Trieda Trieda ČlovekČlovek::

class Clovek{

protected: string meno;

int vek; string zamestnanie;public: Clovek(string m, int v, string

z):meno(m),vek(v),zamestnanie(z) {cout<<"Vytvara sa novy Clovek"<<endl;} ~Clovek() {cout<<"Zanika Clovek"<<endl;} string Meno() {return meno;} int Vek() {return vek;} string Zamestnanie() {return zamestnanie;}

};

Page 28: Dedičnosť a spriatelené triedy

Dedičnosť od viacerých Dedičnosť od viacerých rodičovrodičov Trieda Trieda ZvieraZviera::

class Zviera{

protected: string druh;

int pocet_koncatin; bool lietanie, plavanie, lezenie;public: Zviera(string d, int pk, bool li, bool p, bool le):

druh(d),pocet_koncatin(pk),lietanie(li),plavanie(p),lezenie(le) {cout<<"Vytvara sa nove Zviera"<<endl;}

~Zviera() {cout<<"Zanika Zviera"<<endl;} string Druh() {return druh;} int PocetKoncatin() {return pocet_koncatin;} void VymenujSchopnosti();

};

Page 29: Dedičnosť a spriatelené triedy

Dedičnosť od viacerých Dedičnosť od viacerých rodičovrodičov Definujeme metódu Definujeme metódu VymenujSchopnostiVymenujSchopnosti():():

void Zviera::VymenujSchopnosti(){

if (lietanie) cout<<"Viem lietat"<<endl;if (plavanie) cout<<"Viem plavat"<<endl;if (lezenie) cout<<"Viem liezt po stenach"<<endl;

} Trieda Trieda SpidermanSpiderman::

class Spiderman:public Clovek, public Zviera{

private: bool film;public: Spiderman(string m,int v,string z,string d,int pk,bool li,bool p,bool

le,bool f): Clovek(m,v,z),Zviera(d,pk,li,p,le),film(f) {cout<<"Vznika novy druh Spiderman"<<endl;} ~Spiderman() {cout<<"Spiderman zanika"<<endl;} void Film() {if (film) cout<<"Bol som hrdinom filmu!"<<endl;}

};

Page 30: Dedičnosť a spriatelené triedy

Dedičnosť od viacerých Dedičnosť od viacerých rodičovrodičov

int main(){

Spiderman SM("Peter Parker",30,"novinar","pavuk",4,false,false,true,true);cout<<"Volam sa "<<SM.Meno()<<endl;cout<<"Mam "<<SM.Vek()<<" rokov"<<endl;cout<<"Zivim sa ako "<<SM.Zamestnanie()<<endl;cout<<"Zaroven som "<<SM.Druh()<<endl;cout<<"Pocet mojich koncatin je "<<SM.PocetKoncatin()<<endl;SM.VymenujSchopnosti();SM.Film();return 0;

}

Page 31: Dedičnosť a spriatelené triedy

Dedičnosť od viacerých Dedičnosť od viacerých rodičovrodičov

Výstup:Výstup:

Page 32: Dedičnosť a spriatelené triedy

Dedičnosť od viacerých Dedičnosť od viacerých rodičovrodičov Nie je povolené, aby mali obidve rodičovské funkcie parameter s

rovnakým menom alebo funkciu s rovnakým menom! Príklad: Trieda : Trieda ZvieraZviera s údajom s údajom vekvek

Do triedy Do triedy ZvieraZviera doplníme údaj doplníme údaj vekvek spolu s metódou spolu s metódou VekVek():():class Zviera{

protected: ... int vek;public: ... int Vek() {return vek;}

};

Page 33: Dedičnosť a spriatelené triedy

ZhrnutieZhrnutie

Každá trieda môže mať ľubovoľne veľa potomkov aj rodičovských tried

Odvodená trieda dedí od svojho rodiča všetko okrem konštruktora a deštruktora

Odvodená trieda môže mať vlastné dáta a metódy, ktorými sa líši od rodičovskej triedy. Obsah metód, ktoré sú zdedené, sa môže tiež upraviť podľa potrieb odvodenej triedy.

Pri vytváraní objektu odvodenej triedy sa najprv spustí konštruktor rodičovskej triedy, potom konštruktor odvodenej triedy. Pri deštruktoroch je postup opačný.

Viacnásobná dedičnosť môže byť dvoch typov: viacúrovňová dedičnosť a dedičnosť od viacerých rodičov

Page 34: Dedičnosť a spriatelené triedy

Dedičnosť a smerníkyDedičnosť a smerníky V súvislosti s dedičnosťou prichádza na scénu doteraz nevyužitá V súvislosti s dedičnosťou prichádza na scénu doteraz nevyužitá

vlastnosť smerníkov na objekty – vlastnosť smerníkov na objekty – ak je smerník deklarovaný ako smerník na objekt rodičovskej triedy, môže byť použitý aj tak, aby ukazoval na objekt odvodenej triedy. Obmedzením v tomto . Obmedzením v tomto prípade je, že prípade je, že cez takýto smerník môžeme pristupovať len k takým dátam a metódam, ktoré mala aj rodičovská trieda..

Príklad: Smerník na objekt triedy Príklad: Smerník na objekt triedy TovarTovarPoužijeme smerník na objekt triedy Použijeme smerník na objekt triedy TovarTovar na prístup k objektu na prístup k objektu triedy triedy ZeleninaZelenina::

Zelenina z[3]={Zelenina(123,"Paprika",45,"12.9.2007",1),Zelenina(540,"Uhorka",17,"15.9.2007",2),Zelenina(673,"Kapusta",34,"22.9.2007",1)};

Tovar *smernik=z;cout<<"Smernik ukazuje na tuto zeleninu: "<<endl;cout<<smernik->Nazov()<<endl<<smernik->Cena()<<" Sk/kg"<<endl;

Page 35: Dedičnosť a spriatelené triedy

Dedičnosť a smerníkyDedičnosť a smerníky Výstup:Výstup:

Smernik ukazuje na tuto zeleninu:Paprika45 Sk/kg

Ak by sme však chceli pristupovať k iným údajom ako Ak by sme však chceli pristupovať k iným údajom ako názovnázov a a cenacena, kompilátor by vyhlásil chybu:, kompilátor by vyhlásil chybu:Tovar *smernik=z;cout<<"Smernik ukazuje na tuto zeleninu: "<<endl;cout<<smernik->Nazov()<<endl<<smernik->Cena()<<" Sk/kg"<<endl;cout<<"Datum spotreby: "<<smernik->DatumSpotreby()<<endl;

Page 36: Dedičnosť a spriatelené triedy

Virtuálne funkcieVirtuálne funkcie Virtuálna funkcia je funkcia, ktorá je deklarovaná v rámci rodičovskej je funkcia, ktorá je deklarovaná v rámci rodičovskej

triedy a je predefinovaná odvodenou triedou. V odvodenej triede môže triedy a je predefinovaná odvodenou triedou. V odvodenej triede môže mať teda funkcia úplne iný obsah.mať teda funkcia úplne iný obsah.

Platí pravidlo, že Platí pravidlo, že predefinovaná funkcia musí mať rovnaký počet aj typ parametrov aj rovnakú návratovú hodnotu ako funkcia rodičovskej triedy..

Trieda Mamavirtuálna metódaMetóda Upeč_koláč::

4 vajíčka4 vajíčka

300 g múky300 g múky

2 dl oleja2 dl oleja

200 g cukru200 g cukru

prášok do pečivaprášok do pečiva

ovocieovocie

Trieda DcéraMetóda Upeč_koláč::

4 vajíčka4 vajíčka

300 g múky300 g múky

100 g masla100 g masla

2 dl mlieka2 dl mlieka

200 g cukru200 g cukru

prášok do pečivaprášok do pečiva

ovocieovocie

Page 37: Dedičnosť a spriatelené triedy

Virtuálne funkcieVirtuálne funkcie Ak chceme funkciu ozAk chceme funkciu označiť ako virtuálnu, dosiahneme to vložením načiť ako virtuálnu, dosiahneme to vložením

kľúčového slova kľúčového slova virtual pred deklaráciu funkcie. pred deklaráciu funkcie. Toto označenie je potrebné len v rodičovskej triede..

Pri definovaní funkcie (mimo tela triedy) (mimo tela triedy) už kľúčové slovo virtual neuvádzame!

Predefinovanie virtuálnej triedy odvodenou triedou sa inak nazýva Predefinovanie virtuálnej triedy odvodenou triedou sa inak nazýva aj aj prehodnotenie (overriding).

Virtuálne funkcie sú vlastne ďalšou formou polymorfizmu, keďže Virtuálne funkcie sú vlastne ďalšou formou polymorfizmu, keďže funkcia s jedným menom môže pre každú triedu vykonávať rôzne funkcia s jedným menom môže pre každú triedu vykonávať rôzne inštrukcie.inštrukcie.

Príklad: Supermarket s výpisom informácií o tovare: Supermarket s výpisom informácií o tovare

Do tried Do tried TovarTovar, , PotravinaPotravina a a ZeleninaZelenina doplníme funkciu doplníme funkciu InfoInfo, ktorá , ktorá vypíše informácie o danom tovare. Vypísané informácie sa budú vypíše informácie o danom tovare. Vypísané informácie sa budú pre každú triedu líšiť. V triede pre každú triedu líšiť. V triede TovarTovar a a PotravinaPotravina bude funkcia bude funkcia deklarovaná ako virtuálna, v triede deklarovaná ako virtuálna, v triede ZeleninaZelenina to už tak nemusí byť. to už tak nemusí byť.

Page 38: Dedičnosť a spriatelené triedy

Virtuálne funkcieVirtuálne funkcie Trieda Trieda TovarTovar::

class Tovar{

protected: int kod; string nazov; float cena;public: Tovar(int k, string n, float c):kod(k),nazov(n),cena(c)

{cout<<"Vytvara sa objekt triedy Tovar"<<endl;} ~Tovar() {cout<<"Zanika objekt triedy Tovar"<<endl;} int Kod() {return kod;} string Nazov() {return nazov;} float Cena() {return cena;} virtual void Info();

};

Page 39: Dedičnosť a spriatelené triedy

Virtuálne funkcieVirtuálne funkcie Trieda Potravina:Trieda Potravina:

class Potravina:public Tovar{

protected: string datum_spotreby;public: Potravina(int k, string n, float c, string

ds):Tovar(k,n,c),datum_spotreby(ds){cout<<"Vytvara sa objekt triedy Potravina"<<endl;}

~Potravina() {cout<<"Zanika objekt triedy Potravina"<<endl;} string DatumSpotreby() {return datum_spotreby;} virtual void Info();

};

Page 40: Dedičnosť a spriatelené triedy

Virtuálne funkcieVirtuálne funkcie Trieda Zelenina:Trieda Zelenina:

class Zelenina:public Potravina{

private: int trieda;public: Zelenina(int k, string n, float c, string ds, int

t):Potravina(k,n,c,ds),trieda(t){cout<<"Vytvara sa objekt triedy Zelenina"<<endl;}

~Zelenina() {cout<<"Zanika objekt triedy Zelenina"<<endl;} int Trieda() {return trieda;} void Info();

};

Page 41: Dedičnosť a spriatelené triedy

Virtuálne funkcieVirtuálne funkcie Definícia funkcie Definícia funkcie InfoInfo() pre každú triedu:() pre každú triedu:

void Tovar::Info(){

cout<<"Tovar s kodom "<<kod<<endl;cout<<nazov<<endl<<cena<<" Sk"<<endl;

}void Potravina::Info(){

cout<<"Tovar s kodom "<<kod<<endl;cout<<nazov<<endl<<cena<<" Sk"<<endl;cout<<"Datum spotreby: "<<datum_spotreby<<endl;

}void Zelenina::Info(){

cout<<"Tovar s kodom "<<kod<<endl;cout<<nazov<<endl<<cena<<" Sk/kg"<<endl;cout<<"Datum spotreby: "<<datum_spotreby<<endl;cout<<"Trieda: "<<trieda<<endl;

}

Page 42: Dedičnosť a spriatelené triedy

Virtuálne funkcieVirtuálne funkcie Tovar t(309,"Chladnicka",15000);

Potravina p(598,"Udeny losos",135,"19.9.2007");Zelenina z(439,"Cibula",20,"16.9.2007",2);t.Info();p.Info();z.Info();

Page 43: Dedičnosť a spriatelené triedy

Virtuálne funkcieVirtuálne funkcie Funkcie Funkcie InfoInfo() pre každú triedu môžeme prepísať aj tak, že () pre každú triedu môžeme prepísať aj tak, že

využijeme príslušnú funkciu rodičovskej triedy:využijeme príslušnú funkciu rodičovskej triedy:void Tovar::Info(){

cout<<"Tovar s kodom "<<kod<<endl;cout<<nazov<<endl<<cena<<" Sk"<<endl;

}

void Potravina::Info(){

Tovar::Info();cout<<"Datum spotreby: "<<datum_spotreby<<endl;

}

void Zelenina::Info(){

Potravina::Info();cout<<"Trieda: "<<trieda<<endl;

}

Page 44: Dedičnosť a spriatelené triedy

Virtuálne funkcie a smerníkyVirtuálne funkcie a smerníky Predchádzajúci príklad by bol fungoval, aj keby funkcia Predchádzajúci príklad by bol fungoval, aj keby funkcia InfoInfo() ()

nebola označená ako virtuálna. Skutočný význam virtuálnych nebola označená ako virtuálna. Skutočný význam virtuálnych funkcií sa ukáže napr. pri použití smerníkov.funkcií sa ukáže napr. pri použití smerníkov.

Už sme si hovorili, že smerník na rodičovskú triedu môže v Už sme si hovorili, že smerník na rodičovskú triedu môže v skutočnosti ukazovať aj na odvodenú triedu. skutočnosti ukazovať aj na odvodenú triedu. Ak však chceme zavolať metódu, ktorá je v odvodenej triede predefinovaná, musí byť táto metóda v rodičovskej triede označená ako virtuálna, aby , aby program vedel správne rozoznať, ktorú verziu má použiť.program vedel správne rozoznať, ktorú verziu má použiť.

Majme napr. smerník na trieduMajme napr. smerník na triedu Tovar Tovar, ktorý bude ukazovať na , ktorý bude ukazovať na objekt triedy objekt triedy ZeleninaZelenina::Zelenina z(439,"Cibula",20,"16.9.2007",2);Tovar *smernik=&z;Ak chceme zavolaAk chceme zavolať funkciu ť funkciu InfoInfo(), t.j.(), t.j.smernik->Info();program má na výber funkciu program má na výber funkciu InfoInfo triedy triedy TovarTovar a triedy a triedy ZeleninaZelenina. . Správnu verziu (teda funkciu triedy Správnu verziu (teda funkciu triedy ZeleninaZelenina) zavolá vďaka tomu, ) zavolá vďaka tomu, že je funkcia že je funkcia InfoInfo v triede v triede TovarTovar označená ako virtuálna. označená ako virtuálna.

Page 45: Dedičnosť a spriatelené triedy

Virtuálne funkcie a smerníkyVirtuálne funkcie a smerníky Príklad: Supermarket s poľom smerníkov: Supermarket s poľom smerníkov

Vytvoríme pole smerníkov na objekt typu Vytvoríme pole smerníkov na objekt typu TovarTovar, pričom ale smerníky , pričom ale smerníky budú môcť ukazovať aj na objekty typu budú môcť ukazovať aj na objekty typu PotravinaPotravina a a ZeleninaZelenina. Potom . Potom si dáme vypísať informácie o všetkých prvkoch poľa.si dáme vypísať informácie o všetkých prvkoch poľa.

Tovar *t[3]= {new Tovar(309,"Chladnicka",15000),new Potravina(598,"Udeny losos",135,"19.9.2007"),new Zelenina(439,"Cibula",20,"16.9.2007",2)};

for (int i=0;i<3;i++) t[i]->Info();

Ak by funkcia Ak by funkcia InfoInfo() nebola deklarovaná ako virtuálna, zavolala by sa () nebola deklarovaná ako virtuálna, zavolala by sa vždy funkcia patriaca triede vždy funkcia patriaca triede TovarTovar. Dostali by sme nasledujúci . Dostali by sme nasledujúci výstup:výstup:

Page 46: Dedičnosť a spriatelené triedy

Virtuálne funkcie a smerníkyVirtuálne funkcie a smerníky

Ak však máme funkciu Ak však máme funkciu InfoInfo() deklarovanú ako virtuálnu () deklarovanú ako virtuálnu (minimálne v rodičovskej triede (minimálne v rodičovskej triede TovarTovar), program je schopný ), program je schopný rozoznať, ktorú funkciu rozoznať, ktorú funkciu InfoInfo() má zavolať. Dostaneme teda výstup: () má zavolať. Dostaneme teda výstup:

Page 47: Dedičnosť a spriatelené triedy

Virtuálny deštruktorVirtuálny deštruktor Zatiaľ čo konštruktor nemôže byť virtuálny, deštruktor môže. V . V

niektorých prípadoch je to dokonca žiadúce.niektorých prípadoch je to dokonca žiadúce. Príklad: Supermarket s virtuálnymi deštruktormi: Supermarket s virtuálnymi deštruktormi

Ak si v predchádzajúcom príklade dáme vypísať informácie o Ak si v predchádzajúcom príklade dáme vypísať informácie o konštruktoroch a deštruktoroch, dostaneme nasledujúci výstup:konštruktoroch a deštruktoroch, dostaneme nasledujúci výstup:

Vidíme, že sa pre objekty všetkých tried zavolal len deštruktor Vidíme, že sa pre objekty všetkých tried zavolal len deštruktor triedy Tovar.triedy Tovar.

Page 48: Dedičnosť a spriatelené triedy

Virtuálny deštruktorVirtuálny deštruktor Ak chceme, aby sa zavolali správne deštruktory, musíme Ak chceme, aby sa zavolali správne deštruktory, musíme

deštruktor v rodičovskej triede deštruktor v rodičovskej triede TovarTovar označiť ako virtuálny: označiť ako virtuálny:

class Tovar{

protected: int kod; string nazov; float cena;public: Tovar(int k, string n, float c):kod(k),nazov(n),cena(c)

{cout<<"Vytvara sa objekt triedy Tovar"<<endl;} virtual ~Tovar() {cout<<"Zanika objekt triedy

Tovar"<<endl;} int Kod() {return kod;} string Nazov() {return nazov;} float Cena() {return cena;} virtual void Info();

};

Page 49: Dedičnosť a spriatelené triedy

Virtuálny deštruktorVirtuálny deštruktor V tomto prípade sa už zavolajú správne deštruktoryV tomto prípade sa už zavolajú správne deštruktory

Page 50: Dedičnosť a spriatelené triedy

ZhrnutieZhrnutie

Smerník na objekt rodičovskej triedy môže byť použitý aj tak, aby ukazoval na objekt odvodenej triedy. Prístupné sú však potom len dáta a metódy, ktoré mala aj rodičovská trieda.

Virtuálna funkcia je funkcia, ktorá existuje už v rodičovskej triede a v odvodenej triede môže byť jej obsah predefinovaný. Takéto predefinovanie sa nazýva aj prehodnotenie alebo overriding.

Prehodnotená funkcia odvodenej triedy musí mať rovnaký počet aj typ parametrov a rovnakú návratovú hodnotu ako funkcia rodičovskej triedy

Deštruktor môže byť virtuálny, konštruktor nie Virtuálne funkcie sa uplatňujú najmä pri využití spoločných

smerníkov na objekt rodičovskej a odvodenej triedy

Page 51: Dedičnosť a spriatelené triedy

Spriatelené triedySpriatelené triedy Ak máme v triede súkromné dáta a chceme, aby iná trieda mala k Ak máme v triede súkromné dáta a chceme, aby iná trieda mala k

nim prístup, môžeme to zabezpečiť tým, že ju označíme za nim prístup, môžeme to zabezpečiť tým, že ju označíme za spriatelenú (friend). .

Príklad: Trieda : Trieda DieťaDieťa ako spriatelená trieda triedy ako spriatelená trieda triedy Rodič RodičDo triedyDo triedy Dieťa Dieťa chceme doplniť funkciu chceme doplniť funkciu VyberZÚčtuVyberZÚčtu, ktorá zmenší , ktorá zmenší stav účtu o zadanú čiastku. Aby trieda stav účtu o zadanú čiastku. Aby trieda DieťaDieťa mohla pristupovať k mohla pristupovať k údaju údaju stav_účtustav_účtu, musí byť v triede , musí byť v triede RodičRodič označená ako spriatelená: označená ako spriatelená:class Rodic{

friend class Dieta;private: int stav_uctu;protected: string meno, priezvisko, bydlisko; string cislo_uctu;public: ...

};

Page 52: Dedičnosť a spriatelené triedy

Spriatelené triedySpriatelené triedy Trieda Trieda DieťaDieťa bude obohatená o novú metódu: bude obohatená o novú metódu:

class Dieta:public Rodic{

private: string meno_rodica, priezvisko_rodica;public: Dieta(string m, string p, Rodic r); ~Dieta() {cout<<"Zanika objekt triedy Dieta"<<endl;} string MenoRodica() {return meno_rodica;} string PriezviskoRodica() {return priezvisko_rodica;} void PredstavSa(); void VyberZUctu(int suma) {stav_uctu-=suma;}

};

Page 53: Dedičnosť a spriatelené triedy

Spriatelené triedySpriatelené triedy Hlavný program:Hlavný program:

Rodic Otec("Pavol","Horvath","Piestany","012011/0100",150000);Dieta Syn("Misko","Horvath", Otec);cout<<"Volam sa "<<Otec.Meno()<<" "<<Otec.Priezvisko()<<endl;cout<<"Moje bydlisko je "<<Otec.Bydlisko()<<endl;cout<<"Moje cislo uctu je "<<Otec.CisloUctu()<<endl;cout<<"Na ucte mam "<<Otec.StavUctu()<<" Sk"<<endl;cout<<"Volam sa "<<Syn.Meno()<<" "<<Syn.Priezvisko()<<endl;cout<<"Moj otec je "<<Syn.MenoRodica()<<" "<<Syn.PriezviskoRodica()<<endl;cout<<"Moj otec ma cislo uctu "<<Syn.CisloUctu()<<endl;cout<<"Stav jeho uctu je "<<Syn.StavUctu()<<" Sk"<<endl;Syn.VyberZUctu(130000);cout<<"Po mojom vybere mu na ucte ostalo "<<Syn.StavUctu()<<" Sk"<<endl;

Page 54: Dedičnosť a spriatelené triedy

Spriatelené triedySpriatelené triedy Dostaneme výstup:Dostaneme výstup:

Volam sa Pavol HorvathMoje bydlisko je PiestanyMoje cislo uctu je 012011/0100Na ucte mam 150000 Sk

Volam sa Misko HorvathMoj otec je Pavol HorvathMoj otec ma cislo uctu 012011/0100Stav jeho uctu je 150000 SkPo mojom vybere mu na ucte zostalo 20000 Sk