Ciekawostka

Język C++ rozszerzył możliwości używanego wcześniej języka C o paradygmaty programowania obiektowego. Zmiana ta znacznie poprawiła czytelność kodu, dzięki czemu C++ stał się jednym z najchętniej używanych języków na świecie.

Polimorfizm

Polimorfizm to inaczej wielopostaciowość. Termin ten należy rozumieć jako mechanizmy zawarte w języku programowania, które pozwalają na traktowanie tych samych danych (np. zmiennych, obiektów) w różny sposób. Aby dokładnie zrozumieć ten paradygmat, musimy na początku zaznajomić się z metodami wirtualnymi. Dopiero później będziemy w stanie zrozumieć wielopostaciowość, która w języku C++ związana jest głównie z obiektami dynamicznymi.

Metody wirtualne

Metody wirtualne to ważna część polimorfizmu i abstrakcji. Są to metody, których definicja jest wielopostaciowa — mogą być dziedziczone, nadpisywane oraz rozszerzane w klasach pochodnych.

W języku C++ deklarację metody wirtualnej poprzedzamy słowem kluczowym virtual. Jeśli chcemy utworzyć metodę czysto wirtualnąmetoda czysto wirtualnametodę czysto wirtualną, po deklaracji funkcji dopisujemy =0. Przykład:

Linia 1. class Zwierze otwórz nawias klamrowy. Linia 2. public dwukropek. Linia 3. virtual void jedz otwórz nawias okrągły zamknij nawias okrągły znak równości 0 średnik. Linia 4. zamknij nawias klamrowy średnik.

Metoda zadeklarowana w linijce 3. jest metodą czysto wirtualną.

Klasa Zwierze jest klasą abstrakcyjną — każda klasa, która oparta jest na klasie Zwierze, musi nadpisać metodę jedz().

Zaimplementujmy dwie dodatkowe klasy, które dziedziczą po sobie oraz klasie Zwierze.

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 2. using namespace std średnik. Linia 4. class Zwierze otwórz nawias klamrowy. Linia 5. public dwukropek. Linia 6. virtual void jedz otwórz nawias okrągły zamknij nawias okrągły znak równości 0 średnik. Linia 7. zamknij nawias klamrowy średnik. Linia 9. class Antylopa dwukropek public Zwierze otwórz nawias klamrowy. Linia 10. public dwukropek. Linia 11. void jedz otwórz nawias okrągły zamknij nawias okrągły override otwórz nawias klamrowy. Linia 12. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Antylopa zjada trawe cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 13. zamknij nawias klamrowy. Linia 15. void biegnij otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 16. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Antylopa biegnie cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 17. zamknij nawias klamrowy średnik. Linia 18. zamknij nawias klamrowy średnik. Linia 20. class Gnu dwukropek public Antylopa otwórz nawias klamrowy. Linia 21. public dwukropek. Linia 22. void jedz otwórz nawias okrągły zamknij nawias okrągły override otwórz nawias klamrowy. Linia 23. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Gnu cudzysłów średnik. Linia 24. Antylopa dwukropek dwukropek jedz otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 25. zamknij nawias klamrowy. Linia 26. zamknij nawias klamrowy średnik.

Nadpisując metodę wirtualną, możemy zastosować słowo kluczowe override. Nie jest ono wymagane dla poprawności kodu, ale zwiększa jego czytelność. Nadpisanie metody nie może zmienić jej typu ani właściwości, a jedynie kod, który wykonuje.

Warto zauważyć, że jeśli oznaczymy metodę słowem kluczowym virtual w klasie bazowej, będzie ona wirtualna również we wszystkich klasach pochodnych. Przykładem jest klasa Gnu – zostaje w niej nadpisana wirtualna metoda z klasy nadrzędnej Antylopa, mimo że nie była oznaczona słowem virtual. Dzieje się tak, ponieważ klasa Antylopa dziedziczy po klasie Zwierzę, gdzie metoda jedz() jest oznaczona jako wirtualna.

Zwróć uwagę na odwołanie do metody jedz() z klasy bazowej w linijce 24. Możemy w trakcie realizacji metody pochodnej wykonać kod, który zdefiniowany jest w klasie bazowej. Dzięki temu nadpisywanie metody nie ogranicza się do zdefiniowania funkcji na nowo, ale umożliwia także jej rozszerzanie.

