Aha, tak už ten rozdíl vidím. Ale ty dvě třídy PrvniNadTrida a DruhaNadTrida jsou principově totožné, ne?
Jde jen o to, že rozdíl je v tom, že funkce_1 má v parametru typ té druhé třídy a funkce_2 má v parametru typ té první třídy. Takže první volá funkci druha() z druhé nadTřídy a druhá volá funkci prvni() z první nadTřídy... Říkám to správně? A to přetypování je kde?
Sice vypadají velmi podobně, ale jsou to dvě různé třídy a uvnitř
PodTrida zabírají dvě různé pozice, proto se i jejich adresa bude lišit. Interně si třídu
PodTrida můžete představit takto:
ukazatel na vtable sdílený pro PrvniNadTrida a PodTrida
// členské proměnné třídy PrvniNadTrida, pokud by byly deklarovány
ukazatel na vtable specifický pro DruhaNadTrida
// členské proměnné třídy DruhaNadTrida, pokud by byly deklarovány
// členské proměnné třídy PodTrida, pokud by byly deklarovány
Začátek dat pro
PodTrida a
PrvniNadTrida (ukazatel na jejich vtable) je na stejném místě, takže
pod == static_cast<PrvniNadTrida*>(pod). (Pokud vyrobím instanci třídy
PrvniNadTrida, bude ukazatel na její vtable ukazovat jinam než ukazuje v instanci třídy
PodTrida, ale bude na stejném místě relativně k
PrvniNadTrida*.) Naproti tomu začátek dat pro
DruhaNadTrida (ukazatel na vtable specifický pro danou třídu) je posunutý o délku ukazatele vtable pro
PrvniNadTrida (plus případné členské proměnné, pokud by byly deklarovány), a tak ukazatel získaný přetypováním na
DruhaNadTrida* bude o tuto délku posunutý, takže
pod < static_cast<DruhaNadTrida*>(pod). (Ukazatel na vtable v instanci třídy
DruhaNadTrida bude opět ukazovat jinam než ukazatel specifický pro
DruhaNadTrida v instanci třídy
PodTrida, ale opět bude na stejném místě relativně k
DruhaNadTrida*.)
To přetypování je při volání těch metod implicitní (nemusí se uvádět), protože jde vždy převést z potomka na předka a kompilátor ví, že
PrvniNadTrida i
DruhaNadTrida jsou předky
PodTrida.
Na druhou stranu je dobré vědět, že tohle nemá efekt na
nullptr, takže testování na
nullptr bude správně fungovat i po převodu:
PodTrida *pod = nullptr;
if (pod != nullptr)
funkce1(pod); // neprovede se, pod je nullptr
DruhaNadTrida *nad = pod;
if (nad != nullptr)
funkce1(nad); // neprovede se, nad je taky nullptr