Run Code
|
API
|
Code Wall
|
Misc
|
Feedback
|
Login
|
Theme
|
Privacy
|
Patreon
Polimorfizm :)
#include <iostream> class Base { protected: // Jeżeli Value byłoby private to nie moglibyśmy go użyć w klasach dziedziczących z Base int Value; public: void SetValue(int NewValue) //Metoda niewirtualna - nie można przeciążyć jej w klasach dziedziczących { Value=NewValue; } virtual int GetValue() //Metoda wirtualna - można ją przeciążyć w klasach dziedziczących { return Value; } }; class Div_A : public Base { int GetValue() //Metoda niewirtualna - nie można przeciążyć jej w klasach dziedziczących //Ale jest wirtualna w klasie bazowej dlatego możemy ją przeciążyć { return Value+1; } void Write() { std::cout<<"Hallo world!\n"; } }; class Div_B : public Base { int GetValue() //Jak wyżej ^ { return Value+Value; } }; class Div_C : public Base { int GetValue() //Jak wyżej ^ { return Value*Value; } }; int main() { Base* Tab[3]; //Trzy elementowa tablica wskaźników na obiekty klasy Base Tab[0] = new Div_A; Tab[1] = new Div_B; Tab[2] = new Div_C; // Jeżeli chcemy dostać obiekt, na jaki pokazuje wskaźnik zawarty np. w Tab[0] // to używamy operatora dereferencji (wyłuskania) '*' // Mamy zatem *Tab[0] // Teraz dopiero możemy wywołać metodę jaka jest zawarta wewnątrz obiektu jaki uzyskaliśmy // czyt. taki zapis Tab[0].SetValue(10); nie ma sensu bo wskaźnik Tab[0] zawiera tylko adres.. // a adres nie jest obiektem, który wewnątrz zawiera jakiekolwiek metody (to tylko jakaś liczba) // Trzeba zatem najpierw "wydobyć" obiekt na jaki pokazuje wskaźnik, a dopiero potem wywołać jego metodę // A więc: (*Tab[0]).SetValue(10); // Jednak programiści uznali, że taki zapis (mimo, że jest prawidłowy) to jest brzydki i mało czytelny // Dlatego można zastąpić te nawiasy, kropki i gwiazdeczki czymś takim: Tab[1]->SetValue(10); // Właśnie wywołałem metodę obiektu na jaki pokazuje wkaźnik Tab[1] // Jako że Tab to tablica wskaźników na klasę Base to możemy wywołać przy pomocy tych wskaźników // tylko metody znajdujące się w klasie Base! (Jeżeli jakaś metoda nie znajdowałaby się w klasie Base to wywołanie jej byłoby niemożliwe): // Np. zapis: Tab[0]->Write(); wywoła błąd (co prawda metoda Write znajduje się w obiekcie typu Div_A ale nie znajduje się wewnątrz klasy Base, a wskaźnik jest właśnie typu Base) // Jednak jeżeli: // 1. Jakaś metoda w klasie Base jest wirtualna i w klasach dziedziczących po niej zostanie ona nadpisana // 2. oraz w rzeczywistości wskaźnik mimo, że jest typu Base zawiera obiekt dziedziczący z klasy Base // (W tym wypadku Tab[1] zawiera adres obiektu typu Div_B, a nie czystego Base) // Wtedy jeżeli zostanie wywołana metoda wirtualna kompilator ogarnie, że ma zostać wywołana metoda nadpisana w klasie dziedziczącej // tak więc mając zapis: Tab[2]->SetValue(10); // Tutaj wywołujemy metodę niewirtualną; nienadpisaną, która znajduje się tylko w klasie bazowej for(int i=0; i<3; ++i) { std::cout<<Tab[i]->GetValue()<<' '; //Tutaj wywołujemy metodę GetValue, która normalnie znajduje się w klasie Base, ale posiada różne //nadpisane wersje. Zależnie od obiektu dziedziczącego wywoła inny efekt. } //Teraz naciśnij [Run it (F8)] i zobacz efekt ;) for(int i=0; i<3; ++i) delete Tab[i]; // Bo zawsze należy po sobie posprzątać ^^ }
run
|
edit
|
history
|
help
0
Expected GCD
Do While Meteoro Agustin
Finding Ocean
major element
test
Matrix multiplication naive approach
Easy String Reverse Example
Optimization Lab 2
Test 14(2020)
Menu Combination Sum