W linijce 15. została zadeklarowana metoda biegnij(). Nie jest ona metodą wirtualną, więc nie można jej nadpisać w klasie Gnu. Jeżeli spróbujemy to zrobić, kompilator potraktuje to jako błąd.

Spróbujmy zatem nadpisać metodę biegnij() z klasy Antylopa w klasie Gnu. Jednak na razie nie zmieniajmy kodu klasy Antylopa.

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 2. using namespace std średnik. Linia 4. class Zwierze otwórz nawias klamrowy. Linia 5. public dwukropek. Linia 6. virtual void jedz otwórz nawias okrągły zamknij nawias okrągły znak równości 0 średnik. Linia 7. zamknij nawias klamrowy średnik. Linia 9. class Antylopa dwukropek public Zwierze otwórz nawias klamrowy. Linia 10. public dwukropek. Linia 11. void jedz otwórz nawias okrągły zamknij nawias okrągły override otwórz nawias klamrowy. Linia 12. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Antylopa zjada trawe cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 13. zamknij nawias klamrowy. Linia 15. void biegnij otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 16. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Antylopa biegnie cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 17. zamknij nawias klamrowy średnik. Linia 18. zamknij nawias klamrowy średnik. Linia 20. class Gnu dwukropek public Antylopa otwórz nawias klamrowy. Linia 21. public dwukropek. Linia 22. void jedz otwórz nawias okrągły zamknij nawias okrągły override otwórz nawias klamrowy. Linia 23. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Gnu cudzysłów średnik. Linia 24. Antylopa dwukropek dwukropek jedz otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 25. zamknij nawias klamrowy. Linia 27. prawy ukośnik prawy ukośnik błędne nadpisanie metody niewirtualnej. Linia 28. void biegnij otwórz nawias okrągły zamknij nawias okrągły override otwórz nawias klamrowy. Linia 29. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Gnu cudzysłów średnik. Linia 30. Antylopa dwukropek dwukropek biegnij otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 31. zamknij nawias klamrowy. Linia 32. zamknij nawias klamrowy średnik.

Podczas próby kompilacji przedstawionego kodu powinien wystąpić błąd. Aby nadpisać metodę biegnij() z klasy Antylopa, poprzedzamy jej definicję słowem kluczowym virtual. Przedstawiony poniżej kod powinien skompilować się poprawnie.

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 2. using namespace std średnik. Linia 4. class Zwierze otwórz nawias klamrowy. Linia 5. public dwukropek. Linia 6. virtual void jedz otwórz nawias okrągły zamknij nawias okrągły znak równości 0 średnik. Linia 7. zamknij nawias klamrowy średnik. Linia 9. class Antylopa dwukropek public Zwierze otwórz nawias klamrowy. Linia 10. public dwukropek. Linia 11. void jedz otwórz nawias okrągły zamknij nawias okrągły override otwórz nawias klamrowy. Linia 12. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Antylopa zjada trawe cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 13. zamknij nawias klamrowy. Linia 15. virtual void biegnij otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 16. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Antylopa biegnie cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 17. zamknij nawias klamrowy średnik. Linia 18. zamknij nawias klamrowy średnik. Linia 20. class Gnu dwukropek public Antylopa otwórz nawias klamrowy. Linia 21. public dwukropek. Linia 22. void jedz otwórz nawias okrągły zamknij nawias okrągły override otwórz nawias klamrowy. Linia 23. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Gnu cudzysłów średnik. Linia 24. Antylopa dwukropek dwukropek jedz otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 25. zamknij nawias klamrowy. Linia 27. void biegnij otwórz nawias okrągły zamknij nawias okrągły override otwórz nawias klamrowy. Linia 28. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Gnu biegnie cudzysłów średnik. Linia 29. zamknij nawias klamrowy. Linia 30. zamknij nawias klamrowy średnik.

