Úvod do cpp 7

41
ÚVOD DO CPP 7 Dědičnost - pokračování konstruktory a destruktory v procesu dědění vícenásobná dědičnost virtuální základní třídy

Upload: stanislav-nikita

Post on 14-Mar-2016

27 views

Category:

Documents


0 download

DESCRIPTION

ÚVOD DO CPP 7. Dědičnost - pokračování konstruktory a destruktory v procesu dědění vícenásobná dědičnost virtuální základní třídy. 7. Dědičnost - pokračování 7.1 - řízení přístupu k základní třídě 7.2 - chráněné členy třídy 7.3 - konstruktory a destruktory v procesu dědění - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: ÚVOD DO CPP 7

ÚVOD DO CPP 7

Dědičnost - pokračováníkonstruktory a destruktory v procesu dědění

vícenásobná dědičnostvirtuální základní třídy

Page 2: ÚVOD DO CPP 7

7. Dědičnost - pokračování7.1 - řízení přístupu k základní třídě7.2 - chráněné členy třídy7.3 - konstruktory a destruktory v procesu dědění7.4 - vícenásobná dědičnost7.5 - virtuální základní třídy

Page 3: ÚVOD DO CPP 7

Dědičnosti představuje jeden ze základních nástrojů objektového programování. Umožňuje vytvářet z existujících tříd odvozené třídy, které dědí vlastnosti svých základních, bázových tříd. Terminologie:Místo označení odvozená třída se používá názvu dceřina třída, potomek . Základní třída se nazývá bázová třída, rodičovská třída a pod. Terminologie není zcela ustálená.Při procesu dědění není nutné mít přímo zdrojový text metodrodičovských tříd, ale pouze jejich deklarace v hlavičkovém souboru. Přeložené funkce mohou být uloženy v knihovně a lze je připojit až při sestavování programu.

Page 4: ÚVOD DO CPP 7

Nedědí se:- konstruktor. Je však možné explicitní vyvolání konstruktoru základní třídy- destruktor. Je automaticky vyvoláván v destruktoru odvozené třídy.- přetížený operátor přířazení = . Pokud není nově explicitně definován pro odvozenou třídu, bude použit operátor předka.

Využití zděděných prvků v konstrukci odvozené třídy.Zděděné prvky se dělí podle přístupového práva na:1) Nepřístupné - jsou to zděděné soukromé prvky základní ( rodíčovské ) třídy .Práce s těmito prvky je možná pouze voláním zděděných přístupových metod zakladní třídy. Není možné je přímo využívat ve vlastních metodách odvozené třídy.

2) Chráněné - jsou využitelné ve vlastních metodách odvozené třídy. Nejsou přístupné z vnějšku.

3) Veřejné - jsou využitelné ve vlastních metodách odvozené třídy. Jsou přístupné i z vnějšku.

V deklaraci odvozené třídy je možné doplnit libovolně další prvky a v její implementaci lze využívat zděděné přístupné prvky( tj. chráněné a veřejné ).

Page 5: ÚVOD DO CPP 7

Řízení přístupu k základní třídě, základní pojmy.Třída, která se dědí , je základní třída.Třída, vzniklá děděním je odvozená třída.

Odvozená třída používá obecný formát specifikace :

class jméno_odvozené_třídy : specifikátor_přístupu jméno základní třídy { //..atributy, metody... } ;

Specifikátor_přístupu určuje, jak jsou členy základní třídy děděny odvozenou třídou.Většinou bývá specifikátor přístupu explicitně uveden.Není-li specifikátor přístupu uveden, považuje se implicitně za private.Specifikátor přístupu je jedním z klíčových slov - public - protected - private

Page 6: ÚVOD DO CPP 7

7.2 Zavedení CHRÁNĚNÝCH ČLENŮ, přístup protected. Důvod zavedení chráněných členů :Metody odvozené třídy nemají přístup k privátním členům základní třídy.Jestliže odvozená třída potřebuje přístup k některému z členů základní třídy, musí být tento člen veřejný.Požadavek: Ponechat členu základní třídy přítupové právo private, ale dovolit k němu přístup metodám odvozené třídy. Tomuto požadavku odpovídá zavedení přístupového specifikátoru protectedpro chráněný člen. Je ekvivalentní specifikátoru private s tou výjimkou, že chráněné členy ( protected) základní třídy jsou přístupné i metodám těch tříd,které byly z této základní třídy odvozeny.Vně základní nebo odvozené třídy nejsou chráněné členy ( protected ) přístupné.Specifikátor přístupu protected může být uveden kdekoliv v deklaraci třídy, avšak jeho typické umístění je po deklaraci privátních členů, před členy veřejnými.Syntaxe: class jméno_třídy { // privátní členy protected: // chráněné členy public: // veřejné členy } ;

Page 7: ÚVOD DO CPP 7

Přístupová práva ke členům třídy - souhrn :Rekapitulace tří možných specifikací přístupu ke členům třídy:1) public: veřejné členy může používat kterákoliv funkce nebo inicializátor

2) private: soukromé, privátní členy může používat pouze: - členské funkce ( metoda ) - členské inicializátory - přátelé třídy, t.j. funkce a třídy deklarované v ní jako friendSpecifikace private je ve třídách implicitní.

