Załóżmy taki scenariusz w Visual C ++ 2010:
#include <iostream>
#include <conio.h>
using namespace std;
class Base
{
public:
int b;
void Display()
{
cout<<"Base: Non-virtual display."<<endl;
};
virtual void vDisplay()
{
cout<<"Base: Virtual display."<<endl;
};
};
class Derived : public Base
{
public:
int d;
void Display()
{
cout<<"Derived: Non-virtual display."<<endl;
};
virtual void vDisplay()
{
cout<<"Derived: Virtual display."<<endl;
};
};
int main()
{
Base ba;
Derived de;
ba.Display();
ba.vDisplay();
de.Display();
de.vDisplay();
_getch();
return 0;
};
Teoretycznie wynik tej małej aplikacji powinien wyglądać następująco:
- Podstawa: wyświetlacz niewirtualny.
- Podstawa: wirtualny wyświetlacz.
- Podstawa: wyświetlacz niewirtualny.
- Pochodny: wyświetlacz wirtualny.
ponieważ metoda Display klasy Base nie jest metodą wirtualną, więc klasa pochodna nie powinna mieć możliwości jej przesłonięcia. Dobrze?
Problem w tym, że kiedy uruchamiam aplikację, wypisuje to:
- Podstawa: wyświetlacz niewirtualny.
- Podstawa: wirtualny wyświetlacz.
- Pochodny: wyświetlacz niewirtualny.
- Pochodny: wyświetlacz wirtualny.
Więc albo nie rozumiałem pojęcia metod wirtualnych, albo coś dziwnego dzieje się w Visual C ++.
Czy ktoś mógłby mi pomóc w wyjaśnieniu?
c++
overriding
Leif Lazar
źródło
źródło
de.Base::Display()
.Odpowiedzi:
Tak, trochę nie rozumiesz.
Metoda o tej samej nazwie w klasie pochodnej spowoduje ukrycie metody nadrzędnej w tym przypadku. Można by sobie wyobrazić, że gdyby tak nie było, próba utworzenia metody o takiej samej nazwie jak metoda niewirtualna klasy bazowej powinna spowodować błąd. Jest to dozwolone i nie stanowi problemu - a jeśli wywołasz metodę bezpośrednio, tak jak to zrobiłeś, zostanie nazwana dobrze.
Ale ponieważ nie są wirtualne, mechanizmy wyszukiwania metod w C ++, które pozwalają na polimorfizm, nie będą używane. Na przykład, jeśli utworzyłeś instancję swojej klasy pochodnej, ale wywołałeś swoją metodę 'Display' przez wskaźnik do klasy bazowej, zostanie wywołana metoda bazy, podczas gdy dla 'vDisplay' zostanie wywołana metoda pochodna.
Na przykład spróbuj dodać te wiersze:
... i obserwuj wynik zgodnie z oczekiwaniami:
źródło
Tak, trochę źle zrozumiałeś:
Czyste funkcje wirtualne:
virtual void fun1()=0
-> musi zostać przesłonięty w klasie pochodnejFunkcje wirtualne:
virtual void fun2()
-> można zmienićNormalne funkcje:
void fun3()
-> nie zastępuj goAby uzyskać polimorfizm w czasie wykonywania, musisz przesłonić funkcje wirtualne w języku c ++
źródło
Myślę, że lepiej byłoby też spojrzeć na to w kontekście wiązania statycznego i dynamicznego.
Jeśli metoda nie jest wirtualna (jest już domyślnie w C ++ w przeciwieństwie do Javy), wówczas metoda wiąże się z obiektem wywołującym w czasie kompilacji, przez co nie można poznać rzeczywistego obiektu, który zostanie wskazany w czasie wykonywania. Zatem liczy się tylko typ zmiennej, czyli „Baza”.
źródło