W celu przetestowania stworzonych klas, możemy napisać funkcję główną programu, w której utworzymy obiekty klasy Antylopa oraz Gnu. Następnie wywołamy na nich metody jedz() oraz biegnij().

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 2. using namespace std średnik. Linia 4. class Zwierze otwórz nawias klamrowy. Linia 5. public dwukropek. Linia 6. virtual void jedz otwórz nawias okrągły zamknij nawias okrągły znak równości 0 średnik. Linia 7. zamknij nawias klamrowy średnik. Linia 9. class Antylopa dwukropek public Zwierze otwórz nawias klamrowy. Linia 10. public dwukropek. Linia 11. void jedz otwórz nawias okrągły zamknij nawias okrągły override otwórz nawias klamrowy. Linia 12. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Antylopa zjada trawe cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 13. zamknij nawias klamrowy. Linia 15. virtual void biegnij otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 16. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Antylopa biegnie cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 17. zamknij nawias klamrowy średnik. Linia 18. zamknij nawias klamrowy średnik. Linia 20. class Gnu dwukropek public Antylopa otwórz nawias klamrowy. Linia 21. public dwukropek. Linia 22. void jedz otwórz nawias okrągły zamknij nawias okrągły override otwórz nawias klamrowy. Linia 23. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Gnu cudzysłów średnik. Linia 24. Antylopa dwukropek dwukropek jedz otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 25. zamknij nawias klamrowy. Linia 27. void biegnij otwórz nawias okrągły zamknij nawias okrągły override otwórz nawias klamrowy. Linia 28. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Gnu biegnie cudzysłów średnik. Linia 29. zamknij nawias klamrowy. Linia 30. zamknij nawias klamrowy średnik. Linia 32. int main otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 33. Antylopa antylopa średnik. Linia 34. Gnu gnu średnik. Linia 36. antylopa kropka jedz otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 37. antylopa kropka biegnij otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 38. gnu kropka jedz otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 39. gnu kropka biegnij otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 41. return 0 średnik. Linia 42. zamknij nawias klamrowy.

Przedstawiony program powinien wypisać w konsoli:

Linia 1. Antylopa zjada trawe. Linia 2. Antylopa biegnie. Linia 3. Gnu Antylopa zjada trawe. Linia 4. Gnu biegnie.

Polimorfizm dynamiczny

W języku C++ możemy definiować tablice obiektów dynamicznych tego samego typu bazowego, jednak różniących się typem pochodnym. Warto w tym miejscu omówić dwa przykłady.

Kod pierwszego przykładu wygląda następująco:

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 2. using namespace std średnik. Linia 4. class Zwierze otwórz nawias klamrowy. Linia 5. public dwukropek. Linia 6. virtual void jedz otwórz nawias okrągły zamknij nawias okrągły znak równości 0 średnik. Linia 7. zamknij nawias klamrowy średnik. Linia 9. class Kot dwukropek public Zwierze otwórz nawias klamrowy. Linia 10. public dwukropek. Linia 11. void jedz otwórz nawias okrągły zamknij nawias okrągły override otwórz nawias klamrowy. Linia 12. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Kot zjada mysz cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 13. zamknij nawias klamrowy. Linia 15. void biegnij otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 16. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Kot biegnie cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 17. zamknij nawias klamrowy średnik. Linia 18. zamknij nawias klamrowy średnik. Linia 20. class Antylopa dwukropek public Zwierze otwórz nawias klamrowy. Linia 21. public dwukropek. Linia 22. void jedz otwórz nawias okrągły zamknij nawias okrągły override otwórz nawias klamrowy. Linia 23. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Antylopa zjada trawe cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 24. zamknij nawias klamrowy. Linia 26. void biegnij otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 27. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Antylopa biegnie cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 28. zamknij nawias klamrowy średnik. Linia 29. zamknij nawias klamrowy średnik. Linia 31. class Gnu dwukropek public Antylopa otwórz nawias klamrowy. Linia 32. public dwukropek. Linia 33. void jedz otwórz nawias okrągły zamknij nawias okrągły override otwórz nawias klamrowy. Linia 34. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Gnu cudzysłów średnik. Linia 35. Antylopa dwukropek dwukropek jedz otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 36. zamknij nawias klamrowy. Linia 37. zamknij nawias klamrowy średnik. Linia 39. int main otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 40. prawy ukośnik asterysk przykład pierwszy asterysk prawy ukośnik. Linia 41. Zwierze asterysk tablica podkreślnik zwierzat otwórz nawias kwadratowy 3 zamknij nawias kwadratowy znak równości otwórz nawias klamrowy. Linia 42. new Antylopa otwórz nawias okrągły zamknij nawias okrągły przecinek. Linia 43. new Gnu otwórz nawias okrągły zamknij nawias okrągły przecinek. Linia 44. new Kot otwórz nawias okrągły zamknij nawias okrągły. Linia 45. zamknij nawias klamrowy średnik. Linia 47. for otwórz nawias okrągły int i znak równości 0 średnik i otwórz nawias ostrokątny 3 średnik plus plus i zamknij nawias okrągły otwórz nawias klamrowy. Linia 48. otwórz nawias okrągły asterysk tablica podkreślnik zwierzat otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias okrągły kropka jedz otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 49. prawy ukośnik prawy ukośnik element tablicy jest traktowany jako Zwierze. Linia 50. prawy ukośnik prawy ukośnik otwórz nawias okrągły nie jako Antylopa zamknij nawias okrągły. Linia 51. prawy ukośnik prawy ukośnik minus brak metody biegnij w klasie Zwierze. Linia 52. prawy ukośnik prawy ukośnik otwórz nawias okrągły asterysk tablica podkreślnik zwierzat otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias okrągły kropka biegnij otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 53. zamknij nawias klamrowy. Linia 55. prawy ukośnik prawy ukośnik każdy obiekt dynamiczny musi zostać usunięty. Linia 56. for otwórz nawias okrągły int i znak równości 0 średnik i otwórz nawias ostrokątny 3 średnik plus plus i zamknij nawias okrągły otwórz nawias klamrowy. Linia 57. delete tablica podkreślnik zwierzat otwórz nawias kwadratowy i zamknij nawias kwadratowy średnik. Linia 58. zamknij nawias klamrowy. Linia 60. return 0 średnik. Linia 61. zamknij nawias klamrowy.

