Dědění, volání konstruktorů a destruktorů, virtuální a nevirtuální metody



Napište následující program. Odevzdejte pouze program, na otázky si odpovězte pouze pro sebe.
Program bude obsahovat soubory main.cpp, hlavičkové soubory Cbase.h, Cderiv1.h, Cderiv2.h. Trida.cpp, trida.h
Na začátku každého souboru napište identifikaci pro Doxygen (file, autor, ...)

1) Vytvořte bázovou třídu CBase, která bude mít metodu Print, která vytiskne text „Print Cbase“.
Vytvořte ve třídě CBase konstruktor implicitní a destruktor.
Konstruktor bude tisknout text „Konstr_CBase“, destruktor vytiskne „Destr_CBase“.

2) Vytvořte odvozenou třídu CDeriv1 od CBase pomocí public dědění, která bude mít tytéž metody jako CBase.
Místo „CBase“ se bude v textech tisknout „CDeriv1“.

3) Vytvořte odvozenou třídu CDeriv2 od CBase pomocí public dědění, která bude mít tytéž metody jako CBase.
Místo „CBase“ se bude v textech tisknout „CDeriv2“.
Tato třída bude obashovat jeden prvek třídy Cderiv1 (v private sekci).

4) Vytvořte v main jeden objekt od každé třídy.
Pro každý objekt zavolejte jeho metodu Print.
Program spusťte a podívejte se co se tiskne - kudy prochází program.
Implementujte počítání vzniklých a aktuálních objektů pomocí statických proměnných pro každou třídu. Sledujte počet vytvořených proměnných na konci programu (aktuálních by měla být nula). (V main uveďte kód do zvláštního bloku, aby po jeho skončení bylo možné zjistit zda všechny objekty zanikly).


5) Vytvořte v main pole pro tři ukazatele pb,pd1,pd2 na každou třídu (typ třídy) a nainicializujte je pomocí vytvořených prvků (všechny stejně => vzniknou všechny kombinace tříd ukazatelů a objektů).

CBase *pb[3] = {&b,&d1,&d2};
CDerived1 *pd1[3] = {(CDerived1 *) &b,(CDerived1 *)&d1,(CDerived1 *)&d2 };
CDerived2 *pd2[3] = { (CDerived2 *)&b,(CDerived2 *)&d1,(CDerived2 *)&d2 };

6) Pro všechny ukazatele z minulého bodu zavolejte metodu Print. Co očekáváte a co se stane.
Zavolejte metodu Print i pro základní objekty.

7) Do všech tříd přidejte metodu PrintV tak, aby byla realizována pozdní vazbou (polymorfizmus/virtual).
Realizujte stejný tisk jako v minulém bodě, nyní pro metodu PrintV. Co očekáváte a co se stane. Porovnejte tisk průběhu minulého tisku (časná vazba) a současného ( po přidání pozdní vazby, mechanizmus virtuálních metod).
Zavolejte metodu PrintV i pro základní objekty.
Na jakých proměnných se bude výsledek lišit – u objekt nebo při přístupu přes ukazatel? Proč?

8) Vysvětlete, která/které kombinace ukazatelů pb,pd1,pd2 a jejich inicializací (bod 5 zadání) dávají smysl, a které jsou špatně a proč.

9) Je možné zjistit typ proměnné "programově" (všimněte si, že plně "funguje" až po zavedení vlastnosti virtual, kdy použije pozdní vazbu. Jinak je tato funkce "vyřešena" při překladu).
Pomocí příkazu typeid je možné získat strukturu type_info.
Pomocí metody name() můžeme například zjistit jméno typu objektu. typeid( XXX ).name(); Doplňte tento tisk do metod Print a PrintV – zhodnoťte, zda se název třídy získaný pomocí typeid liší od tisků původních (body zadání 1-3).

10) vytvořte dynamickou proměnnou typu CDerived2 a ihned ji zrušte pomocí delete.
Porovnejte počet vzniklých a zaniklých objektů.
Přidejte k destruktoru virtualitu a srovnejte s předchozím.

11) Doplňte třídu, na které jste během semestru pracovali o metody Print a PrintV tak, aby mohly být zařazeny jako další prvek do polí pb,pd1,pd2 a zařaďte je na poslední místo (takže budou mít pole čtyři prvky, poslední bude patřit k vaší třídě). Soubory pro vaši třídu budou mít jména Trida.cpp, trida.h.