Metoda wirtualna: Różnice pomiędzy wersjami

[wersja przejrzana][wersja przejrzana]
Usunięta treść Dodana treść
ToBot (dyskusja | edycje)
m Wspomagane przez bota ujednoznacznienie (tyle do zrobienia): Implementacja
m poprawa linków
Linia 7:
 
==== C++ ====
* Słowo kluczowe ''virtual'' można pominąć w [[deklaracja (informatyka)|deklaracjach]]ch w klasach pochodnych.
* Słowo kluczowe ''virtual'' określa się tylko w deklaracji metody, nie określa się tego w definicji (chyba że deklaracja jest jednocześnie definicją, co ma miejsce gdy [[Implementacja (informatyka)|implementacja]] metody zostanie określona w ciele klasy).
 
Linia 14:
 
=== Zastosowania ===
* Rozszerzalność [[Kod źródłowy|kodu]]. [[Polimorfizm (informatyka)|Polimorfizm]] umożliwia rozszerzanie nawet skompilowanych fragmentów kodu.
** Pozwala na rozszerzalność kodu również wtedy, gdy dostępna jest jedynie [[kompilacja (informatyka)|skompilowana]] wersja klasy bazowej.
* Zwalnia programistę od niepotrzebnego wysiłku.
Linia 114:
W przykładzie znajdują się deklaracje 3 klas: <code>Figura</code>, <code>Kwadrat</code> i <code>Kolo</code>. W klasie <code>Figura</code> została zadeklarowana metoda wirtualna (słowo kluczowe ''virtual'') <code>virtual float pole()</code>. Każda z klas pochodnych od klasy <code>Figura</code> ma zaimplementowane swoje metody <code>float pole()</code>. Następnie (w funkcji main) znajdują się deklaracje obiektów każdej z klas i wskaźnika mogącego pokazywać na obiekty klasy bazowej <code>Figura</code>.
 
Wywołanie metod składowych dla każdego z obiektów powoduje wykonanie metody odpowiedniej dla klasy danego obiektu. Następnie wskaźnikowi <code>wskJakasFigura</code> zostaje przypisany adres obiektu <code>jakasFigura</code> i zostaje wywołana metoda <code>float pole()</code>. Wynikiem jest ''"-1"'' zgodnie z treścią metody <code>float pole()</code> w klasie <code>Figura</code>. Następnie przypisujemy wskaźnikowi adres obiektu klasy Kwadrat - możemy tak zrobić ponieważ klasa <code>Kwadrat</code> jest klasą pochodną od klasy <code>Figura</code> - jest to tzw. [[rzutowanie w górę]]. Wywołanie teraz metody <code>float pole()</code> dla wskaznika nie spowoduje wykonania metody zgodnej z typem wskaźnika - który jest typu <code>Figura*</code> lecz zgodnie z aktualnie wskazywanym obiektem, a więc wykonana zostanie metoda <code>float pole()</code> z klasy <code>Kwadrat</code> (gdyż ostatnie przypisanie wskaźnikowi wartości przypisywało mu adres obiektu klasy <code>Kwadrat</code>). Analogiczna sytuacja dzieje się gdy przypiszemy wskaźnikowi adres obiektu klasy <code>Kolo</code>. Następnie zostaje wykonana funkcja <code>void wyswietlPole(Figura&)</code> która przyjmuje jako parametr obiekt klasy <code>Figura</code> przez [[referencjaReferencja (informatyka)|referencję]]. Tutaj również zostały wykonane odpowiednie metody dla obiektów klas pochodnych a nie metoda zgodna z obiektem jaki jest zadeklarowany jako parametr funkcji czyli <code>float Figura::pole()</code>. Takie działanie jest spowodowane przez przyjmowanie obiektu klasy <code>Figura</code> przez referencję. Gdyby obiekty były przyjmowane przez wartość (parametr bez ''&'') zostałaby wykonana 3 krotnie metoda <code>float Figura::pole()</code> i 3 krotnie wyświetlona wartość ''-1''.
 
Wyżej opisane działanie zostało spowodowane przez określenie metody w klasie bazowej jako '''wirtualnej'''. Gdyby zostało usunięte słowo kluczowe ''virtual'' w deklaracji metody w klasie bazowej, zostałyby wykonane metody zgodne z typem wskaźnika lub referencji, a więc za każdym razem zostałaby wykonana metoda <code>float pole()</code> z klasy <code>Figura</code>.