W przedstawionym przykładzie została dodana prosta klasa Kot dziedzicząca po klasie Zwierze.

W funkcji głównej programu deklarujemy trójelementową tablicę wskaźników na obiekty dynamiczne typu Zwierze. Dzięki wbudowanemu w język C++ polimorfizmowi możemy taką tablicę wypełnić wskaźnikami na różne obiekty dynamiczne, których klasy dziedziczą po typie Zwierze. Jak widać na przykładzie, w deklaracji tablicy tworzymy nowe obiekty typu Antylopa, Gnu oraz Kot.

W linijce 48. dla każdego obiektu, na który wskazują wskaźniki z tablicy tablica_zwierząt, wywołujemy metodę jedz(). Zastanów się, jaki będzie wynik programu. Przetestuj jego działanie.

Linia 1. Antylopa zjada trawe. Linia 2. Gnu Antylopa zjada trawe. Linia 3. Kot zjada mysz.

Zwróć uwagę na to, że wszystkie obiekty, na które wskazują elementy tablicy tablica_zwierząt, traktowane są jako obiekty klasy Zwierze. Oznacza to, że metody, które chcemy wywołać, muszą być widoczne w klasie bazowej Zwierze. Sprawdź, co się stanie, gdy odkomentujemy linijkę nr 52 i spróbujemy wywołać metodę, która nie występuje w klasie Zwierze. Mimo że każdy obiekt posiada metodę biegnij(), wystąpi błąd, gdyż nie jest ona widoczna z poziomu klasy Zwierze.

