Na początek, żebyś wiedział z czym masz do czynienia..
W większości języków wspierających polimorfizm (Java, Python, C#...), masz do czynienia właśnie z funkcjami wirtualnymi. Ukrywają to jednak mechanizmy danego języka (nie C++) i nie wiesz że za to płacisz. Mniejsza już o to ile i na jakim etapie bo zagadnienie ma dotyczyć C++.
W C++ masz do czynienia z 2 rodzajami polimorfizmu:
- statycznym - możliwy do stosowania na etapie kompilacji i którego działanie w programie nie implikuje żadnego dodatkowego narzutu na wywołanie funkcji. Jak i kiedy.. może innym razem.
- dynamicznym - stosowany na etapie uruchomienia programu, niezbędny w przypadkach gdy nie wiesz z jakiego rodzaju typem (a więc klasą) obiektu będziesz miał do czynienia a będziesz wiedział już w trakcie działania programu.
Ten drugi rodzaj polimorfizmu, wspierają metody wirtualne. A teraz o koszcie...
Od C++ wymaga się ekstremalnej wydajności. Stąd tak potężne mechanizmy wyboru jakie dostarcza ten język. Jeśli zastosujesz funkcję oznaczoną jako virtual, każde jej wywołanie połączone będzie z określeniem na rzecz którego obiektu (a dokładniej jakiego typu) będzie wywoływana. To określanie najczęściej odbywa się przez przeglądanie tablicy wywołań którą generuje kompilator dla klasy która posiada daną funkcję wirtualną (nazywaną vtable). Takie wywołanie (połączone z rozwiązaniem zagadki "na rzecz kogo"), kosztuje setki taktów zegara! Rozwiązanie zagadki działa zaś wyłącznie dla wskaźników i referencji na dany obiekt. To jest rozwiązanie kosztowne i wymagające świadomego użycia.
Załóżmy że jednak go użyłeś....
Oznacza to że będziesz chciał w klasach dziedziczących, przesłonić funkcję. Słowo kluczowe to "dziedziczących". W przypadku dziedziczenia, najczęściej dojdzie także do rozbudowania klasy dziecka o dodatkowe atrybuty. Pojawi się konieczność prawidłowego usunięcia obiektu z pamięci na etapie jego destrukcji. Stąd konieczne jest wtedy opatrywanie klas rodziców, wirtualnym destruktorem. Jeśli nie następuje rozbudowa o nowe atrybuty (rzadki przypadek), to destruktor wirtualny nie jest konieczny.
I na koniec tzw. "dobra reguła i praktyka". Jeśli pojawi się przy metodzie virtual, chcesz pewnie dziedziczyć, prawie na pewno będziesz miał destruktor wirtualny...
Na tym poprzestanę bo już długie wyszło... są oczywiście wyjątki, niuanse, reguły... ale pytałeś o zasadę...