3) protected: chráněné členy mohou používat pouze - členské funkce - členské inicializátory - přátelé třídy a také - členské funkce ( metody ) tříd odvozených z této třídy a jejich přátelé.

Page 8: ÚVOD DO CPP 7

DĚDĚNÍ - změna přístupových práv v závislosti na způsobu dědění, odvození třídy nevirtuálním děděním základní třídy .Základní třída může být děděna třemi způsoby a to se specifikátorem přístupu 1) public 2) protected 3) private.

Způsob 1) - syntaxe: class Odvozena : public Zakladni { /*...*/ } ;

- veřejné členy základní třídy se stávají veřejnými členy třídy odvozené - chráněné členy základní třídy se stávají chráněnými členy třídy odvozené - k privátním členům základní třídy nemá odvozená třída přístup.( metody)Platí: Předek základní třída <----------- odvozená třída členy: protected ....................... zůstávají protected public .............................zůstávají public private nemá přístup

Třída základní je veřejným předkem třídy odvozené.

Page 9: ÚVOD DO CPP 7

Způsob 2) Synaxe:

class Odvozena : private Zakladni { /*...*/ } ;

- veřejné členy základní třidy se stávají soukromými ( privátními ) členy třídy odvozené

- chráněné členy základní třídy se stávají soukromými ( privátními ) členy třídy odvozené.

- k privátním členům základní třídy nemá třída odvozená přístup.

Třída základní je privátním předkem třídy odvozené.

Platí: základní třída <----------- odvozená třída protected ..................... private public............................ private private nemá přístup

Page 10: ÚVOD DO CPP 7

Způsob 3) Syntaxe:

class Odvozena : protected Zakladni { /*...*/ } ;

- veřejné členy základní třídy se stávají chráněnými členy třídy odvozené

- chráněné členy základní třídy se stávají chráněnými členy třídy odvozené.

- k privátním členům třídy základní nemá třída odvozená přístup.

Třída základní je chráněným předkem třídy odvozené.Platí: základní třída <----------- odvozená třída protected......................protected public.......................... protected private nemá přístup

Page 11: ÚVOD DO CPP 7

Příklad přístupu ke členům třídy. Základní třída je děděna jako veřejná public.

class Zakladni_trida{ private: void privatni_metoda() { /*...*/} protected: void chranena_metoda() { /*...*/} public : void verejna_metoda() { /*...*/}}; // end Zakladni_trida……………………………