Przykład drugi:

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 2. using namespace std średnik. Linia 4. class Zwierze otwórz nawias klamrowy. Linia 5. public dwukropek. Linia 6. virtual void jedz otwórz nawias okrągły zamknij nawias okrągły znak równości 0 średnik. Linia 7. zamknij nawias klamrowy średnik. Linia 9. class Kot dwukropek public Zwierze otwórz nawias klamrowy. Linia 10. public dwukropek. Linia 11. void jedz otwórz nawias okrągły zamknij nawias okrągły override otwórz nawias klamrowy. Linia 12. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Kot zjada mysz cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 13. zamknij nawias klamrowy. Linia 15. void biegnij otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 16. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Kot biegnie cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 17. zamknij nawias klamrowy średnik. Linia 18. zamknij nawias klamrowy średnik. Linia 20. class Antylopa dwukropek public Zwierze otwórz nawias klamrowy. Linia 21. public dwukropek. Linia 22. void jedz otwórz nawias okrągły zamknij nawias okrągły override otwórz nawias klamrowy. Linia 23. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Antylopa zjada trawe cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 24. zamknij nawias klamrowy. Linia 26. void biegnij otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 27. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Antylopa biegnie cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 28. zamknij nawias klamrowy średnik. Linia 29. zamknij nawias klamrowy średnik. Linia 31. class Gnu dwukropek public Antylopa otwórz nawias klamrowy. Linia 32. public dwukropek. Linia 33. void jedz otwórz nawias okrągły zamknij nawias okrągły override otwórz nawias klamrowy. Linia 34. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Gnu cudzysłów średnik. Linia 35. Antylopa dwukropek dwukropek jedz otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 36. zamknij nawias klamrowy. Linia 37. zamknij nawias klamrowy średnik. Linia 39. int main otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 40. prawy ukośnik asterysk przykład drugi asterysk prawy ukośnik. Linia 41. Antylopa asterysk tablica podkreślnik antylop otwórz nawias kwadratowy 3 zamknij nawias kwadratowy znak równości otwórz nawias klamrowy. Linia 42. new Antylopa otwórz nawias okrągły zamknij nawias okrągły przecinek. Linia 43. new Gnu otwórz nawias okrągły zamknij nawias okrągły przecinek. Linia 44. new Antylopa otwórz nawias okrągły zamknij nawias okrągły. Linia 45. zamknij nawias klamrowy średnik. Linia 47. for otwórz nawias okrągły int i znak równości 0 średnik i otwórz nawias ostrokątny 3 średnik plus plus i zamknij nawias okrągły otwórz nawias klamrowy. Linia 48. otwórz nawias okrągły asterysk tablica podkreślnik antylop otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias okrągły kropka jedz otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 49. otwórz nawias okrągły asterysk tablica podkreślnik antylop otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias okrągły kropka biegnij otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 50. zamknij nawias klamrowy. Linia 52. prawy ukośnik prawy ukośnik każdy obiekt dynamiczny musi zostać usunięty. Linia 53. for otwórz nawias okrągły int i znak równości 0 średnik i otwórz nawias ostrokątny 3 średnik plus plus i zamknij nawias okrągły otwórz nawias klamrowy. Linia 54. delete tablica podkreślnik antylop otwórz nawias kwadratowy i zamknij nawias kwadratowy średnik. Linia 55. zamknij nawias klamrowy. Linia 57. return 0 średnik. Linia 58. zamknij nawias klamrowy.

W tym przykładzie zmieniamy typ tablicy na Antylopa i tworzymy w niej dwa obiekty klasy Antylopa oraz jeden obiekt klasy Gnu. Zwróć uwagę, że każdy obiekt typu Gnu jest również obiektem typu Antylopa.

Uruchom przedstawiony kod i sprawdź, jakie otrzymasz wyniki. Zauważ, że w pętli w linijce 47. można wywołać obie metody jedz() oraz biegnij(), ponieważ wszystkie użyte metody są widoczne w klasie Antylopa. Ostatecznie wynik prezentuje się następująco:

Linia 1. Antylopa zjada trawe. Linia 2. Antylopa biegnie. Linia 3. Gnu Antylopa zjada trawe. Linia 4. Antylopa biegnie. Linia 5. Antylopa zjada trawe. Linia 6. Antylopa biegnie.

Hermetyzacja w języku C++

Hermetyzacja to inaczej ukrywanie implementacji. Paradygmat ten odnosi się do danych oraz funkcji, które je modyfikują. Dzięki hermetyzacji możemy ukrywać dostęp do danych oraz metod, kontrolując tym samym interakcję między obiektami.

Z mechanizmem hermetyzacji powiązane są trzy podstawowe modyfikatory dostępumodyfikatory dostępumodyfikatory dostępu:

  • prywatny (private) – zmienna może być modyfikowana i odczytywana tylko w klasie, w której została zadeklarowana,

  • chroniony (protected) – zmienna może być modyfikowana i odczytywana w klasie, w której została zadeklarowana oraz w klasach pochodnych od klasy, w której została zadeklarowana,

  • publiczny (public) – zmienna może być modyfikowana i odczytywana w dowolnym miejscu programu, w którym mamy dostęp do obiektu.

