V predchádzajúcej časti seriálu sme sa venovali triedam. Dnes v tom budeme pokračovať. Pozrieme sa pokročilejšiu techniku, ktorej sa hovorí dedičnosť. Dnes sa pozrieme iba na základnú, takzvanú verejnú dedičnosť, pomocou kľúčového slova public.
Začneme jednoduchou otázkou. Kto/čo je to robotník a riaditeľ. Čo majú spoločne a čo odlišne. Robotník, je nejaký zamestnanec, zamestnanec je nejaký človek, človek je nejaký cicavec a tak by sme mohli isť ďalej. Riaditeľ je v podstate tiež nejaký zamestnanec (človek, cicavec...). Čiže ma určite vlastnosti rovnaké ako robotník, ibaže môže riadiť, prideľovať mzdy, rozhodovať...
A pravé tento vzťah súvislosti vyjadruje dedičnosť. Zameriame sa iba na tri triedy. Zamestnanec, robotník a riaditeľ. „Naučíme“ zamestnanca chodiť do roboty, poberať plat, chodiť na obedy... Toto všetko robí ako robotník tak aj riaditeľ. Preto už stačí robotníka „naučiť“ iba napríklad pracovať pri páse a povedať mu, že je zamestnanec. To isté riaditeľa stačí naučiť iba rozhodovať a povedať mu, že je zamestnanec.
Dedičnosť
Zápis dedičnosti vyzerá:
Class robotnik : public zamestnanec {//funkcie triedy robotník };
V tomto prípade predpokladáme, že triedu zamestnanec už máme definovanú. Zatiaľ, budeme stále používať kľúčové slovo public. O ostatných možnostiach dedičnosti si povieme neskôr.
Teraz si toto všetko vyskúšame na nasledujúcom príklade (viem, že je dlhy, ale nie je náročný. Iba presne popisuje ku ktorým funkciám máme z ktorých tried prístup):
#include <cstdlib> #include <iostream> using namespace std; class zamestnanec //definícia triedy zamestnanec {public: //pre jednoduchosť uvediem všetky funkcie ako verejne void ChodDoRoboty(); void ChodNaObed(); void ZoberPlat(); }; class robotnik:public zamestnanec //definujeme triedu robotník, ktorá dedí po triede zamestnanec {public: void PracujPriPase(); }; class riaditel:public zamestnanec //definujeme triedu riaditeľ, ktorá dedí po triede zamestnanec {public: void Rozhoduj(); }; void zamestnanec::ChodDoRoboty() {cout<<"Idem do roboty\n"; //Pre jednoduchosť taktiež všetky činnosti nahradíme iba slovným výpisom } void zamestnanec::ChodNaObed() {cout<<"Idem na obed\n"; } void zamestnanec::ZoberPlat() {cout<<"Hura vyplata\n"; } void robotnik::PracujPriPase() {cout<<"Pracujem pri pase\n"; } void riaditel::Rozhoduj() {cout<<"Rozhodujem\n"; } int main(int argc, char *argv[]) { //Vytvorime 3 objekty 3 rôznych tried zamestnanec Fero; robotnik Jano; riaditel Palo; cout<<"Fero\n"; Fero.ChodDoRoboty(); Fero.ChodNaObed(); Fero.ZoberPlat(); //Fero.PracujPriPase(); //Fero.Rozhoduj(); cout<<"Jano\n"; Jano.ChodDoRoboty(); Jano.ChodNaObed(); Jano.ZoberPlat(); Jano.PracujPriPase(); //Jano.Rozhoduj(); cout<<"Palo\n"; Palo.ChodDoRoboty(); Palo.ChodNaObed(); Palo.ZoberPlat(); //Palo.PracujPriPase(); Palo.Rozhoduj(); system("PAUSE"); return EXIT_SUCCESS; }
Všimnite si tri triedy, deklarovane v úvode a ich vzájomné prepojenie pomocou dedičnosti. Celý príklad sa točí okolo piatich funkcii. Tri z nich sú deklarovane v triede zamestnanec, jedna v triede riaditeľ a jedna v triede robotník. V úvode funkcie main potom vytvoríme tri objekty daných tried a skúsime, ktoré funkcie sú im prístupne. Funkcie, ktoré nie sú daným objektom prístupné sú v komentároch, inak by kód nešiel skompilovať.
Objektu triedy zamestnanec sú prístupné iba tri funkcie definovane v triede zamestnanec. Objektu triedy robotník je prístupná funkcia definovaná v triede robotník, spolu s troma funkciami z triedy zamestnanec, ktoré táto trieda zdedila. Podobne aj trieda riaditeľ. Podobne by to fungovalo aj s premennými.
Dúfam, že ste vďaka tomuto príkladu pochopili o čom dedičnosť je. V najbližších dieloch sa na dedičnosť pozrieme ešte zopárkrát.
Konštruktory a deštruktory
Možno sa pýtate ako je to s konštruktormi a deštruktormí v prípade dedičnosti. Uvedomte si, že v našom prípade je trieda zamestnanec ako keby základ a trieda robotník potom nadstavba nad ňu. Preto je potrebne najprv vytvoriť a základ a až potom nadstavbu. Pri odstraňovaní objektu treba postupovať zas opačne od triedy robotník k zamestnanec. Nasledujúci príklad, je trochu upravený príklad z úvodu v ktorom vytvoríme objekt triedy robotník vo funkcii Pracuj(). Po skončení tejto funkcie sa objekt dostáva mimo svoj obor platnosti, a preto je odstránený.
#include <cstdlib> #include <iostream> using namespace std; class zamestnanec //definícia triedy zamestnanec {public: //pre jednoduchosť uvedieme iba konštruktor a deštruktor zamestnanec(); ~zamestnanec (); }; class robotnik:public zamestnanec //definujeme triedu robotník, ktorá dedí po triede zamestnanec {public: robotnik(); //konštruktor a deštruktor ~robotnik(); void PracujPriPase(); }; zamestnanec::zamestnanec() { cout<<"Konstruktor zamestnanec\n"; } zamestnanec::~zamestnanec() { cout<<"Destruktor zamestnanec\n"; } robotnik::robotnik() { cout<<"Konstruktor robotnik\n"; } robotnik::~robotnik() { cout<<"Destruktor robotnik\n"; } void robotnik::PracujPriPase() {cout<<"Pracujem pri pase\n"; } void Pracuj() {robotnik Jano; Jano.PracujPriPase(); } int main(int argc, char *argv[]) { Pracuj(); system("PAUSE"); return EXIT_SUCCESS; }
Myslím, že vďaka výstupu si tento program nevyžaduje ďalší komentár.
Prekrývanie funkcii
V odvodenej triede môžete deklarovať rovnakú funkciu ako v bázovej triede (triede, z ktorej dedíme). Tým docielime to, že keď zavoláme z odvodenej triedy túto, prekrytú, funkciu vykoná sa funkcia z odvodenej triedy a nie z bázovej. Avšak bazovú triedu úplné nestratíme, pretože ju môžeme zavolať zápisom: názov objektu .(bodka) názov bázovej triedy ::(dve dvojbodky) názov funkcie. Všetko si to ešte ukážeme na poslednom príklade v tejto časti. Ide o zjednodušený a upravený príklad z úvodu.
#include <cstdlib> #include <iostream> using namespace std; class zamestnanec //definicia triedy zamestnanec {public: void ChodNaObed(); }; class robotnik:public zamestnanec //definujeme triedu robotník, ktorá dedí po triede zamestnanec {public: void ChodNaObed(); }; void zamestnanec::ChodNaObed() { cout<<"Idem na obed\n"; } void robotnik::ChodNaObed() { cout<<"Musim robit, nejdem na obed.\n"; } int main(int argc, char *argv[]) { robotnik Jano; cout<<"Jano.ChodNaObed()\n"; Jano.ChodNaObed(); cout<<"Jano.zamestnanec::ChodNaObed()\n"; Jano.zamestnanec::ChodNaObed(); system("PAUSE"); return EXIT_SUCCESS; }
Všimnite si rozdielny výstup, podľa toho, ktorú verziu funkcie ChodNaObed() voláme.
To by bolo zatiaľ všetko. V najbližších častiach sa budeme venovať poliam, zreťazeným zoznamom, ukazovateľom a kľúčovým slovám new a delete.


mohol
Pali este si mohol do prvej triedy pre chodNaObed pridat podmienku na to ci je zamestnanec v práci a pod :)
Mohol :)
Jasne mohol, mohol by som toho pridať ešte kopu, avšak mojím cielom nebolo popísať plne funkčne funkcie a triedy iba ukazať ako čo funguje. Je samozrejme, že v praxi vyzerá kód omnoho zložitejšie a prepracovanejšie. tento kód by však zbytočne zabral pomaly tri članky a bolo by to zbytočné.