170 likes | 289 Views
Programowanie obiektowe III rok EiT. dr inż. Jerzy Kotowski Wykład VIII. Program wykładu. Źródła podejścia obiektowego Podstawy metody PRINCE - PR ojects I n C ontrolled E nvironment Podstawy metody LFA - L ogical F ramework A pproach , składanie wniosków o grant
E N D
Programowanie obiektoweIII rok EiT dr inż. Jerzy Kotowski Wykład VIII
Program wykładu • Źródła podejścia obiektowego • Podstawy metody PRINCE -PRojects In Controlled Environment • Podstawy metody LFA -Logical Framework Approach, składanie wniosków o grant • Język C++ - gadżety języka, polimorfizm, klasy, dziedziczenie • Gadżety języka C++ c.d., klasy • Przykład problemu • Podstawy języka JAVA • Klasówka
Literatura • C++ for C programmers, Ira Pohl, The Benjamin/Cummings Publishing Company, Inc. • Symfonia C++, Jerzy Grębosz, Oficyna Kallimach, Kraków 1999
Operatory new i delete Visual Studio: test0.sln • new - operator jednoargumentowy. Bardziej użyteczny od malloc i calloc. Operator służy do sterowania pamięcią o nazwie freestore. • Do niszczenia obiektów założonych przy pomocy operatora new służy operator delete. Przy pomocy operatora delete można zniszczyć wyłącznie obiekt założony przy pomocy operatora new. • Oznacza to w szczególności, że twór założony przy pomocy funkcji malloc musi być niszczony przy pomocy funkcji free. • Składnia operatora new:new type-namenew type-name initializer • W każdym z powyższych przypadków operator new rezerwuje odpowiednią ilość pamięci i zwraca adres typu void* do zarezerwowanego obszaru. • Składnia operatora delete:deleteexpressiondelete [] expression • Operator delete nic nie zwraca, w takim znaczeniu, że zwraca void. • Przykład: dynamiczna alokacja tablicy dwuwymiarowej. • Program tablica1.cpp
Fragment programu void main(void) // Dynamiczna alokacja tablicy dwuwymiarowej { int** data; int sz1,sz2; cout << "\nEnter two sizes: "; cin >> sz1 >> sz2; // Oddzielamy Enterem lub dowolną liczbą spacji data=new int* [sz1];// alokacja tablicy wskaźników do liczb int for(int i=0;i<sz1;i++) data[i]=new int[sz2]; cout << "\nEnter " << sz1 << " by " << sz2 << " ints:\n"; int j; // Kompilator nie pozwolił na deklarację w wewnętrznej pętli for(i=0;i<sz1;i++) for(j=0;j<sz2;j++) cin >> data[i][j]; cout << "\nResult:\n\n"; for(i=0;i<sz1;cout << "\n",i++) for(j=0;j<sz2;j++) cout << data[i][j] << "\t"; getch(); }
Ciekawe punkty programu tablica1.cpp • Przy wprowadzaniu grupy danych za pomocą operatora cin kolejne pozycje oddzielamy dowolną liczbą spacji lub klawiszem Enter. • Adres data ustawiamy na wartość zwracaną przez operator new: data=new int* [sz1]; - rozmiar zajętego obszaru jest zatem zależny od modelu pamięci i jest równy sz1* rozmiar_jednego wskaźnika. • Operator new można oczywiście wykorzystywać w składni:int *i; i = new int; • Wszystkie elementy tablicy data (czyli wskaźniki) ustawiamy na wskazania do obszarów, w których zapamiętywane będą kolejne wiersze tablicy: data[i]=new int[sz2]; • Wykorzystanie jak przy klasycznej tablicy: cin >> data[i][j];cout << data[i][j];data[1][2]=3; • Operator przecinkowy: for(i=0;i<sz1;cout << "\n",i++)
Unie anonimowe ..\..\Visual Studio Projects\test0\test0.sln • Unia anonimowa to taka, która jest deklarowana bez etykiety (tag name). • C++ pozwala na bezpośredni dostęp do składowych takiej unii. W związku z tym nazwy pól powinny różnić się od nazw innych zmiennych znajdujących się w tym samym horyzoncie zdarzeń (obszarze ważności nazwy). • Program unia anonimowa.cpp staticunion { int i; char c[8]; double w; };//kompilator domagal sie typu static void main(void) { w=3.14; cout << " i: " << i << endl; i=49; cout << "c[0]: " << c[0] << endl; i++; cout << "c[0]: " << c[0] << endl; getch(); }
Klasy - wprowadzenie • W języku C++ struktura może mieć funkcje składowe == metody składowe == member functions. Struktura może mieć również pola opisane jako private. Konsekewncją jest koncepcja klasy - class, która jest strukturą z domniemaną widzialnością private. • Modyfikatory widzialności (dostępu):publicprivateprotected • Private parts są ukryte przed client code. • Podejście projektowe oparte na idei OOP sprowadza się do projektowania odpowiednich ADT (Abstract Data Type). • Dobrze zaprojektowany ADT oddaje nie tylko kluczowe własności modelowanego procesu ale może być często z powodzeniem stosowany w innym kodzie źródłowym. • Struktura (klasa) ma komponenty o nazwie members. • Etykieta struktury jest typem (nazwą typu obiektowego). • Structure member operator daje dostęp do poszczególnych składników struktury. Składnia: structure_variable.member_name • member_name musi być unikalne w obrębie danej struktury. Nazwy pól różnych struktur mogą być identyczne.
Zakres ważności nazwy obiektu a jego czas życia • Czas życia obiektu to okres od momentu gdy zostanie mu przydzielone miejsce w pamięci (definicja, C++) do momentu, gdy to miejsce zostaje zwolnione. • Zakres ważności nazwy obiektu to ta część programu, w której ta nazwa znana jest kompilatorowi. • Przykład: void Ala(void) { static float x; … } • Zakresy ważności: • Lokalny – świadomie ograniczamy go do kilku linijek programu (blok, wnętrze definicji funkcji). • Blok funkcji – zakres ważności ograniczony do bloku funkcji ma etykieta. • Obszar pliku – jeżeli program składa się z kilku plików i w jednym z nich, na zewnątrz jakiegokolwiek bloku (także bloku funkcji) zadeklarujemy jakąś nazwę, to mówimy wówczas, że taka nazwa jest globalna. Ma ona zakres ważności pliku i jest znana od miejsca, gdzie znalazła się deklaracja do końca pliku. Nazwa globalna nie jest automatycznie znana w innych plikach. • Obszar klasy – nazwa użyta do zadeklarowania jakiejś składowej klasy jest znana przez wszystkie inne składowe tej klasy.
Stack - stos • Idea przykładu: przekształcamy definicję stosu z postaci strukturalnej na postać obiektową. • Stos jest jedną z bardziej użytecznych struktur danych. • Stos jest strukturą, która pozwala na składowanie i kasowanie tylko jednego elementu znajdującego się na szczycie stosu. • System obsługi stosu nosi nazwę LIFO. • Typowe operacje, które można dokonywać na stosie to push, pop, top, empty oraz full: • Operator push składa wartość na stosie • Operator pop pobiera wartość ze stosu • Operator top zwraca wartość znajdującą się na szczycie stosu • Operator empty sprawdza czy stos jest pusty • Operator full sprawdza, czy stos jest pełny. • Stos jest typowym ADT. • W postaci strukturalnej stos jest organizowany na obszarze pamięci o sztywnym rozmiarze. Szczyt stosu wskazuje składnik (member) o nazwie top. Poszczególne operacje dokonywane na stosie są w programie źródłowym zdefiniowane jako funkcje, których jednym z argumentów jest wskaźnik do obiektu typu stack.
Stos - wersja strukturalna • Struktura stack ma dwa pola typu public. Pole s ma rozmiar max_len deklarowany jako const int. • Na początku programu jest również deklarowany nowy typ Boolean przy pomocy słowa kluczowego enum. Stała False jest inicjalizowana na 0 a stała Truena 1. • Funkcja resetjest wykorzystywana do inicjalizacji. Ustawia wskaźnik stosu na 0. Argumentem funkcji jest adres do struktury typu stack. • Funkcja push ma dwa argumenty: co oraz gdzie. Zakłada się, że stos nie jest pełny. Wpierw zwiększamy wskaźnik stosu. Następnie podstawiamy pod ten adres pierwszy argument funkcji. • W funkcji pop jest zmniejszenie wskaźnika stosu po pobraniu wartości. constint max_len=1000; enum Boolean {False,True}; struct stack { char s[max_len]; int top; }; void reset(stack* stk) { stk->top=0; } void push(char c,stack* stk) { stk->top++; stk->s[stk->top]=c; } char pop(stack* stk) { return(stk->s[stk->top--]); }
Stos - wersja strukturalna, c.d. • W funkcji top nie ma zmniejszenia wskaźnika stosu po pobraniu wartości. • Funkcje empty oraz full zwracają wartość typu Boolean. Arrgumentami są adresy do obiektu typu stack. char top(stack* stk) { return(stk->s[stk->top]); } Boolean empty(stack* stk) { return((Boolean)(stk->top==0)); }//dodano rzutowanie na typ Boolean Boolean full(stack* stk) { return((Boolean)(stk->top==max_len-1)); }// dodano rzutowanie na typ Boolean
Stos - client code..\..\Visual Studio Projects\test0\test0.sln • W segmencie main tekst str jest zrzucany na stos sa następnie ściągany ze stosu i drukowany na ekranie. Drukowanie w odwrotnej kolejności. • Obie pętle wykorzystują konstrukcjęwhile. • Wszystkie funkcje do obsługi stosu wywoływane w segmencie main jako jeden ze swoich argumentów adres do stosu &s • Programstos strukturalny.cpp. void main(void) { stack s; staticchar str[40]="Elektronika i Telekomunikacja"; int i=0; cout << str << endl; reset(&s); while((str[i])&&(!full(&s))) push(str[i++],&s); while(!empty(&s)) cout << pop(&s); cout << endl; getch(); }
Stos – wersja obiektowa, opis • W wersji obiektowej funkcje do obsługi stosu stają się funkcjami składowymi klasy. • Member functions są traktowane jako składowe struktury (klasy). • Dostęp do nich jest identyczny jak do wszystkich innych składowych. • Do dotychczasowych funkcji do obsługi stosu zostanie dodanych kilka nowych. • Przy okazji zostanie zaprezentowany i wykorzystany mechanizm przeciążania funkcji. • Pewne funkcje będą definiowane jako inline, definicje innych znajdą się poza klasą a w samej definicji klasy znajdą się wyłącznie ich deklaracje prototypowe.
Stos - wersja obiektowa • Member functions mają bezpośredni dostęp przez member_name do wszystkich składowych swojej klasy - nawet do składowych ukrytych. • Funkcja składowa top zmieniła nazwę na top_of aby nie było konfliktu nazw (pole top). • Nazwy pop i top są przeciążone. constint max_len=1000; enum Boolean {False,True}; class stack { char s[max_len]; int top; public: void reset() { top = 0; } // definition void push(char c); // function prototype char pop() { return (s[top--]);} char pop(int n); // overloading, prototype char top_of() { return (s[top]); } Boolean empty() { return ((Boolean)(top == 0)); } Boolean empty(int n); // overloading, prototype Boolean full() { return ((Boolean)(top == max_len - 1 )); } };
Stos - wersja obiektowa, funkcje składowe • Pełna nazwa funkcji definiowanej poza klasą ma postać:nazwa_klasy::nazwa_funkcji • void stack::push(char c) - definicja składowej poza klasą • Przeciążona funkcja pop(int n) zwraca n-ty element ze stosu. • Przeciążona funkcja empty(int n) zwraca True, jeżeli na stosie jest mniej niż n elementów void stack::push(char c) { top++; s[top] = c; }// definicja składowej poza klasą char stack::pop(int n) { while(n-->1) top--; return(s[top--]); } Boolean stack::empty(int n) { return ((Boolean)(top-n+1 <= 0)); }// True, jeżeli jest mniej niż n elementów
Stos - client code..\..\Visual Studio Projects\test0\test0.sln • W segmencie main tekst str jest zrzucany na stos sa następnie ściągany ze stosu i drukowany na ekranie. Drukujemy co drugi element w odwrotnej kolejności. • Funkcje składowe są czytelniejsze - nie mają argumentów. • Program stos obiektowy.cpp void main(void) { stack s; char str[50] = {"Instytut Informatyki, Automatyki i Robotyki"}; int i = 0; cout << str << endl; s.reset(); while (str[i]) if (!s.full()) s.push(str[i++]); while(!s.empty(2)) // print the rewerse cout << s.pop(2); // drukujemy od końca co drugi element cout << endl; getch(); }