Dzięki nim mamy możliwość wydzielenia w strukturze klasy sekcji o różnym dostępie do pól oraz metod.

Aby zweryfikować działania modyfikatorów dostępu, umieśćmy w klasie bazowej Zwierze trzy zmienne: publiczną, chronioną i prywatną:

Linia 1. class Zwierze otwórz nawias klamrowy. Linia 2. private dwukropek. Linia 3. int zmiennaA znak równości 1 średnik. Linia 4. protected dwukropek. Linia 5. int zmiennaB znak równości 2 średnik. Linia 6. public dwukropek. Linia 7. int zmiennaC znak równości 3 średnik. Linia 8. virtual void jedz otwórz nawias okrągły zamknij nawias okrągły znak równości 0 średnik. Linia 9. zamknij nawias klamrowy średnik.

Mamy poprawną deklarację trzech pól w klasie Zwierze. Napiszmy dwie metody, po jednej w klasie ZwierzeAntylopa, w których zbadamy dostęp do tych trzech zmiennych. Spróbujemy uzyskać dostęp do zmiennych oraz wypisać je na ekran. Jednocześnie w funkcji main umieścimy kod, w którym również spróbujemy sprawdzić dostęp do zawartości zmiennych. Kod prezentuje się następująco:

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 2. using namespace std średnik. Linia 4. class Zwierze otwórz nawias klamrowy. Linia 5. private dwukropek. Linia 6. int zmiennaA znak równości 1 średnik. Linia 7. protected dwukropek. Linia 8. int zmiennaB znak równości 2 średnik. Linia 9. public dwukropek. Linia 10. int zmiennaC znak równości 3 średnik. Linia 11. virtual void jedz otwórz nawias okrągły zamknij nawias okrągły znak równości 0 średnik. Linia 13. void metoda1 otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 14. cout otwórz nawias ostrokątny otwórz nawias ostrokątny zmiennaA otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 15. cout otwórz nawias ostrokątny otwórz nawias ostrokątny zmiennaB otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 16. cout otwórz nawias ostrokątny otwórz nawias ostrokątny zmiennaC otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 17. zamknij nawias klamrowy. Linia 18. zamknij nawias klamrowy średnik. Linia 20. class Antylopa dwukropek public Zwierze otwórz nawias klamrowy. Linia 21. public dwukropek. Linia 22. void jedz otwórz nawias okrągły zamknij nawias okrągły override otwórz nawias klamrowy. Linia 23. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Antylopa zjada trawe cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 24. zamknij nawias klamrowy. Linia 26. void biegnij otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 27. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Antylopa biegnie cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 28. zamknij nawias klamrowy średnik. Linia 30. void metoda2 otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 31. cout otwórz nawias ostrokątny otwórz nawias ostrokątny zmiennaA otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 32. cout otwórz nawias ostrokątny otwórz nawias ostrokątny zmiennaB otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 33. cout otwórz nawias ostrokątny otwórz nawias ostrokątny zmiennaC otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 34. zamknij nawias klamrowy. Linia 35. zamknij nawias klamrowy średnik. Linia 37. int main otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 38. prawy ukośnik prawy ukośnik instancja klasy Antylopa. Linia 39. Antylopa antylopa średnik. Linia 41. prawy ukośnik prawy ukośnik dostęp z metody z klasy bazowej. Linia 42. antylopa kropka metoda1 otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 44. prawy ukośnik prawy ukośnik dostęp z metody z klasy pochodnej. Linia 45. antylopa kropka metoda2 otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 47. prawy ukośnik prawy ukośnik dostęp funkcji głównej programu. Linia 48. cout otwórz nawias ostrokątny otwórz nawias ostrokątny antylopa kropka zmiennaA otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 49. cout otwórz nawias ostrokątny otwórz nawias ostrokątny antylopa kropka zmiennaB otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 50. cout otwórz nawias ostrokątny otwórz nawias ostrokątny antylopa kropka zmiennaC otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 52. return 0 średnik. Linia 53. zamknij nawias klamrowy.

