• Nie Znaleziono Wyników

Podstawy programowania II

N/A
N/A
Protected

Academic year: 2022

Share "Podstawy programowania II"

Copied!
37
0
0

Pełen tekst

(1)

Podstawy

programowania II

Wykład pt.:

Programowanie obiektowe

autor: dr inż. Michał Łabowski michal.labowski@wat.edu.pl www.mlabowski.wel.wat.edu.pl

(2)

programowanie strukturalne, programowanie obiektowe Programowanie proceduralne:

• paradygmat programowania

• program składa się z bloku głównego (funkcja main) określającego kolejność operacji wykonywanych przez moduły (funkcje)

• unikanie zmiennych globalnych, wymiana danych pomiędzy modułami za pomocą interfejsów (argumenty aktualne funkcji)

• używanie instrukcji warunkowych (if , if else), pętli (for, while, do while), unikanie instrukcji skoku (goto)

Zalety:

• dobry sposób na rozpoczęcie nauki programowania

• możliwość łatwej dekompozycji kodu na moduły Wady:

• rozdzielenie danych i operacji na nich wykonywanych

• wykorzystanie jedynie standardowych typów danych

(3)

programowanie strukturalne, programowanie obiektowe Programowanie obiektowe:

• Object Orientated Programming (OOP)

• paradygmat programowania

• programy definiowane są za pomocą obiektów – elementów łączących stan (dane) i działanie (funkcje)

• podstawowym pojęciem jest klasa

• cechy: abstrakcja, enkapsulacja, polimorfizm, dziedziczenie

• istota OOP – w programie obiektowym nie posługujemy się obiektami typów fundamentalnych (int, char) lecz klasami, które odpowiadają pojęciom ze świata rzeczywistego.

Zalety:

• typ danych (w postaci klasy) dopasowany do rzeczywistego zagadnienia

• powiązanie danych i operacji na nich wykonywanych

• możliwość ograniczenia dostępu do danych Wady:

• nadmiarowość kodu związana z definiowaniem klas

• potrzeba przeprowadzenia szczegółowej analizy zagadnienia przed rozpoczęciem pisania kodu

(4)

OOP

OOP

Encapsulation

Inheritance

Polymorphism Classes

Friendship Data abstraction

(5)

Klasa Klasa to inaczej typ. Definicja klasy:

class Tmoj_typ {

// dane składowe // funkcje składowe };

Dobra praktyka nakazuje, aby nazwę własnego typu rozpoczynać od wielkiej litery T (jak Typ).

Dane składowe służą do przechowywania informacji.

Funkcje składowe służą do wykonywania operacji na danych składowych.

Przykład – klasa do obsługi książki:

(6)

Obiekt Klasa to projekt techniczny nowego typu. Mając zdefiniowany ten typ można tworzyć konkretne egzemplarze – obiekty danej klasy.

Dostęp do składników klasy:

• obiekt . składnik, np.:

• wskaźnik -> składnik, np.:

• referencja . składnik, np.:

Kropka . to operator odniesienia się do składnika obiektu znanego z nazwy lub referencji.

Strzałka -> to operator odniesienia się do składnika obiektu wskazywanego przez wskaźnik.

(7)

OOP

OOP

Encapsulation

Inheritance

Polymorphism Classes

Friendship Data abstraction

(8)

Kapsułowanie (ang. encapsulation)

Klasa stanowi połączenie danych i funkcji, które zamknięte są w niej jak w kapsule.

Kapsułowanie (ang. encapsulation) - inaczej hermetyzacja danych:

• dostęp do danych składowych klasy jest ograniczony za pomocą interfejsu, czyli obiekt udostępnia tylko pewien zbiór funkcji, które są widoczne z zewnątrz i mogą być wywoływane

• dostęp do pól obiektu powinien być realizowany poprzez odpowiednie metody(set(), get()) a nie przez bezpośredni dostęp do nich.

Dostęp do składników klasy regulowany jest poprzez etykiety dostępu [1]:

• private – dostęp tylko dla funkcji składowych danej klasy (a także dla funkcji zaprzyjaźnionych). Jeśli przed składnikami klasy nie wystąpi żadna etykieta, wtedy zakłada się przez domniemanie, że składniki mają dostęb private

• protected – dostęp jak w przypadku private i dodatkowo dla klas pochodnych (związane z pojęciem dziedziczenia klas)

• public – dostęp bez ograniczeń. Zwykle taki dostęp mają wybrane funkcje składowe, za których pomocą realizowany jest dostęp z zewnątrz do składników prywatnych klasy.

(9)

Kapsułowanie (ang. encapsulation) Dobra praktyka – kolejność umieszczania składników klasy w jej definicji (od góry):

• public – te składniki są najbardziej interesujące dla użytkownika klasy

• protected

• private – te składniki interesują jedynie programistę, a nie użytkownika

(10)

Funkcje składowe Funkcje zadeklarowane wewnątrz klasy nazywamy funkcjami składowymi (ang.

member functions). Wywołanie publicznej funkcji składowej obiektu:

obiekt.funkcja(argumenty) co oznacza: „wykonaj funkcjęfunkcja na rzecz obiektuobiekt”.

Przykłady:

Cechy funkcji składowych [1]:

• mają zasięg klasy (zwykłe funkcje mają zasięg pliku),

• mają dostęp do wszystkich składników klasy (private, public, protected)

• są to narzędzia, za pomocą których dokonujemy operacji na danych składowych

• są wspólne dla każdego obiektu klasy (mamy tylko jeden egzemplarz funkcji w pamięci, nawet jeśli mamy 1000 obiektów danej klasy)

(11)

Funkcje składowe Definiowanie funkcji składowych – możliwe są dwa sposoby:

• sposób pierwszy – definicja funkcji wewnątrz definicji klasy, przykład:

Cechy:

• jeśli definicja funkcji znajduje się w definicji klasy, wówczas funkcja jest funkcją inline (kompilator wstawa kod funkcji w miejscu jej wywołania w programie),

• przyjmuje się, że taki sposób definicji funkcji stosuje się, jeśli ciało funkcji składa się maksymalnie z 2 linii.

definicja funkcji w klasie

(12)

Funkcje składowe Definiowanie funkcji składowych – możliwe są dwa sposoby:

• sposób drugi – wewnątrz definicji klasy umieszczamy jedynie deklarację funkcji, natomiast definicję funkcji (jej ciało) piszemy poza deklaracją klasy:

Cechy:

• ponieważ definicja funkcji znajduje się poza klasą, dlatego musimy przekazać kompilatorowi informację, że dana funkcja jest funkcją składową danej klasy.

Robimy to za pomocą operatora zakresu :: , Tksiazka::pokaz_tytul() oznacza, że pokaz tytul jest funkcją składową klasy Tksiazka.

definicja funkcji poza klasą

(13)

Struktura programu obiektowego Zwykle w programie występuje wiele klas. Każdą klasę zapisujemy w dwóch plikach [1]:

• definicję klasy umieszczamy w pliku nagłówkowym Tnazwa_klasy.h

• definicję „większych” funkcji składowych umieszczamy w pliku źródłowym o nazwie Tnazwa_klasy.cpp

Tnazwa_klasy.h

Tnazwa_klasy.cpp

(14)

Konstruktor Konstruktor:

• specjalna funkcja składowa klasy wykorzystywana do inicjalizacji składników klasy,

• konstruktor nie tworzy obiektu, wkracza do pracy tuż po utworzeniu obiektu, aby go zainicjować wartościami,

• nie jest obowiązkowy – jeśli go pominiemy tworzony jest automatycznie konstruktor domyślny,

• nazywa się tak samo jak klasa,nie ma typu zwracanego!

konstruktor

zdefiniowany w klasie

(15)

Konstruktor

konstruktor

zdefiniowany poza definicją klasy

(16)

Konstruktor Konstruktor domyślny:

- konstruktor wykorzystywany, gdy klient nie przekaże, w sposób jawny, wartości inicjujących obiekt,

- kompilator tworzy konstruktor domyślny samodzielnie, jeśli programista nie zdefiniuje samodzielnie żadnego konstruktora,

- nie przyjmuje żadnych argumentów:

- lub, w szczególnym przypadku, wszystkie argumenty formalne muszą mieć wartość domyślną:

konstruktor domyślny

konstruktor domyślny

(17)

Konstruktor Konstruktor domyślny:

- jest wykorzystywany do inicjalizacji danych składowych klasy.

(18)

Destruktor Destruktor:

• jest przeciwieństwem konstruktora,

• jest to funkcja składowa wywoływana chwilę przed likwidacją obiektu danej klasy,

• używany do zwolnienia pamięci zajmowanej przez obiekt (jeśli w obiekcie istnieją elementy utworzone za pomocą operatora new to powinny one zostać usunięte w destruktorze za pomocą operatora delete),

• jest to metoda wywoływana automatycznie przed usunięciem obiektu, choć możemy ją także wywołać samodzielnie,

• nazywa się tak samo jak klasa, z tym że przed nazwą ma znak tyldy ~,

• nie ma określonego typu zwracanego.

destruktor zdefiniowany w klasie

(19)

Destruktor

destruktor zdefiniowany poza klasą

(20)

Składniki statyczne Każdy obiekt klasy posiada zaalokowaną pamięć dla zestawu składowych klasy.

Zestaw funkcji składowych jest współdzielony przez wszystkie obiekty danej klasy.

Składnik statyczny klasy:

- składnik wspólny dla wszystkich egzemplarzy obiektów klasy (np. Licznik posiadający informacje o liczbie elementów klasy – patrz wzorzec projektowy Singleton),

- jest to zmienna należąca do klasy, nie do obiektu, istnieje nawet jeśli nie zdefiniujemy żadnego obiektu danej klasy,

- składnik klasy jest statyczny, jeśli przed jego deklaracją w ciele klasy znajduje się słowo kluczowe static

Deklarację składnika statycznego umieszczamy w deklaracji klasy

Definicję składnika statycznego

umieszczamy w pliku z definicją klasy (najczęściej na samej górze)

(21)

Składniki statyczne Sposoby odwołania do publicznego składnika statycznego:

- nazwa klasy + operator zakresu:

nazwa_klasy::skladnik_statyczny

- jeśli istnieje już co najmniej jeden obiekt klasy, wówczas do składnika statycznego można odwołać się wykorzystując nazwę obiektu i operator .

obiekt.skladnik_statyczny

- jeśli zdefiniowany jest wskaźnik na obiekt klasy, wówczas odwołanie polega na podaniu nazwy wskaźnika i operatora ->

obiekt->skladnik_statyczny Przykłady zastosowania:

- zliczanie obiektów,

- prosta komunikacja pomiędzy obiektami, - oszczędność miejsca w pamięci,

Itd..

(22)

Funkcje statyczne Statyczna funkcja składowa klasy:

- może operować wyłącznie na statycznych składnikach klasy, - deklaracja funkcji musi być poprzedzona przedrostkiem static,

- wywołanie takiej funkcji polega na podaniu jej nazwy poprzedzonej nazwą klasy i operatorem zakresu:

nazwa_klasy::statyczna_funkcja_skladowa();

- ograniczenia: statyczne funkcje składowe wywoływane są na rzecz klasy, nie otrzymują niejawnie argumentu w postaci wskaźnika this.

(23)

Wskaźnik this Wskaźnik this:

- funkcje składowe klasy (poza statycznymi) wywoływane są na rzecz obiektu,

- informacja o tym, na którym obiekcie funkcja pracuje przesyłana jest do niej niejawnie za pomocą wskaźnika na ten obiekt (wskaźnik this),

Wskaźnik this jest

automatycznie wstawiany przez kompilator (nie trafia do kodu źródłowego!), możemy go także wstawiać

samodzielnie

(24)

Wskaźnik this Wskaźnik this:

- wskaźnik na obiekt: this

- odwołanie do obiektu wywołującego: *this

Przykład. Napisz klasę Person, ze składnikami prywatnymi imię, nazwisko i wiek.

Publiczne funkcje składowe powinny pozwolić na zwrócenie aktualnego imienia, nazwiska i wieku. Dodatkowo jedna z publicznych funkcji składowych powinna pozwolić na porównanie wieku dwóch osób i zwrócenie stałej referencji do osoby starszej.

Wynik:

main.cpp

(25)

Wskaźnik this

Numer linii Opis

2 Dołączenie definicji klasy Person zawartej w pliku nagłówkowym Person.h. Znaki cudzysłowu są wskazówką dla kompilatora, aby poszukiwanie pliku rozpoczął w bieżącym folderze, następnie w standardowych ścieżkach systemu.

5-6 Definicje obiektów Person, wywoływany jest konstrukor z trzema argumentami

7 Wywołanie metody older na rzecz obiektu ola, argumentem jest obiekt ala, zaś zwracany jest obiekt klasy Person

8 Wywołanie metody name() na rzecz obiektu zwróconego metodą older.

(26)

Wskaźnik this Person.h

(27)

Wskaźnik this

Numer linii Opis

7-21 Deklaracja klasy Person

9 Deklaracja konstruktora domyślnego (bezargumentowy) 10 Deklaracja konstruktora z trzema argumentami

8 Deklaracja destruktora

12-16 Deklaracja publicznych metod stanowiących interfejs klasy 18-20 Deklaracje prywatnych zmiennych składowych klasy

16 Deklaracja metody pozwalającej na porónwanie dwóch obiektów tej samej klasy – obiektu na rzecz którego wywołano metodę i obiektu wprowadzonego jako argument aktualny wywołania

(28)

Wskaźnik this Person.cpp

(29)

Wskaźnik this

Numer linii Opis

3-7 Definicja konstruktora domyslnego. W jego ciele realizowane jest przypisanie początkowych, domyślnych wartość zmiennym

składowym klasy

9-13 Definicja konstruktora z trzema argumentami. Ich wartość przypisywane są składnikom klasy

18, 22, 26, 30, 34

Nagłówki definicji zakończone słowem kluczowym const – takie funkcje składowe nie mogą modyfikować obiektu, na rzecz którego zostały wywołane. Jeśli obiekt wywołujacy został zdefiniowany ze słowem kluczowym const, wówczas na jego rzecz można wywołać tylko takie metody. Dobrą praktyką programistyczną jest

umieszczanie specyfikatora const prz każdej metodzie, która nie modyfikuje stanu obiektu, np. w tzw. getterach, czyli funkcjach, których zadaniem jest pobranie wartości składnika klasy.

34-40 Funkcja older porównuje dwa obiekty klasy Person. Odwołanie do składnika age klasy, na rzecz której dokonano wywołania funkcji realizowane jest po prostu poprzez podanie nazwy tego składnika, czyli age. Odwołanie do składnika age argumentu formalnego

(30)

Wskaźnik this

Numer linii Opis

34-40 Zadaniem funkcji jest zwrócenie referencji do obiektu o większej wartości składniek age. W przypadku argumentu formalnego jest to proste – zwracamy ten obiekt, czyli p. Jednak jak zwrócić obiekt na rzecz którego wywołano funkcję? Za pomocą wskaźnika this, który wskazuje na obiekt wywołany. Dzięki operatorowi dereferencji (czyli wysłuskania wartości) możemy zwrócić nie wskaźnik lecz sam obiekt (linia instrukcją return *this;). Zwrócony obiekt jest przypisywany do referencji do klasy Person. Przypomnienie: referencja to inna nazwa dla danego obiektu/zmiennej, przekazanie obiektu do funkcji przez referencję pozwala na jego modyfikację wewnątrz funkcji

(pracujemy wtedy na oryginalne obiektu).

(31)

Wskaźnik this Komenda do kompilacji programu (Linux + GCC):

Element Opis

g++ Wywołanie kompilatora GNU GCC

Person.cpp main.cpp

Lista plików z kodem źródłowym poddanym kompilacji -o Argument outfile, po nim podajemy nazwę wynikowego

programu

-Wall Włącza wszyskie wiadomości typu warning -Wextra Włącza dodatkowe wiadomości typu warning -Werror Traktuj ostrzeżenia jak błędy

-0level Optymalizacja kodu na poziomie level, np. -03 optymalizuje kod pod względem czasu wykonywania

-Inazwa_folderu Wskazuje ścieżkę do plików nagłówkowych

(32)

Funkcje składowe const Definiowanie obiektów stałych:

- posiadają przedrostek const

- obiekty stałe mogą mieć przypisaną wartość jedynie podczas definicji (inicjalizacja)

- na rzecz stałych obiektów można wywołać jedynie funkcje gwarantujące, że tych obiektów nie zmienią, czyli funkcje składowe const

- składnia deklaracji funkcji const:

typ_zwracanynazwa_funkcji(argumenty formalne) const;

(33)

Lista inicjalizacyjna konstruktora Jeśli obiekt zawiera składowe stałe (const), wówczas pojawia się pozorny problem z ich inicjalizacją. W trakcie wywołania konstruktora w pierwszej kolejności realizowane jest przydzielenie pamięci dla składowych klasy. Następnie rozpoczyna się wykonywanie ciała funkcji konstruktora. Na tym etapie składowe obiektu już istnieją, więc ustawienie wartości tych składowych nie jest operacją inicjalizacji, lecz przypisania. Tymczasem stałym składowym wartość można nadać jedynie drogą inicjalizacji (definicja z przypisaniem wartości).

Rozwiązaniem problemu jest lista inicjalizacyjna konstruktora o następujących cechach:

- może być wywołana jedynie w konstruktorach,

- jest wykonywana przed przekazaniem sterowania do ciała konstruktora,

City.h City.cpp

(34)

Przykład Zadanie 1. Tworzenie klasy Tschowek:

• zapisz definicję klasy Tschowek, posiadającej dwie prywatne zmienne składowe:

float wartosc i string nazwa.

• Utwórz konstruktor przypisujący im wartości początkowe iWart oraz iNazwa.

• Utwórz destruktor wypisujący komunikat „Destruktor”.

• Utwórz publiczne funkcje składowe wprowadz_wartosc(float iWart), wprowadz_nazwe(std::string iNazwa), wypisz_wartosc() i wypisz_Nazwe().

• Utwórz obiekty typu Tschowek, Tschowek* oraz Tschowek &.

• Przypisz im wartości początkowe i je wypisz z wykorzystaniem zdefiniowanych funkcji składowych.

(35)

Przykład Zadanie 2. Tworzenie klasy Tcalculator:

• zapisz definicję klasy Tcalculator w dwóch osobnych plikach (.cpp i .h),

• utwórz funkcje składowe:

show_menu() wyświetlającą menu,

ask_for_operator() pobierającą z klawiatury operator arytmetyczny i zapisującą go w zmiennej składowej operator

ask_for_arg1() – pobierającą wartość argumentu nr 1 i zapisującą ją w zmiennej składowej arg1

ask_for_arg2() – pobierającą wartość argumentu nr 2 i zapisującą ją w zmiennej składowej arg2

show_result() – wyświetlającą rezultat obliczeń (np. 2 + 3 = 5)

• pamiętaj o stworzeniu konstruktora i destruktora (jedynie w celu przetrenowania ich tworzenia, tutaj one nic nie będą robić)

• wszystkie dane składowe klasy mają być prywatne

(36)

Przykład Zadanie 3. Zmodyfikuj klasę Tcalculator:

• dodaj funkcję składową update() wywołującą funkcje show_menu(), ask_for_operator(), ask_for_arg1(), ask_for_arg2(), show_results()

• wywołuj tę funkcję w pętli, po każdym jej wykonaniu sprawdź, czy użytkownik nadal chce kontunuować

(37)

Literatura:

[1] Grębosz J., Opus Magnum C++, Helion, Gliwice, 2018

[2] Prata S., Język C++ Szkoła programowania, Helion, Gliwice, 2013 [3] Prata S., Język C Szkoła programowania, Helion, Gliwice, 2012

Cytaty

Powiązane dokumenty

[r]

Funkcja jest wygodnym sposobem zamknięcia pewnych obliczeń w „czarnej skrzynce”, której później można używać nie dbając o to, jak je zrealizowano.. Ogólnie definicja

[r]

Substancje gazowe oraz substancje występujące w postaci par lub aerozolu dostają się z powietrzem oddechowym do pęcherzyków płucnych, a następnie dyfundując przez błonę

Jak widać z wykresów, wydatki na dobra dwóch pierwszych grup dóbr są rosnącymi funkcjami dochodów, przy czym. wzrost ich jest

INFORMACJE O OBLICZANIU FUNKCJI PIERWOTNYCH 221 Mianownik jest iloczynem wielomianów pierwszego i drugiego stopnia.. Obliczymy całkę nieoznaczoną funkcji wymiernej z przykładu 9.4.18

Jako PRACĘ DOMOWĄ , bardzo proszę zrobić ćwiczenia znajdujące się w karcie pracy (PRESENT SIMPLE-ĆWICZENIA).. PRACĘ DOMOWĄ proszę przesłać na maila do PIĄTKU, 22.05.2020

Ludzie często zobowiązują się do czegoś, często też nie wywiązują się ze swoich zobowiązań i uważają, że nic takiego się nie stało.. Spróbujcie