Wprowadzenie
Dziedziczenie publiczne modeluje relację "jest". Obiekt klasy pochodnej
jest także obiektem klasy bazowej. To znaczy, że obiekt klasy pochodnej może być traktowany tak samo jak obiekt klasy bazowej, ponieważ klasa pochodna dziedziczy to, co było publiczne w klasie bazowej, czyli interfejs.
Skoro obiekty jednej klasy
są obiektami innej klasy (ale nie zawsze odwrotnie), to występują konwersje między tymi klasami. W graficznych sposobach przedstawiania hierarchii dziedziczenia (na przykład
diagramy UML) przyjęło się, że klasy bazowe są na górze, a pochodne na dole. Stąd wzięły się terminy
konwersji w górę i
rzutowania w dół.
class Prostokat
{
};
class Kwadrat
: public Prostokat
{
};
Konwersja w górę
Konwersja w górę hierarchii dziedziczenia (z pochodnej na bazową).
Kwadrat kw;
Prostokat p, * pp;
p = kw;
pp = & kw;
Konwersja w górę jest automatyczna i bezpieczna, bo obiekt klasy pochodnej
jest obiektem klasy bazowej (Każdy kwadrat
jest prostokątem).
Należy zauważyć, że obiekt klasy pochodnej jest niemal zawsze większy od obiektu klasy bazowej. W przypadku konwersji w górę obiektu klasy pochodnej, zostanie on przycięty.
Rzutowanie w dół
Rzutowanie w dół hierarchii dziedziczenia nie jest automatyczne, ponieważ obiekt klasy bazowej nie zawsze
jest obiektem klasy pochodnej (Nie każdy prostokąt
jest kwadratem). Rzutowanie w dół w C++ dotyczy tylko wskaźników i służy do tego
dynamic_cast <>
.
Jeśli nie można wykonać rzutowania,
dynamic_cast<> zwraca wskaźnik pusty.
Kwadrat kw, * kp;
Prostokat * p;
p = & kw;
kp = dynamic_cast < Kwadrat *>( p );
if( kp )
{
}
else
{
}
Błąd kompilacji:
error: cannot dynamic_cast ‘p’ (of type ‘class Prostokat*’) to type ‘class Kwadrat*’ (source type is not polymorphic)
Rzutowanie w dół jest wykonywane w czasie działania programu (bo nie wiadomo, co może być pod wskazanym adresem). To wymaga zapisania informacji o typie w obiektach (o czym na następnej lekcji).