Co to jest funkcja wirtualna?
Funkcja wirtualna to funkcja zdefiniowana w nadklasie, która musi znajdować się w podklasie, aby ta podklasa miała pełną definicję klasy. Funkcje wirtualne opierają się na paradygmacie programowania obiektowego zwanym wirtualnym dziedziczeniem, który jest najczęściej spotykany w C ++ przy użyciu słowa kluczowego „virtual”. Aby zdefiniować funkcję wirtualną, potrzebne są dwie klasy, nadklasa i podklasa. Nadklasa jest miejscem, w którym funkcja jest najpierw deklarowana i ewentualnie definiowana. Podklasa to miejsce, w którym funkcja jest zdefiniowana - lub zastąpiona, w zależności od tego, czy funkcja została zdefiniowana w nadklasie.
Funkcję wirtualną można zdefiniować na dwa sposoby. Po pierwsze, można go zdefiniować jako odcinek, w którym ma puste ciało i nic nie robi. Po drugie, może być zdefiniowany jako czysta funkcja wirtualna, gdzie jest zdefiniowany jako NULL w pliku nagłówkowym nadklasy.
Obie metodologie mają zalety i wady. Zdefiniowanie funkcji jako kodu pośredniczącego gwarantuje, że wszystkie podklasy ją implementują, nawet jeśli nic nie robi. Jeśli zapomnisz zastąpić funkcję i odpowiednio ją zaimplementować w podklasie, nie pojawią się jednak żadne błędy ani ostrzeżenia, które by to wskazywały. Z drugiej strony zdefiniowanie funkcji czysto wirtualnej wymaga, aby każda podklasa miała własną definicję funkcji, a jeśli tak nie jest, pojawią się błędy.
Funkcje wirtualne podlegają jednak tym samym regułom dziedziczenia, co funkcje niebędące wirtualnymi, więc hierarchie dziedziczenia z więcej niż dwoma poziomami mogą nie wymagać wyraźnych definicji funkcji wirtualnych. Na przykład można rozważyć klasę A, która deklaruje funkcję wirtualną, która jest zaimplementowana w podklasie B. Klasa B ma własną podklasę, klasę C. Klasa C nie wymaga wyraźnej definicji funkcji klasy A, ponieważ dziedziczy definicja z klasy B. W razie potrzeby klasa C może zastąpić funkcję klasy B lub może zastąpić funkcję klasy B, wywołując ją.
Z drugiej strony, funkcje wirtualne nie muszą być zdefiniowane w podklasie, jeśli są zadeklarowane jako wirtualne w tej podklasie. Na przykład można rozważyć klasę A, która deklaruje funkcję wirtualną i ma dwie podklasy, B i C. Ponadto można sobie wyobrazić, że klasa B ma podklasy D i E, a podklasa C ma podklasy F i G.
Klasy od B do G muszą mieć jakoś zdefiniowaną funkcję wirtualną klasy A. Jeśli klasa B ma implementację funkcji A, klasy D i E nie muszą być ponownie konfigurowane. Być może podklasy C muszą implementować funkcję A, ale oba robią coś innego, więc zdefiniowanie funkcji w samej klasie C nie byłoby przydatne. W takim przypadku funkcja może zostać zadeklarowana jako wirtualna w klasie C, a implementacja nie jest konieczna.
Funkcje wirtualne mogą być trudne do nauczenia się, ale jeśli są właściwie używane, mogą zmniejszyć duplikację kodu i ogólnie znacznie ułatwić jego zrozumienie. Istnieje jednak wiele pułapek związanych z funkcjami wirtualnymi, szczególnie w przypadku wielokrotnego dziedziczenia. W przypadku wielokrotnego dziedziczenia dwuznacznie zdefiniowane funkcje wirtualne mogą ze sobą kolidować, dlatego należy ich używać ostrożnie w tym kontekście.