Możemy przypuszczać, że program nie uruchomi się, ponieważ w wielu przypadkach nie mamy dostępu do zmiennych, których wartość próbujemy poznać. Kluczowe są dla nas linijki nr 14, 15, 16 oraz nr 31, 32, 33, a także nr 48, 49, 50. Zastanów się, które z nich zostaną uznane przez kompilator z błędne. Oczywiście będą to linijki nr 31, 48 i 49.

Oto kod, w którym komentarzami oznaczono błędne wiersze. Dodano również wyjaśnienie, na czym polegał błąd:

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 2. using namespace std średnik. Linia 4. class Zwierze otwórz nawias klamrowy. Linia 5. private dwukropek. Linia 6. int zmiennaA znak równości 1 średnik. Linia 7. protected dwukropek. Linia 8. int zmiennaB znak równości 2 średnik. Linia 9. public dwukropek. Linia 10. int zmiennaC znak równości 3 średnik. Linia 11. virtual void jedz otwórz nawias okrągły zamknij nawias okrągły znak równości 0 średnik. Linia 13. void metoda1 otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 14. cout otwórz nawias ostrokątny otwórz nawias ostrokątny zmiennaA otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 15. cout otwórz nawias ostrokątny otwórz nawias ostrokątny zmiennaB otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 16. cout otwórz nawias ostrokątny otwórz nawias ostrokątny zmiennaC otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 17. zamknij nawias klamrowy. Linia 18. zamknij nawias klamrowy średnik. Linia 20. class Antylopa dwukropek public Zwierze otwórz nawias klamrowy. Linia 21. public dwukropek. Linia 22. void jedz otwórz nawias okrągły zamknij nawias okrągły override otwórz nawias klamrowy. Linia 23. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Antylopa zjada trawe cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 24. zamknij nawias klamrowy. Linia 26. void biegnij otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 27. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Antylopa biegnie cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 28. zamknij nawias klamrowy średnik. Linia 30. void metoda2 otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 31. prawy ukośnik prawy ukośnik dostęp do prywatnej zmiennej klasy bazowej. Linia 32. prawy ukośnik prawy ukośnik nie jest możliwy z klasy pochodnej. Linia 33. prawy ukośnik prawy ukośnik cout otwórz nawias ostrokątny otwórz nawias ostrokątny zmiennaA otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 34. cout otwórz nawias ostrokątny otwórz nawias ostrokątny zmiennaB otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 35. cout otwórz nawias ostrokątny otwórz nawias ostrokątny zmiennaC otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 36. zamknij nawias klamrowy. Linia 37. zamknij nawias klamrowy średnik. Linia 39. int main otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 40. prawy ukośnik prawy ukośnik instancja klasy Antylopa. Linia 41. Antylopa antylopa średnik. Linia 43. prawy ukośnik prawy ukośnik dostęp z metody z klasy bazowej. Linia 44. antylopa kropka metoda1 otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 46. prawy ukośnik prawy ukośnik dostęp z metody z klasy pochodnej. Linia 47. antylopa kropka metoda2 otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 49. prawy ukośnik prawy ukośnik dostęp funkcji głównej programu. Linia 50. cout otwórz nawias ostrokątny otwórz nawias ostrokątny antylopa kropka zmiennaC otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 51. prawy ukośnik prawy ukośnik dostęp do zmiennych prywatnych oraz chronionych. Linia 52. prawy ukośnik prawy ukośnik nie jest możliwy z poziomu funkcji głównej programu. Linia 53. prawy ukośnik prawy ukośnik cout otwórz nawias ostrokątny otwórz nawias ostrokątny antylopa kropka zmiennaA otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 54. prawy ukośnik prawy ukośnik cout otwórz nawias ostrokątny otwórz nawias ostrokątny antylopa kropka zmiennaB otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 56. return 0 średnik. Linia 57. zamknij nawias klamrowy.

Słownik

metoda czysto wirtualna
metoda czysto wirtualna

możliwa do zadeklarowania tylko w klasie abstrakcyjnej metoda, która musi zostać zaimplementowana w klasach dziedziczących po danej klasie; w klasie bazowej nie posiada implementacji, a jedynie deklarację

modyfikatory dostępu
modyfikatory dostępu

słowa kluczowe, za pomocą których definiujemy zakres widoczności elementów takich jak klasy, pola oraz metody