Co to jest dziedziczenie wirtualne?
Dziedziczenie wirtualne jest rodzajem dziedziczenia, w którym implementacja nadklasy jest niekompletna, a podklasa jest wymagana do pełnej definicji obiektu. Ten typ dziedziczenia może być stosowany w połączeniu z dziedziczeniem pojedynczym i wielokrotnym, ale najczęściej jest stosowany w przypadku dziedziczenia wielokrotnego. Każda klasa dziedzicząca z wirtualnej klasy bazowej staje się bezpośrednią podklasą tej klasy bazowej. Wirtualna klasa bazowa może polegać na podklasie w celu wdrożenia wszystkich swoich metod, ale nie jest to wymagane.
C ++ jest najbardziej znanym językiem komputerowym używającym wirtualnego dziedziczenia. Aby zadeklarować wirtualne dziedziczenie w C ++, używane jest słowo kluczowe „virtual”. Zarówno nadklasa, jak i podklasa muszą deklarować metody wirtualne za pomocą słowa kluczowego „virtual”. Mówi to kompilatorowi C ++, że nadklasa jest niekompletna i musi uzyskać informacje z podklasy, aby ją ukończyć. Użycie podklasy do ukończenia nadklasy nie oznacza, że podklasy będą się wzajemnie nadpisywać, jeśli mają tę samą klasę podstawową, a zamiast tego kompilator C ++ dba o to, jakie elementy pasują do każdego obiektu.
Ponieważ do wirtualnego dziedziczenia wymagana jest wirtualna klasa podstawowa, nie można zadeklarować wirtualnych funkcji globalnych w C ++. Tego typu dziedziczenia można używać tylko w przypadku przestrzegania zasad programowania obiektowego (OOP). Powodem tego jest to, że funkcje globalne nie są powiązane z określoną klasą, a zatem zwykle same w sobie są samodzielne. Bez dziedziczenia nadklasy i podklasy nie może dojść do skutku, więc funkcje globalne i dziedziczenie wirtualne wykluczają się wzajemnie. Funkcje globalne mogą teoretycznie być używane wewnątrz funkcji wirtualnych, ale odwrotność może nie zawsze działać.
Wirtualne dziedziczenie służy do rozwiązywania wielu problemów programistycznych, a jednym z najbardziej przydatnych jest rozwiązywanie dwuznaczności. W przypadku wielokrotnego dziedziczenia można mieć klasę podstawową A, która ma dwie podklasy, B i C, a następnie klasę D, która dziedziczy z obu klas B i C. Ten wzorzec jest powszechnie nazywany „diamentem śmierci”, ponieważ jeśli klasy A, Wszystkie B i C mają implementacje tej samej metody, klasa D nie jest w stanie określić, której implementacji powinien użyć. Wirtualne dziedziczenie rozwiązuje ten problem, ponieważ implementacja każdej klasy pozostaje odrębna, a zatem jednoznaczna. To rozróżnienie jest obsługiwane przez wyspecjalizowane wewnętrzne obiekty zwane wirtualnymi tabelami (vtables), które śledzą każdy typ obiektu, ale programista nie musi jawnie manipulować tymi tabelami, ponieważ są one wbudowane w język.