Co to dokładnie znaczy, jeśli funkcja jest zdefiniowana jako wirtualna i czy jest to to samo, co czysta wirtualna?
Z funkcji wirtualnej Wikipedii ...
W programowaniu obiektowym, w językach takich jak C ++ i Object Pascal, funkcja wirtualna lub metoda wirtualna to dziedziczna i dająca się zastąpić funkcja lub metoda, dla której ułatwione jest dynamiczne wysyłanie. Ta koncepcja jest ważną częścią polimorfizmu (środowiska wykonawczego) programowania obiektowego (OOP). Krótko mówiąc, funkcja wirtualna określa funkcję docelową do wykonania, ale cel może nie być znany w czasie kompilacji.
W przeciwieństwie do funkcji niebędącej funkcją wirtualną, gdy funkcja wirtualna jest nadpisywana, najbardziej pochodna wersja jest używana na wszystkich poziomach hierarchii klas, a nie tylko na poziomie, na którym została utworzona. Dlatego jeśli jedna metoda klasy bazowej wywołuje metodę wirtualną, zamiast wersji zdefiniowanej w klasie bazowej zostanie użyta wersja zdefiniowana w klasie pochodnej.
Jest to sprzeczne z funkcjami innymi niż wirtualne, które nadal można przesłonić w klasie pochodnej, ale „nowa” wersja będzie używana tylko przez klasę pochodną i poniżej, ale w ogóle nie zmieni funkcjonalności klasy podstawowej.
natomiast..
Funkcja czysto wirtualna lub metoda czysto wirtualna to funkcja wirtualna, która musi zostać zaimplementowana przez klasę pochodną, jeśli klasa pochodna nie jest abstrakcyjna.
Gdy istnieje metoda czysto wirtualna, klasa jest „abstrakcyjna” i nie można jej tworzyć samodzielnie. Zamiast tego należy użyć klasy pochodnej, która implementuje metody czysto wirtualne. Czysta-wirtualna nie jest w ogóle zdefiniowana w klasie podstawowej, więc klasa pochodna musi ją zdefiniować, lub ta klasa pochodna jest również abstrakcyjna i nie można jej utworzyć. Instancja może być utworzona tylko klasa, która nie ma metod abstrakcyjnych.
Wirtualny zapewnia sposób na zastąpienie funkcjonalności klasy podstawowej, a czysty wirtualny tego wymaga .
pure
słowo kluczowe, ale Bell Labs zamierzał wydać główną wersję C ++, a jego menedżer nie pozwoliłby na to na późnym etapie. Dodawanie słów kluczowych to wielka sprawa.Chciałbym skomentować definicję wirtualnego Wikipedii, którą kilka osób tutaj powtórzyło. [W momencie pisania tej odpowiedzi] Wikipedia zdefiniowała metodę wirtualną jako metodę, którą można zastąpić w podklasach. [Na szczęście Wikipedia była od tamtej pory edytowana i teraz wyjaśnia to poprawnie.] To jest niepoprawne: każdą metodę, nie tylko wirtualną, można zastąpić w podklasach. Wirtualny daje polimorfizm, czyli możliwość wybrania w czasie wykonywania najbardziej pochodnego zastąpienia metody .
Rozważ następujący kod:
Jaka jest wydajność tego programu?
Pochodne zastępuje każdą metodę Base: nie tylko wirtualną, ale także niewirtualną.
Widzimy, że gdy masz wskaźnik bazowy na pochodną (bDerived), wywołanie NonVirtual wywołuje implementację klasy Base. Jest to rozwiązywane w czasie kompilacji: kompilator widzi, że bDerived jest Bazą *, że NonVirtual nie jest wirtualny, więc robi to z klasą Base.
Jednak wywołanie Virtual wywołuje implementację klasy Derived. Z powodu słowa kluczowego virtual wybór metody odbywa się w czasie wykonywania , a nie w czasie kompilacji. To, co dzieje się tutaj podczas kompilacji, polega na tym, że kompilator widzi, że jest to Base * i że wywołuje metodę wirtualną, więc wstawia wywołanie do vtable zamiast do klasy Base. Ta tabela vt jest tworzona w czasie wykonywania, stąd rozdzielczość w czasie wykonywania do najbardziej pochodnego przesłonięcia.
Mam nadzieję, że nie było to zbyt mylące. Krótko mówiąc, każdą metodę można zastąpić, ale tylko metody wirtualne dają polimorfizm, to znaczy wybór najbardziej pochodnej zmiany w czasie wykonywania. W praktyce jednak zastąpienie metody innej niż wirtualna jest uważane za złą praktykę i rzadko stosowane, dlatego wiele osób (w tym ktokolwiek napisał ten artykuł w Wikipedii) uważa, że można zastąpić tylko metody wirtualne.
źródło
Derived*
wywołań z tymi samymi funkcjami, aby doprowadzić punkt do domu. W przeciwnym razie świetna odpowiedźWirtualne słowo kluczowe daje C ++ jego zdolność do wspierania polimorfizmu. Gdy masz wskaźnik do obiektu jakiejś klasy, takiego jak:
W tym (głupim) przykładzie funkcja GetNumberOfLegs () zwraca odpowiednią liczbę na podstawie klasy obiektu, do którego została wywołana.
Teraz rozważ funkcję „SomeFunction”. Nie ma znaczenia, jaki typ obiektu zwierzęcego jest do niego przekazywany, o ile pochodzi on od Zwierząt. Kompilator automatycznie zarzuci dowolną klasę pochodzenia zwierzęcego na zwierzę, ponieważ jest to klasa bazowa.
Jeśli to zrobimy:
wyświetli „2”. Jeśli to zrobimy:
wyświetli „4”. Nie możemy tego zrobić:
ponieważ nie można go skompilować, ponieważ funkcja wirtualna GetNumberOfLegs () jest czysta, co oznacza, że musi zostać zaimplementowana przez wyprowadzenie klas (podklas).
Czyste funkcje wirtualne są najczęściej używane do definiowania:
a) klasy abstrakcyjne
Są to klasy podstawowe, z których należy wywodzić, a następnie implementować funkcje czysto wirtualne.
b) interfejsy
Są to „puste” klasy, w których wszystkie funkcje są czysto wirtualne i dlatego musisz wyprowadzić, a następnie zaimplementować wszystkie funkcje.
źródło
W klasie C ++ słowo wirtualne jest słowem kluczowym, które to oznacza, metoda może zostać zastąpiona (tj. Zaimplementowana) przez podklasę. Na przykład:
W takim przypadku podklasa może zastąpić funkcję initShape w celu wykonania specjalistycznej pracy:
Termin czysto wirtualny odnosi się do funkcji wirtualnych, które muszą zostać zaimplementowane przez podklasę i nie zostały zaimplementowane przez klasę podstawową. Metodę wyznacza się jako czystą wirtualną, używając słowa kluczowego virtual i dodając a = 0 na końcu deklaracji metody.
Więc jeśli chcesz uczynić Shape :: initShape czystym wirtualnym, wykonaj następujące czynności:
Dodając do klasy czystą wirtualną metodę, uczynisz klasę abstrakcyjną klasą podstawową, co jest bardzo przydatne do oddzielania interfejsów od implementacji.
źródło
m_name
. Com_
znaczy„Wirtualny” oznacza, że metoda może być nadpisana w podklasach, ale ma bezpośrednio wywoływalną implementację w klasie podstawowej. „Czysta wirtualna” oznacza, że jest to metoda wirtualna bez implementacji, którą można wywołać bezpośrednio. Taki sposób musi zostać co najmniej raz zastąpiony w hierarchii dziedziczenia - jeśli klasa ma jakieś niezaimplementowane metody wirtualne, obiektów tej klasy nie można zbudować i kompilacja się nie powiedzie.
@quark wskazuje, że metody czysto wirtualne mogą mieć implementację, ale ponieważ metody czysto wirtualne muszą zostać zastąpione, domyślnej implementacji nie można bezpośrednio wywołać. Oto przykład metody czysto wirtualnej z domyślną:
Według komentarzy to, czy kompilacja się nie powiedzie, zależy od kompilatora. Przynajmniej w GCC 4.3.3 nie kompiluje się:
Wynik:
źródło
Jak działa wirtualne słowo kluczowe?
Załóżmy, że człowiek jest klasą podstawową, a Indian pochodzi od człowieka.
Zadeklarowanie do_work () jako wirtualnego oznacza po prostu: które do_work () do wywołania zostaną określone TYLKO w czasie wykonywania.
Załóżmy, że tak
Jeśli wirtualny nie jest używany, to samo jest określane statycznie lub statycznie powiązane przez kompilator, w zależności od tego, który obiekt wywołuje. Więc jeśli obiekt Man wywołuje do_work (), to man do_work () jest nazywany NAWET ZA POMOCĄ PUNKTÓW DO INDYJSKIEGO OBIEKTU
Uważam, że najczęściej głosowana odpowiedź jest myląca - Każda metoda, niezależnie od tego, czy wirtualna może mieć nadpisaną implementację w klasie pochodnej. W konkretnym odniesieniu do C ++ poprawną różnicą jest powiązanie w czasie wykonywania (gdy używany jest wirtualny) i czas kompilacji (gdy nie jest używany wirtualny, ale metoda jest nadpisana, a wskaźnik bazowy jest wskazywany na obiekcie pochodnym) powiązanie powiązanych funkcji.
Wydaje się, że istnieje inny mylący komentarz, który mówi:
TO JEST ŹLE! Funkcje czysto wirtualne mogą również mieć ciało I MOŻNA BYĆ WDROŻONE! Prawda jest taka, że czystą funkcję wirtualną klasy abstrakcyjnej można nazwać statycznie! Dwaj bardzo dobrzy autorzy to Bjarne Stroustrup i Stan Lippman .... ponieważ napisali ten język.
źródło
Funkcja wirtualna jest funkcją składową zadeklarowaną w klasie bazowej i przedefiniowaną przez klasę pochodną. Funkcje wirtualne są hierarchiczne w kolejności dziedziczenia. Gdy klasa pochodna nie przesłania funkcji wirtualnej, używana jest funkcja zdefiniowana w jej klasie bazowej.
Czysta funkcja wirtualna to taka, która nie zawiera definicji względem klasy podstawowej. Nie ma implementacji w klasie bazowej. Każda klasa pochodna musi zastąpić tę funkcję.
źródło
Simula, C ++ i C #, które domyślnie używają statycznego wiązania metod, programista może określić, że określone metody powinny używać wiązania dynamicznego, oznaczając je jako wirtualne. Dynamiczne wiązanie metod ma kluczowe znaczenie dla programowania obiektowego.
Programowanie obiektowe wymaga trzech podstawowych pojęć: enkapsulacji, dziedziczenia i dynamicznego wiązania metod.
źródło
Metody wirtualne MOGĄ zostać zastąpione przez wyprowadzenie klas, ale wymagają implementacji w klasie bazowej (tej, która zostanie zastąpiona)
Metody czysto wirtualne nie mają implementacji klasy podstawowej. Muszą być zdefiniowane przez klasy pochodne. (Więc technicznie zastąpienie nie jest właściwym terminem, ponieważ nie ma nic do zastąpienia).
Wirtualny odpowiada domyślnemu zachowaniu Java, gdy klasa pochodna zastępuje metodę klasy podstawowej.
Metody Pure Virtual odpowiadają zachowaniu metod abstrakcyjnych w klasach abstrakcyjnych. A klasa, która zawiera wyłącznie metody wirtualne i stałe, byłaby cpp-wisiorek interfejsu.
źródło
Czysta funkcja wirtualna
wypróbuj ten kod
W klasie anotherClass usuń funkcję sayHellow i uruchom kod. dostaniesz błąd! Ponieważ gdy klasa zawiera czystą funkcję wirtualną, z tej klasy nie można utworzyć żadnego obiektu i jest ona dziedziczona, to klasa pochodna musi zaimplementować tę funkcję.
Funkcja wirtualna
wypróbuj inny kod
W tym przypadku funkcja sayHellow jest oznaczona jako wirtualna w klasie bazowej. Mówi kompilator, który próbuje wyszukać funkcję w klasie pochodnej i implementuje funkcję. Jeśli nie zostanie znaleziony, uruchom funkcję podstawową.
źródło
„Funkcja wirtualna lub metoda wirtualna to funkcja lub metoda, której zachowanie można zastąpić w klasie dziedziczącej funkcją o tej samej sygnaturze” - Wikipedia
To nie jest dobre wytłumaczenie funkcji wirtualnych. Ponieważ nawet jeśli członek nie jest wirtualny, dziedziczenie klas może go zastąpić. Możesz spróbować to zobaczyć sam.
Różnica pojawia się, gdy funkcja przyjmuje klasę podstawową jako parametr. Gdy podajesz klasę dziedziczącą jako dane wejściowe, funkcja ta wykorzystuje implementację klasy podstawowej funkcji przesłonięcia. Jeśli jednak ta funkcja jest wirtualna, używa tej, która jest zaimplementowana w klasie pochodnej.
źródło
Funkcje wirtualne muszą mieć definicję w klasie bazowej, a także w klasie pochodnej, ale nie są konieczne, na przykład funkcja ToString () lub toString () jest funkcją wirtualną, dzięki czemu można zapewnić własną implementację, zastępując ją w klasach zdefiniowanych przez użytkownika.
Funkcje wirtualne są deklarowane i definiowane w normalnej klasie.
Czysta funkcja wirtualna musi być zadeklarowana z końcem „= 0” i może być zadeklarowana tylko w klasie abstrakcyjnej.
Klasa abstrakcyjna posiadająca wyłącznie funkcje wirtualne nie może mieć definicji tych funkcji czysto wirtualnych, więc oznacza to, że implementacja musi być zapewniona w klasach pochodzących z tej klasy abstrakcyjnej.
źródło