mam rażąco zgrywania wyłączyć niektóre przykładowy kod z Wikipedii Virtual function stronie:
#include <iostream>
#include <vector>
class Animal {
public:
virtual void eat() const {
std::cout << "I eat like a generic Animal." << std::endl;
}
virtual ~Animal() {
}
};
class Wolf : public Animal {
public:
void eat() const {
std::cout << "I eat like a wolf!" << std::endl;
}
};
class Fish : public Animal {
public:
void eat() const {
std::cout << "I eat like a fish!" << std::endl;
}
};
Jeśli zadzwonisz eat()
wewnątrz konstruktora Animal
, to nazywamy Animal
eat()
funkcja za każdym razem. Nawet po utworzeniu obiektu Wolf
lub Fish
, ponieważ konstruktor Animal
zostanie ukończony przed zainicjowaniem obiektu podklasy, nadrzędne funkcje eat
nie będą jeszcze działać.
Jest to wadą, ponieważ może powodować zamieszanie między tym, co jest oczekiwane, a tym, co faktycznie się dzieje. Jeśli przesłonię eat
, a następnie utworzę obiekt mojej podklasy, oczekuję, że moja nadpisana funkcja zostanie wywołana, nawet z odwołania do Animal
. Spodziewam się tego, ponieważ tak się dzieje, gdy wywołanie jest wykonywane bezpośrednio przez kod poza konstruktorem. Zachowanie jest inne wewnątrz konstruktora, co powoduje, że drapię się po głowie w oszołomieniu.
Jest to jeden z powodów, dla których nie podoba mi się przewodnik w stylu C++ google. Wywoływanie wirtualnych metod z konstruktorów i destruktorów powinno być unikane jako jedna rzecz z reguły - gdziekolwiek tego nie robisz, to tylko zrób to, jeśli masz dobry powód i możesz go bronić w przeglądzie kodu. Z drugiej strony, zalecenie użycia dwuetapowej inicjalizacji jest (prawdopodobnie) całkowicie błędne, a wiele innych przewodników po stylach zaleca dwuetapowe inicjowanie ... –
Pamiętaj, że przewodnik po stylu Google nie jest w C++, pomimo tytułu strony . Zakazują wyjątków, podając skandaliczny język, w którym wiele idiomów C++ albo nie może być użytych, albo pozbawionych ich użyteczności. Jest to powód, dla którego wymagają dwuetapowej inicjalizacji i wszystkich podatnych na błędy bólów głowy, które pociąga za sobą; nie ma możliwości wskazania awarii od konstruktora. Jeśli nie masz konkretnego powodu, by podążać za stylem Google, zignoruj go. –