- Tak, są takie same. Klasa pochodna, która nie deklaruje czegoś wirtualnego, nie powstrzymuje go od bycia wirtualnym. W rzeczywistości nie ma możliwości zatrzymania dowolnej metody (włączając destruktor) od wirtualności w klasie pochodnej, jeśli była ona wirtualna w klasie bazowej. W> = C++ 11 można użyć
final
, aby zapobiec nadpisywaniu w klasach pochodnych, ale to nie przeszkadza, aby było wirtualne.
- Tak, destruktor w klasie pochodnej można pominąć, jeśli nie ma nic wspólnego. I nie ma znaczenia, czy jest to wirtualne.
- Pominęłbym go, jeśli to możliwe. I zawsze używam ponownie słowa kluczowego
virtual
dla funkcji wirtualnych w klasach pochodnych dla jasności. Ludzie nie powinni przechodzić przez hierarchię dziedziczenia, aby zorientować się, że funkcja jest wirtualna. Dodatkowo, jeśli klasa jest kopiowalna lub przenośna bez konieczności zadeklarowania własnej kopii lub przeniesienia konstruktorów, deklarowanie dowolnego destruktora (nawet jeśli zdefiniujesz go jako default
) zmusi Cię do zadeklarowania kopiowania i przeniesienia konstruktorów i operatorów przypisania, jeśli chcę ich, ponieważ kompilator nie będzie już dla ciebie ich używał.
Jako mały punkt dla pozycji 3. W uwagach zaznaczono, że jeśli destruktor jest nieokreślony, kompilator generuje domyślny (który jest nadal wirtualny). Ten domyślny jest funkcją inline.
Funkcje wbudowane potencjalnie narażają więcej programu na zmiany w innych częściach programu i sprawiają, że trudno jest uzyskać kompatybilność binarną dla bibliotek współdzielonych. Ponadto zwiększone sprzężenie może spowodować wiele ponownych kompilacji w obliczu pewnych rodzajów zmian. Na przykład, jeśli zdecydujesz, że naprawdę chcesz implementację swojego wirtualnego destruktora, każdy kod, który go wywołał, będzie musiał zostać zrekompilowany. Podczas gdy zadeklarowałeś to w treści klasy, a następnie zdefiniowałeś ją jako pustą w pliku .cpp
, dobrze byłoby zmienić ją bez rekompilacji.
Moim osobistym wyborem byłoby pominięcie go, gdy jest to możliwe. Moim zdaniem powoduje to zaśmiecanie kodu, a kompilator może czasami robić nieco bardziej wydajne rzeczy z domyślną implementacją nad pustą. Ale istnieją ograniczenia, które mogą być pod tym, że to zły wybór.
Twoje ostatnie zdanie prawdopodobnie powinno brzmieć "nie powinno" zamiast "powinien". –
@ Chr. Lutz, wyprzedzam cię o to. Zostało to teraz poddane edycji. :-) – Omnifarious
Nie zgadzam się z częścią "omit". Oświadczenie go w nagłówku nie kosztuje wiele i definiuje go (pusty obiekt) w źródle. Jeśli to zrobisz, zawsze możesz wrócić i dodać kilka kroków (rejestrowanie?) Bez zmuszania klientów do ponownej kompilacji. –