class Odvozena_trida : public Zakladni_trida { public: void fce() { // privatni_metoda(); //fce() ji nemuže použít, fce() není // metodou základní třídy, nemá k ní přístup

chranena_metoda(); // OK -může ji použít, protože fce()je //metodou třídy odvozené verejna_metoda();//OK - fce() ji může použít, je veřejným členem třídy Zakladni_trida }// end fce( )}; // end Odvozena_trida……………………………………………

Page 12: ÚVOD DO CPP 7

class Dalsi_odvozena : public Odvozena_trida { public: void funkcedalsi(){ chranena_metoda(); //OK - funkcedalsi() je členská fce //třídy nepřímo odvozené (indirekt) ze třídy Zakladni_trida. }};// end třídy Dalsi_odvozena……………………………………………………

int main(){ Odvozena_trida Ob; //Ob. privatni_metoda(); // nelze //Ob. chranena_metoda(); // nelze, ekvivalent private Ob. verejna_metoda(); /*OK, veřejný člen v Zakladni_trida i v Odvozena_trida při dědění public */

Dalsi_odvozena Obdalsi; Obdalsi.funkcedalsi(); //OK veřejná v Dalsi_odvozena Obdalsi.fce(); /* OK fce( ) je veřejná ve třídě Odvozena_trida */ Obdalsi.verejna_metoda(); //OK veřejná ve třídě Zakladni return 0;}

Page 13: ÚVOD DO CPP 7

Příklad - přístup vnitřní, metody vůči atributům.viz metoda zobraz_soucet() { atribut x, atribut y}Zakladni třída je veřejně přístupným předkem třídy Odvozena.Privátní atribut x základní třídy je ve třídě odvozené pro její metody nedostupný, zůstává privátní, nezáleží na tom, jak byl děděn.Proto je chybný přímý přístup metody zobraz_soucet() k privátní proměnné xzákladní třídy. */class Zakladni { int x; // standardně privátnípublic: void nastav_x(int n) { x=n;} void zobraz_x() { cout << x << '\n';}};// end Zakladni…………………………………class Odvozena : public Zakladni{ int y; // standardně privátnípublic: void nastav_y( int n) { y=n;} void zobraz_y() { cout << y << '\n';} //ale!!!!void zobraz_soucet() { cout << x+y << '\n'; } /*chyba !!metoda třídy Odvozena se pokouší o přímý přístup k privátní proměnné x třídy Zakladni ............... */};

Page 14: ÚVOD DO CPP 7

REDEKLARACERedeklarace umožňuje změnit přístupová práva pro zděděnou složku.Syntaxe: jméno_třídy_původu:: jmeno fceV odvozené třídě pro ni stačí uvést odpovídající modifikátor přístupových práv, včetně úplného odkazu t.j.včetně jména rodičovské třídy.Nelze deklarovat libovolný přístup, lze pouze obnovit minulá přístupová práva. Příklad redeklarace přístupu k zobraz_x( ) :Redeklarace z private na public. Proto můžeme metodu volat v těle funkce main( ). příklad:Class odvozena{Private: int x;public:/* REDEKLARACE přístupového specifikátoru metody zobraz_x() a metody nastav_x() z private zpět na public */Zakladni::zobraz_x;Zakladni::nastav_x;};Příklad:/* základní třída je děděna se specifikátorem private.Program ukazuje možnost změnit specifikátor přístupu, vyvolaný děděním, private, pomocí redeklarece v odvozené třídě na přístupový specifikátor public */

Page 15: ÚVOD DO CPP 7

class Zakladni{ int x;public: void nastav_x(int n) { x=n;} void zobraz_x() { cout << x << '\n';}};// end zakladni..................................

//ODVOZENÁ třída dědí PRIVÁTNĚ:class Odvozena : private Zakladni{ int y;public:/* REDEKLARACE přístupového specifikátoru metody zobraz_x() a metody nastav_x() z private zpět na public */Zakladni::zobraz_x;Zakladni::nastav_x; void nastav_y( int n) { y=n;} void zobraz_y() { cout << y << '\n'; }};//end odvozene

Page 16: ÚVOD DO CPP 7

int main(){ Odvozena objekt;/* BEZ REDEKLARACE : objekt.nastav_x(10); CHYBA ! nastav_x() se stala následkem dědění se specifikátorem přístupu private privátní ve třídě odvozená a není proto z vnějšku přístupná.Totéž platí pro zobraz_x()............................................................................Přístup k metodě je ŘEŠENÝ REDEKLARACÍ přístupového specifikátoru ve třídě Odvozena (viz redeklarace ze specifikátoru private metod zobraz_x()a nastav(x) ve tride Odvozena na specifikátor public:) */

objekt.nastav_x(10); // OK - Chyba odstraněna // redeklarací objekt.nastav_y(20); cout<< "Vypis:\n"; cout <<"x = "; objekt.zobraz_x(); // OK - Chyba odstraněna // redeklarací cout << "y = "; objekt.zobraz_y(); system("Pause"); return 0;}

Page 17: ÚVOD DO CPP 7

7.3 DĚDIČNOST - konstruktory a destruktory

Konstruktory základní i odvozené třídy jsou spouštěny v pevně stanovenémpořadí.

Konstruktor základní třídy je spouštěn před konstruktorem třídy odvozené. To umožňuje provést v základní třídě inicializaci,která musí být dokončena před případnou inicializací třídy odvozené.

Pro destruktory platí opačné pořadí.Destruktor odvozené třídy musí být volán před destruktorem základní třídy. Obrácený postup není možný. Je to logický postup, protože základní třída tvoří základ třídy odvozené.Destruktor odvozené třídy musí být vyvolán před tím,než objekt přestává existovat.

Page 18: ÚVOD DO CPP 7

Příkad:Spouštění konstruktorů a destruktorů základní a odvozené třídy . */class Zakladni { public:// konstruktorZakladni() { cout<<"Konstruktor zakladni tridy\n"; }// destruktor~Zakladni() { cout << "Destruktor zakladni tridy\n"; getchar(); }};// end základní třídy……………………………………………………

class Odvozena : public Zakladni { public://konstruktor Odvozena() { cout << "Konstruktor odvozene tridy\n"; }//destruktor ~ Odvozena() { cout << "Destruktor odvozene tridy\n"; }};// end odvozené třídy ……………………………………………………..

Page 19: ÚVOD DO CPP 7

int main(){ Odvozena objekt; system("Pause"); return 0;}/* vypis: Konstruktor zakladni tridy Konstruktor odvozene tridy Destruktor odvozene tridy Destruktor zakladni tridy */

Page 20: ÚVOD DO CPP 7

Předávání argumentů konstruktorům základní a odvozené třídy.

1)Předání argumentů konstruktoru odvozené třídy :Nejjednodužší je předání argumentů konstruktoru odvozené třídy. V tomto případu se argumenty předávají obvyklým způsobem.Příklad :/* předání argumentu konstruktoru odvozené třídy class Odvozena. */class Zakladni { public:// konstruktor: Zakladni() { cout << "Konstruktor zakladni tridy\n";}// destruktor ~Zakladni(){ cout << "Destruktor zakladni tridy\n"; getchar(); }}; // end zakladni……………………………………………………

Page 21: ÚVOD DO CPP 7

class Odvozena : public Zakladni { int j; public://konstruktor - předání argumentu Odvozena(int n) { cout << "Konstruktor odvozené třídy\n"; j = n; }//destruktor ~ Odvozena() { cout << "Destruktor odvozene tridy\n"; }//clenska: void zobraz_j() { cout << j << '\n'; }};// end odvozena

Page 22: ÚVOD DO CPP 7

int main(){ Odvozena objekt( 20); objekt.zobraz_j(); system("Pause"); return 0;}/* výpis: Konstruktor zakladni tridy Konstruktor odvozene tridy 20 Destruktor odvozene tridy Destruktor zakladni tridy */

Page 23: ÚVOD DO CPP 7

2)Předání argumentu konstruktoru základní třídy :Předání argumentu konstruktoru základní třídy se provádí pomocí rozšířeného formátu deklarace konstruktoru odvozené třídy.Syntaxe deklarace konstruktoru :jméno_odvoz_třídy(seznam argumentů):jméno_zaklad_třídy(seznam argumentů) { // tělo konstruktoru odvozené třídy}

Tím je umožněno dopředné předání argumentu do základní třídy.Příklad:předání stejného argumentu konstruktoru základnía odvozené třídy :class Zakladni { int i; public:// konstruktor: Zakladni(int n) { cout << "Konstruktor zakladni tridy\n"; i = n; }

Page 24: ÚVOD DO CPP 7

// destruktor ~Zakladni() { cout << "Destruktor zakladni tridy\n"; getchar(); }//členskávoid zobraz_i() { cout <<"i= "<< i << '\n';}};// end zakladni................................................

class Odvozena : public Zakladni { int j; public://konstruktor - předání argumentu do základní třídy: Odvozena(int n) : Zakladni(n) { cout << "Konstruktor odvozene tridy\n"; j = n; }//destruktor ~ Odvozena() { cout << "Destruktor odvozene tridy\n"; getchar();

}

Page 25: ÚVOD DO CPP 7

//clenska void zobraz_j() { cout <<"j= " << j <<'\n'; }};// end odvozena

int main(){ Odvozena objekt( 20);// pro obě třídy stejná inicializace

objekt.zobraz_j(); objekt.zobraz_i(); getchar(); return 0;}/* vypis: Konstruktor zakladni tridy Konstruktor odvozene tridy j = 20 i = 20 Destruktor odvozene tridy Destruktor zakladni tridy */

Page 26: ÚVOD DO CPP 7

Nejčastější případ - předání rozdílných parametrů konstruktorům odvozené a základní třídy :

Předání argumentu konstruktorům odvozené i základní třídy. Argumenty konstruktorů jsou pro obě třídy rozdílné :class Zakladni { int i; public:// konstruktor Zakladni(int n ) { cout << "Konstruktor zakladni tridy\n"; i = n; }// destruktor ~Zakladni() { cout << "Destruktor zakladni tridy\n"; getchar(); }//clenskavoid zobraz_i() { cout <<"i= "<< i << '\n';}};// end zakladni

Page 27: ÚVOD DO CPP 7

class Odvozena : public Zakladni { int j; public://konstruktor - předání argumentu do základní třídy:Odvozena(int n, int m): Zakladni( m ) { cout << "Konstruktor odvozene tridy\n"; j = n; }//destruktor ~ Odvozena() { cout << "Destruktor odvozene tridy\n";}//clenska void zobraz_j() { cout <<"j= " << j <<'\n'; }};// end odvozena

Page 28: ÚVOD DO CPP 7

int main(){ Odvozena objekt( 20, 30); // 20 Odvozena, 30 Zakladni

objekt.zobraz_j(); objekt.zobraz_i(); getchar(); return 0;}/* vypis: Konstruktor zakladni tridy Konstruktor odvozene tridy j = 20 i = 30 Destruktor odvozene tridy Destruktor zakladni tridy */

Page 29: ÚVOD DO CPP 7

7.4 Vícenásobná dědičnost.Dědit lze dvojím způsobem:1) Postupným děděním, kdy odvozená třída může být použita jako základní třída pro další odvozenou třídu atd...Příklad postupného dědění třídy1 a třídy2 třídou 3 - kostra programu:class základní { // třída1 int x; //.............//konstruktor základní( x).......} ;class odvozená1: public základní { // třída2 int y; //.........//konstruktor odvozena1( y, x): základní( x){........} ;

class odvozená2: public odvozená1 { //třída3 int z; //...........//konstruktor odvozená2( z, y, x) : odvozená1( y, x )} ;

Page 30: ÚVOD DO CPP 7

Konstruktory jsou volány postupně od základní třída1 až po třída3,

destruktory jsou volány v obráceném pořadí.

Odvozená třída2 ze třídy1 je použita jako základní třída pro další odvozenou třídu3.

Odvozená třída3 dědí třídu základní nepřímo - indirect.Třída3, má přístup k veřejným členům třídy1 a třídy2.

Page 31: ÚVOD DO CPP 7

#include<iostream>using namespace std;class Trida1{ int a;public://konstruktor:................................Trida1( int x){ a = x;}//...................................................nt predej_a() { return a;}};// end trida1//přímé dědění základní třídy:class Trida2 : public Trida1 { int b;public://konstruktor:........................................................Trida2(int x, int y): Trida1(y) //volání konstruktoru //základní třídy Trida1(y); { b = x; } //.......................................................................int predej_b() { return b; }};// end trida2

//Trida3 dědí odvozenou třídu2 a nepřímo základní třídu:class Trida3: public Trida2 { int c;public://konstruktor:Trida3( int x, int y, int z) : Trida2(y,z) { //volá //konstruktor třídy2 c=x;}/* Protože Trida3 dědí public,Třída3 má přístup k veřejným členům Tridy1 a Tridy2 *///Členské: void zobraz() { cout << predej_a() << ' '<< predej_b() << ' '; cout << c << '\n'; }};//end Trida3

int main(){ Trida3 objekt(1,2,3);

cout << "Vypis objekt3.zobraz() = "; objekt.zobraz();

//predej_a() a predej_b() jsou zde verejnecout<<"Vypis objekt.predej_a() = ";cout<< objekt.predej_a();cout << '\n';cout <<"Vypis objekt.predej_a() = ";cout<< objekt.predej_b();cout <<'\n';system("Pause);return 0;}

Page 32: ÚVOD DO CPP 7
Page 33: ÚVOD DO CPP 7
Page 34: ÚVOD DO CPP 7
Page 35: ÚVOD DO CPP 7
Page 36: ÚVOD DO CPP 7
Page 37: ÚVOD DO CPP 7
Page 38: ÚVOD DO CPP 7
Page 39: ÚVOD DO CPP 7
Page 40: ÚVOD DO CPP 7
Page 41: ÚVOD DO CPP 7