Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!
Zadejte Vaši e-mailovou adresu:
Kamarád fotí rád?
Přihlas ho k odběru fotomagazínu!
Zadejte e-mailovou adresu kamaráda:
C/C++
Vícenásobná dědičnost v C++
7. března 2001, 00.00 | V tomto článku si objasníme vícenásobnou dědičnost v C++ a předvedeme si některé problémy, které mohou nastat..
Vícenásobná dědičnost je dědičnost, ve které je nová třída bezprostředním následovníkem více tříd. Narozdíl od jednoduché dědičnosti, kdy každá nová třída je bezprostředním následovníkem pouze jedné třídy.
Vícenásobná dědičnost se chová podle stejných pravidel jako dědičnost jednoduchá, jen na rozdíl od jednoduché dědičnosti vzniká při vícenásobné dědičnosti několik "drobných" problémů. Vícenásobná dědičnost je tedy opět specializace. Nová třída "dědí" po svých předchůdcích vlastnosti, s tím, že další vlastnosti mohou být přidány. Přístup ke zděděným položkám při vícenásobné dědičnosti má stejná pravidla jako přístup ke zděděným položkám při dědičnosti jednoduché. Ve svém článku "Jednoduchá dědičnost v C++" jsem uvedl tabulku přístupových práv, která beze změn platí i pro vícenásobnou dědičnost, proto ji zde nebudu uvádět znovu.
Syntaxe pro vícenásobnou dědičnost je velmi podobná jako syntaxe pro vyjádření dědičnosti jednoduché. Vlastně je zřejmé, že jednoduchá dědičnost je specielním případem dědičnosti vícenásobné, kdy počet předků je roven 1. Další předkové jsou oddělení čárkou. Tedy například:
class potomek : public Predek1, public Predek2, public Predek3 {};Nyní jsem definoval třídu potomek, která má 3 předky, každý předek je děděn veřejnou dědičností. Nová třída nemá žádné nové atributy ani metody. Instanci třídy potomek v paměti počítače je dobré si představit jako-by byly "za sebou" 3 instance jednotlivých předků a dále nové vlastnosti třídy potomek.
Problémy při vícenásobné dědičnostiVse by bylo krásné nebýt několika velmi nepříjemných problémů, které vícenásobná dědičnost přináší. Problémy:
Při vícenásobné dědičnosti může nastat situace, že třída dědí z nadtříd, které mají stejné názvy atributů, nebo metod. Který potom zdědit?
Nějaký atribut, nebo metoda mohou být zděděné "vícekrát". Opakovaná dědičnost nastává, jestliže v třídním diagramu existuje mezi 2 třídami více než jedna cesta. Například třída B dědí ze třídy A. Třída C dědí ze třídy A. Třída D dědí ze třídy C a B. Třída D vlastně dvakrát dědí ze třídy A. Má mít třída D položky třídy A dvakrát, nebo jen jednou?
Jak jsem uvedl ve článku o jednoduché dědičnosti při vytváření instance se implicitně zavolají konstruktory předka, při rušení se volá implicitně destruktor potomka. Ve vícenásobné dědičnosti je ale bezprostředních předků více. V jakém pořadí se tedy mají volat konstruktory a destruktory?
Dalším problémem často se projevujícím u vícenásobné dědičnosti je správné (spíše špatné) přetypování potomka na předka. Jedná se ale spíše o problém s přetypováváním, proto se mu nebudu věnovat ve článcích o vícenásobné dědičnosti, ale až někdy v budoucnu ve článku věnovanému přetypování v C++.
Konflikt jmenTedy problém jaké atributy a metody dědit, jestliže se vyskytují ve více předcích se stejným názvem. Upozorňuji jen, že v tomto případě nesmí mít předci žádnou společnou nadtřídu. Mají-li, dojde sice také ke kolizi jmen, ale jedná se o problém opakovaného dědění. Problém kolize jmen se řeší tak, že třída zdědí všechny atributy a metody i v případě, že mají stejné jméno. Prostě ve třídě existuje více položek se stejným názvem. Protože přístup k položkám musí být jednoznačný, přistupuje se k položce pomocí tak zvaného úplného jména. Úplné jméno je jméno třídy následováno "čtyřtečkou" a poté následuje název atributu, nebo metody. Vše vysvětlím na příkladu:
|
Dobře si všimněte jak v metodě C::nuluj přistupuji k atributu Atribut. Jedná se o úplné jméno atributu, čímž zamezím nejednoznačnosti. Kdybych chtěl zavolat metodu, jejichž jméno je v nějaké kolizi, musel bych také uvést úplné jméno. Každá z metod pracuje nad "svými" atributy. Tedy metoda A::nastav pracuje s atributem A::Atribut a metoda B::nastav pracuje s atributem B::Atribut. Pro pochopení přidávám následující funkci main:
|
Jak vidíte každá metoda pracuje nad "svými" daty. U virtuálních metod je velkou výhodou, že je lze předefinovat. Proto by bylo vhodné metodu metoda ve třídě C předefinovat, aby se při jejím volání nemuselo psát úplné jméno. Nic mi nebrání tělo metody předefinovat například takto:
|
nebo:
|
Nebo jakkoliv jinak.
Tolik tedy k jednomu z problému vícenásobné dědičnosti. Příště budu řešit problém opakovaného dědění a poté v dalším článku problém konstruktorů a destruktorů při vícenásobné dědičnosti.
Obsah seriálu (více o seriálu):
- Základy OOP v C++: Od C k C++
- Základní pojmy objektově orientovaného programování
- Vytváření tříd, instance třídy, zasílání zpráv v C++
- Vytváření instancí - konstruktory, destruktory
- Kopírovací konstruktor v C++
- Jednoduchá dědičnost v C++
- Časná versus pozdní vazba - úvod do polymorfismu v C++
- Polymorfismus - dokončení
- Vícenásobná dědičnost v C++
- Vícenásobná dědičnost v C++ - opakovaná dědičnost
- Vícenásobná dědičnost v C++ - volání konstruktorů a destruktorů
- Přetěžování operátorů v C++ 1.díl
- Přetěžování operátorů v C++ 2. díl
- Vstupní a výstupní operace pomocí datových proudů v C++
- Přetěžování operátorů << a >> pro datové proudy v C++
- Neformátovaný vstup a výstup v C++
- Paměťové proudy v C++
- Prostory jmen v C++
- Řetězce v C++
- Výjimky v C++
- Výjimky v C++ - výjimky tvoří dědičnou hierarchii
- Výjimky v C++ - dokončení
- Dynamická identifikace typů v C++
- Přetypování v C++
- Problémy s typy při vícenásobné dědičnosti
- Šablony funkcí v C++
- Šablony datových typů v C++
- Vnitřní typy u parametrů šablon, vnořené šablony v C++
- Pole s libovolným intervalem indexování v C++
- Datové kontejnery v C++ - Úvod do STL
- Vector - datový kontejner v C++
- Iterátory v C++
- Šablona vector v C++ a iterátory
- Asociativní pole v C++
- Množina v C++
- Funkční objekty v C++
- Standardní funkční objekty v C++
- Úvod do standardních algoritmů v C++
- Kopírovací a přesouvací algoritmy v C++
- Vyhledávací algoritmy v C++
- Skenovací (prohlížecí) algoritmy v C++
- Transformační algoritmy v C++
- Řadící algoritmy v C++
- Halda v C++
- Standardní algoritmy v C++ - dokončení
- Automatické ukazatele v C++
- Inteligentní ukazatel - čítač referencí v C++
- Použití čítače referencí v C++
- Kopírování velkých objektů v C++
- Řízené kopírování prvků v poli v C++
- Dokončení seriálu objektově orientované programování v C++
-
25. listopadu 2012
-
30. srpna 2002
-
10. října 2002
-
4. listopadu 2002
-
12. září 2002
-
25. listopadu 2012
-
28. července 1998
-
31. července 1998
-
28. srpna 1998
-
6. prosince 2000
-
27. prosince 2007
-
4. května 2007