Programowanie obiektowe

Slides:



Advertisements
Podobne prezentacje
Projektowanie Aplikacji Komputerowych
Advertisements

C++ wykład 2 ( ) Klasy i obiekty.
C++ wykład 4 ( ) Przeciążanie operatorów.
Programowanie obiektowe
Programowanie obiektowe PO PO - LAB 2 Wojciech Pieprzyca.
Klasa listy jednokierunkowej Przekazywanie parametrów do funkcji
Programowanie obiektowe
Programowanie obiektowe PO PO - LAB 4 Wojciech Pieprzyca.
1 Dzisiejszy wykład Wzorce funkcji Wzorce klas. 2 Wzorce Często pojawia się konieczność pisania podobnych funkcji lub klas operujących na argumentach.
Programowanie obiektowe
1 Dzisiejszy wykład Klasa string wersja prosta wersja ze zliczaniem odwołań Wyjątki Specyfikator volatile.
1 Dzisiejszy wykład Wzorce funkcji Wzorce klas Tablica asocjacyjna Składowe statyczne.
Programowanie obiektowe PO PO - LAB 3 Wojciech Pieprzyca.
Klasy i obiekty.
Dziedziczenie. Po co nam dziedziczenie? class osoba { char * imie, char * imie, * nazwisko; * nazwisko;public: void wypisz_imie(); void wypisz_imie();
Bezpieczeństwo wyjątków w C++: OpenGL
Programowanie w środowisku sieciowym
Programowanie Obiektowe w Javie (c.d.)
Programowanie obiektowe w Javie
Szablony (wzorce) Przykład 1: Szablon klasy -
Licznik template<class Count_Type> class Count { public:
OOP - programowanie zorientowane obiektowo w VB.NET
25/08/ Języki programowania 1 Piotr Górczyński Obiekty i zdarzenia.
PROGRAMOWANIE OBIEKTOWE
C++ wykład 5 ( ) Dziedziczenie.
C++ wykład 6 ( ) Polimorfizm.
C++ wykład 2 ( ) Klasy i obiekty.
Zasady zaliczenia Warunki uzyskania zaliczenia:
Czytanie, pisanie i rysowanie – cd.. Jeszcze jeden strumyk PrintStream działa jak PrintWriter, ale: Używa domyślnego (systemowego) kodowania Nie wyrzuca.
Projektowanie i programowanie obiektowe II - Wykład II
Klasy w C++. Deklaracja klasy class NazwaTwojejKlasy { //w tym miejscu piszemy definicje typów, //zmienne i funkcje jakie mają należeć do klasy. }; //tutaj.
Programowanie obiektowe III rok EiT
Programowanie obiektowe III rok EiT
Java 3 MPDI Programowanie obiektowe W7. import java.io.*; public class X { // kontrukcja throws – określenie jakie wyjątki może dana metoda // sygnalizować
Podstawy programowania II
Podstawy Programowania
Programowanie obiektowe III rok EiT dr inż. Jerzy Kotowski Wykład IX.
Programowanie obiektowe III rok EiT
Programowanie obiektowe
Programowanie obiektowe Wykład 3 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21 Dariusz Wardowski.
Programowanie obiektowe Wykład 7 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/20 Dariusz Wardowski.
Programowanie obiektowe Wykład 6 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14 Dariusz Wardowski.
Programowanie obiektowe 2013/2014
Programowanie obiektowe 2013/2014
Prasek Aneta, Skiba Katarzyna. Funkcje stałe const to takie funkcje, które nie mogą modyfikować stanu obiektu. Oznacza to, że funkcja stała nie może zmieniać.
Kurs języka C++ – wykład 9 ( )
Programowanie w języku C++
Dobry kod OO Jeżeli zapytamy statystycznego programistę z czym kojarzy mu się dobry kod OO to najprawdopodobniej będzie mówił o wzorcach projektowych.
Treści multimedialne - kodowanie, przetwarzanie, prezentacja Odtwarzanie treści multimedialnych Andrzej Majkowski informatyka +
Programowanie strukturalne i obiektowe C++
Programowanie strukturalne i obiektowe C++ Przeładowanie operatorów Robert Nowak.
Kurs języka C++ – wykład 4 ( )
K URS JĘZYKA C++ – WYKŁAD 6 ( ) Polimorfizm.
Programowanie obiektowe Wykład 9 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/15 Dariusz Wardowski.
Paradygmat programowania obiektowego, klasa, obiekt
This, friend, operatory. this dostępny w każdej niestatycznej metodzie dostępny w każdej niestatycznej metodzie jest to wskaźnik do obiektu na rzecz którego.
Programowanie obiektowe
Wykład 4 Klasa Vec, której konstruktory alokują pamięć dla obiektów 1.Przykład definicji klasy Vec 2.Definicje konstruktorów i destruktora 3.Definicja.
Partnerstwo dla Przyszłości 1 Lekcja 27 Klasy i obiekty.
Wykład 2 Klasa Zesp i jej hermetyzacja 1.Przykład definicji klasy Zesp 2.Zmiana definicji klasy 3.Zmienne i funkcje statyczne PO2-1 / 28.
Wykład 5 Klasa Vec i jej operatory 1.Kategorie operatorów 2.Operatory ogólne - przykłady 3.Operatory specjalne [ ], ( ) oraz –> 4.Operatory new i delete.
Wykład 8 Polimorfizm 1.Funkcje polimorficzne 2.Czyste funkcje wirtualne i klasy abstrakcyjne PO8-1 / 38.
Partnerstwo dla Przyszłości 1 Lekcja 28 Dziedziczenie i rodzaje dziedziczenia.
Programowanie Obiektowe – Wykład 6
Programowanie Obiektowe – Wykład 9
Programowanie Obiektowe – Wykład 2
Podstawy programowania
BYDGOSKI FESTIWAL NAUKI
Programowanie w Javie 1 Dr Robert Kowalczyk
Zapis prezentacji:

Programowanie obiektowe Polimorfizm - przykłady

Hierarchia klas trójkątów Tekstowy system okienkowy Dzisiejszy wykład Hierarchia klas trójkątów Tekstowy system okienkowy Hierarchia klas wyjątków

Przykład - hierarchia klas trójkątów shape trojkat prostokatny rownoramienny

Przykład - hierarchia klas trójkątów class point { private: double x, y; public: point(double kx, double ky) : x(kx), y(ky){} friend ostream& operator<<(ostream &o, const point& p); }; ostream& operator<<(ostream &o, const point& p) o << "(" << p.x <<"," << p.y << ")"; return o; }

Przykład - hierarchia klas trójkątów class point { private: double x, y; public: point(double kx, double ky) : y(ky), x(kx){} friend ostream& operator<<(ostream &o, const point& p); }; ostream& operator<<(ostream &o, const point& p) o << "(" << p.x <<"," << p.y << ")"; return o; } Programista dostarczył własny konstruktor, więc kompilator nie będzie generował konstruktora domyślnego. Ciało funkcji jest puste, wszystkie zmienne prywatne klasy są inicjalizowane za pomocą listy inicjalizacyjnej. Kolejność inicjalizacji nie zależy od kolejności zmiennych na liście inicjalizacyjnej lecz od kolejności deklaracji w klasie.

Przykład - hierarchia klas trójkątów class point { private: double x, y; public: point(double kx, double ky) : y(ky), x(kx){} friend ostream& operator<<(ostream &o, const point& p); }; ostream& operator<<(ostream &o, const point& p) o << "(" << p.x <<"," << p.y << ")"; return o; } Operator przekierowania do strumienia. Implementowany jako funkcja zaprzyjaźniona ponieważ nie mamy dostępu do kodu klasy ostream z biblioteki standardowej a chcemy zachować standardową składnię np.: cout << p << endl i dodatkowo mieć dostęp do składowych prywatnych klasy point.

Przykład - hierarchia klas trójkątów class shape { public: virtual void show(void) = 0 cout << "Ksztalt ... ??? " << endl; } };

Przykład - hierarchia klas trójkątów class shape { public: virtual void show(void) = 0; }; Czysto wirtualna funkcja, sprawiająca że klasa shape jest klasą abstrakcyjną. Nie jest możliwe utworzenie obiektu klasy abstrakcyjnej. Wykorzystywana jako interfejs do hierarchii klas.

Przykład - hierarchia klas trójkątów class trojkat : public shape { protected: point a, b, c; public: trojkat(point ka, point kb, point kc): a(ka),b(kb),c(kc){} void show(void) cout << "Trojkat DOWOLNY" << a <<" "<< b <<" "<< c << endl; } }; Konstruktor klasy trojkat. Inicjalizuje składowe chronione klasy.

Przykład - hierarchia klas trójkątów class trojkat : public shape { protected: point a, b, c; public: trojkat(point ka, point kb, point kc): a(ka),b(kb),c(kc){} void show(void) cout << "Trojkat DOWOLNY" << a <<" "<< b <<" "<< c << endl; } }; Redefinicja wirtualnej funkcji show z abstrakcyjnej klasy bazowej shape. Funkcja nadal pozostaje funkcją wirtualną, mimo że słowo kluczowe nie jest powtórzone. Wszystkie funkcje czysto wirtualne z klasy bazowej zostały zdefiniowane, wiec klasa nie jest już klasą abstrakcyjną. Parametry funkcji redefiniowanej muszą być takie same jak parametry funkcji zadeklarowanej w klasie bazowej.

Przykład - hierarchia klas trójkątów class prost : public trojkat { public: prost(point ka, point kb, point kc): trojkat(ka, kb, kc){} void show(void) cout << "Trojkat PROSTOKATNY " <<a<<" "<<b<<" "<<c<< endl; } }; Konstruktor klasy prost. Konstruktor klasy pochodnej nie ma dostępu do składowych klasy bazowej, wiec inicjalizacja zmiennych realizowana jest za pomocą wywołania konstruktora klasy bazowej.

Przykład - hierarchia klas trójkątów class prost : public trojkat { public: prost(point ka, point kb, point kc): trojkat(ka, kb, kc){} void show(void) cout << "Trojkat PROSTOKATNY " <<a<<" "<<b<<" "<<c<< endl; } }; Redefinicja wirtualnej funkcji show.

Przykład - hierarchia klas trójkątów class rownoboczny : public trojkat { public: rownoboczny(point ka, point kb, point kc): trojkat(ka,kb, kc){} void show(void) cout << "Trojkat ROWNOBOCZNY " <<a<<" "<<b<<" "<<c<< endl; } };

Przykład - hierarchia klas trójkątów int main(int argc, char* argv[]) { shape* tab[3]; trojkat t(point(0, 0), point(5, 5), point(10, 10)); prost p(point(10, 10), point(5, 5), point(10, 10)); rownoboczny r(point(3, 3), point(15, 15), point(8, 8)); tab[0] = &t; tab[1] = &p; tab[2] = &r; for (int i = 0; i < sizeof(tab)/sizeof(tab[0]); i++){ tab[i] -> show(); } return 0;

Przykład - hierarchia klas trójkątów Zastosowanie abstrakcyjnej klasy bazowej umożliwiło utworzenie interfejsu dla hierarchii klas Zastosowanie funkcji wirtualnych umożliwiło wywołanie funkcji wirtualnej z właściwej klasy na podstawie wskaźnika do klasy bazowej. Trojkat DOWOLNY (0,0) (5,5) (10,10) Trojkat PROSTOKATNY (10,10) (5,5) (10,10) Trojkat ROWNOBOCZNY (3,3) (15,15) (8,8)

Przykład - tekstowy system okienkowy System okienek pracujący w trybie tekstowym w oparciu o bibliotekę ncurses Biblioteka ncurses użyta jest w celu umożliwienia sterowania pozycją kursora w sposób przenośny W programie użyto małego podzbioru funkcji oferowanych przez ncurses //screen.h void init_screen (); void done_screen (); void gotoyx (int y, int x); int ngetch (); void getscreensize (int &y, int &x); //ncurses.h int printw(char *fmt [, arg] ...); int refresh(void);

Przykład - tekstowy system okienkowy W pliku cpoint.h zdefiniowano klasy pomocnicze: CPoint i CRect struct CPoint { int x; int y; CPoint(int _x=0, int _y=0): x(_x), y(_y) {}; CPoint& operator+=(const CPoint& delta) x+=delta.x; y+=delta.y; return *this; }; struct CRect CPoint topleft; CPoint size; CRect(CPoint t1=CPoint(), CPoint s=CPoint()): topleft(t1), size(s) {};

Przykład - tekstowy system okienkowy Struktura klas w programie CView CGroup CWindow CDesktop CFramedWindow CInputLine

Przykład - tekstowy system okienkowy CView - obiekt widoczny na ekranie Pole geom opisujące wymiary i położenie widoku Funkcja paint umożliwiająca wydrukowanie zawartości okna Funkcja handleEvent obsługująca zdarzenia Wirtualny destruktor class CView { protected: CRect geom; public: CView (CRect g):geom (g) }; virtual void paint () = 0; virtual bool handleEvent (int key) = 0; virtual void move (const CPoint & delta) geom.topleft += delta; virtual ~CView () {};

Przykład - tekstowy system okienkowy Środowisko sterowane zdarzeniami Reaguje jedynie na polecenia zewnętrzne wciśnięcie klawisza polecenie narysowania wnętrza okna Żaden z obiektów nie robi nic "z własnej inicjatywy"

Przykład - tekstowy system okienkowy CWindow - ruchome okno class CWindow:public CView { protected: char c; public: CWindow (CRect r, char _c = '*'):CView (r), c (_c) {}; void paint () for (int i = geom.topleft.y; i < geom.topleft.y + geom.size.y; i++) gotoyx (i, geom.topleft.x); for (int j = 0; j < geom.size.x; j++) printw ("%c", c); }; bool handleEvent (int key) switch (key) case KEY_UP: move (CPoint (0, -1)); return true; case KEY_DOWN: move (CPoint (0, 1)); case KEY_RIGHT: move (CPoint (1, 0)); case KEY_LEFT: move (CPoint (-1, 0)); return false;

Przykład - tekstowy system okienkowy CFramedWindow - okno z ramką class CFramedWindow: public CWindow { public: CFramedWindow (CRect r, char _c = '\''):CWindow (r, _c) {}; void paint () for (int i = geom.topleft.y; i < geom.topleft.y + geom.size.y; i++) gotoyx (i, geom.topleft.x); if ((i == geom.topleft.y)||(i == geom.topleft.y + geom.size.y - 1)) printw ("+"); for (int j = 1; j < geom.size.x - 1; j++) printw ("-"); } else printw ("|"); printw ("%c", c); };

Przykład - tekstowy system okienkowy CInputLine - okienko do wprowadzania tekstu class CInputLine:public CFramedWindow { string text; public: CInputLine (CRect r, char _c = ','):CFramedWindow (r, _c) {}; void paint () CFramedWindow::paint (); gotoyx (geom.topleft.y + 1, geom.topleft.x + 1); for (unsigned j = 1, i = 0; (j + 1 < (unsigned) geom.size.x) && (i < text.length ()); j++, i++) printw ("%c", text[i]); }; bool handleEvent (int c) if (CFramedWindow::handleEvent (c)) return true; if ((c == KEY_DC) || (c == KEY_BACKSPACE)) if (text.length () > 0) text.erase (text.length () - 1); } if ((c > 255) || (c < 0)) return false; if (!isalnum (c) && (c != ' ')) text.push_back (c);

Przykład - tekstowy system okienkowy CGroup - grupa obiektów class CGroup:public CView { list < CView * >children; public: CGroup (CRect g):CView (g) {}; void paint () for (list < CView * >::iterator i = children.begin (); i != children.end (); i++) (*i)->paint (); }; //...

Przykład - tekstowy system okienkowy CGroup - grupa obiektów (cd.) class CGroup:public CView { list < CView * >children; public: CGroup (CRect g):CView (g) {}; void paint (); bool handleEvent (int key) if (!children.empty () && children.back ()->handleEvent (key)) return true; if (key == '\t') if (!children.empty ()) children.push_front (children.back ()); children.pop_back (); }; } return false; //...

Przykład - tekstowy system okienkowy CGroup - grupa obiektów (cd.) class CGroup:public CView { list < CView * >children; public: CGroup (CRect g):CView (g) {}; void paint (); bool handleEvent (int key); void insert (CView * v) children.push_back (v); }; ~CGroup () for (list < CView * >::iterator i = children.begin (); i != children.end (); i++) delete (*i);

Przykład - tekstowy system okienkowy CDesktop - cały ekran class CDesktop:public CGroup { public: CDesktop ():CGroup (CRect ()) int y, x; init_screen (); getscreensize (y, x); geom.size.x = x; geom.size.y = y; }; ~CDesktop () done_screen (); void paint() for (int i = geom.topleft.y; i < geom.topleft.y + geom.size.y; i++) gotoyx (i, geom.topleft.x); for (int j = 0; j < geom.size.x; j++) printw ("."); CGroup::paint(); } int getEvent () { return ngetch (); }; void run () int c; paint (); refresh (); while (1) c = getEvent (); if (c == 27) break; if (handleEvent (c))

Przykład - tekstowy system okienkowy Funkcja main int main () { CDesktop d; d.insert (new CInputLine (CRect (CPoint (5, 7), CPoint (15, 15)))); d.insert (new CWindow (CRect (CPoint (2, 3), CPoint (20, 10)), '#')); d.run (); return 0; };

Zarządzanie zasobami Kiedy funkcja alokuje zasób - otwiera plik, zamyka semafor, blokuje dostęp, alokuje pamięć - zwykle dla późniejszej poprawnej pracy systemu ważne jest poprawne zwolnienie zasobu. Często funkcja, w której przydzielono zasób, jest również odpowiedzialna za jego zwolnienie Powyższe rozwiązanie nie zadziała w przypadku wcześniejszego powrotu z funkcji, np. podczas wystąpienia wyjątku. Poniżej pierwsze podejście do rozwiązania problemu void use_file(const char* fn) { FILE* f = fopen(fn,"w") ; // use f fclose(f) ; } void use_file(const char* fn) { FILE* f = fopen(fn,"w") ; try { // use f } catch (...) { fclose(f) ; throw;

Zarządzanie zasobami Rozwiązanie na poprzedniej stronie jest rozwlekłe i nużące, a więc podatne na błędy. Na szczęście istnieje rozwiązanie bardziej eleganckie. Problem w ogólnej postaci wygląda następująco: Zwykle wymagane jest zwalnianie zasobów w kolejności odwrotnej do ich przydzielania. Przypomina to zachowanie obiektów lokalnych, tworzonych przez konstruktory i kasowanych przez destruktory. void acquire() { // acquire resource 1 // ... // acquire resource n // use resources // release resource n // release resource 1 }

Technika zdobywanie zasobów jest inicjalizacją Zdefiniujmy klasę File_ptr, która zachowuje się jak FILE*: Program skraca się znacząco class File_ptr { FILE* p; public: File_ptr(const char* n, const char* a) { p = fopen(n,a) ; } File_ptr(FILE* pp) { p = pp; } ~File_ptr() { fclose(p) ; } operator FILE*() { return p; } }; void use_file(const char* fn) { File_ptr f(fn,"r") ; // use f }

Zdobywanie zasobów i konstruktory Podobną technikę można zastosować w konstruktorach Często alokowanym w podobny sposób zasobem jest pamięć Zwykle lepiej zastosować standardowy wzorzec vector class X { File_ptr aa; Lock_ptr bb; public: X(const char* x, const char* y) : aa(x,"rw") , // acquire ‘x’ bb(y) // acquire ‘y’ {} // ... }; class Y { int* p; void init() ; public: Y(int s) {p = new int[s]; init() ; } ~Y() { delete[] p; } // ... }; class Z { vector<int> p; void init() ; public: Z(int s) : p(s) { init() ; } // ... };

Wzorzec auto_ptr Wzorzec auto_ptr jest wzorcem z biblioteki standardowej implementującym technikę "zdobywanie zasobów jest inicjalizacją" dla obiektów alokowanych dynamicznie void f(Point p1,Point p2, auto_ptr<Circle> pc, Shape* pb) // remember to delete pb on exit { auto_ptr<Shape> p(new Rectangle(p1,p2)) ; // p points to a rectangle auto_ptr<Shape> pbox(pb) ; p->rotate(45) ; // use auto_ptr<Shape> exactly as a Shape* // ... if (in_a_mess) throw Mess() ; }

Wzorzec auto_ptr auto_ptr jest zadeklarowany w pliku nagłówkowym <memory> template<class X> class std::auto_ptr { template <class Y> struct auto_ptr_ref{ /* ... */ }; // helper class X* ptr; public: typedef X element_type; explicit auto_ptr(X* p =0) throw() { ptr=p; } auto_ptr(auto_ptr& a) throw() { ptr=a.release(); } // note: not const auto_ptr& template<class Y> auto_ptr(auto_ptr<Y>& a) throw() { ptr=a.release(); } auto_ptr& operator=(auto_ptr& a) throw() { reset(a.release()); return *this;} template<class Y> auto_ptr& operator=(auto_ptr<Y>& a) throw() { reset(a.release()); return *this;} ~auto_ptr() throw() { delete ptr; } X& operator*() const throw() { return *ptr; } X* operator->() const throw() { return ptr; } X* get() const throw() { return ptr; } // extract pointer X* release() throw() { X* t = ptr; ptr=0; return t; } // relinquish ownership void reset(X* p =0) throw() { if (p!=ptr) { delete ptr; ptr=p; } } auto_ptr(auto_ptr_ref<X>) throw() ; // copy from auto_ptr_ref template<class Y> operator auto_ptr_ref<Y>() throw() ; // copy from auto_ptr_ref template<class Y> operator auto_ptr<Y>() throw() ; // destructive copy from auto_ptr };

Wzorzec auto_ptr konstruktor wzorca i przypisanie wzorca umożliwiają niejawną konwersję tak samo jak dla wskaźników auto_ptr ze względu na destrukcyjną semantykę kopiowania nie nadaje się do przechowywania w standardowych kolekcjach void g(Circle* pc) { auto_ptr<Circle> p2 = pc; // now p2 is responsible for deletion auto_ptr<Circle> p3 = p2; // now p3 is responsible for deletion (and p2 isn’t) p2->m = 7; // programmer error: p2.get()==0 Shape* ps = p3.get() ; // extract the pointer from an auto_ptr auto_ptr<Shape> aps = p3; // transfer of ownership and convert type auto_ptr<Circle> p4 = pc; // programmer error: now p4 is also responsible for deletion } void h(vector< auto_ ptr<Shape*> >& v) // dangerous: use of auto_ptr in container { sort(v.begin() ,v.end()) ; // Don’t do this: The sort will probably mess up v }

auto_ptr nie nadaje się do przechowywania wskaźników do tablic Wzorzec auto_ptr auto_ptr nie nadaje się do przechowywania wskaźników do tablic do tego celu można stosować wzorzec vector void g() { auto_ptr<int> p=new int[100]; // error, delete instead of delete[] invoked on exit from g } void g() { vector<int> a(100); int* p=&(a[0]); // guaranteed to point to array of 100 integers }

Laboratorium - zadanie Proszę zaimplementować prywatne funkcje jest_prostokatny(point a, point b, point c) dla klasy prostokatny jest_rownoramienny(point a, point b, point c) dla klasy rownorammienny jest_rownoboczny(point a, point b, point c) dla klasy rownoboczny jest_trojkatem(point a, point b, point c) dla klasy trojkat sprawdzające czy na podstawie współrzędnych przekazanych przez programistę można zbudować dany typ trójkąta. Proszę użyć zaimplementowanych funkcji w konstruktorach odpowiednich klas. W przypadki kiedy na podstawie danego zestawu współrzędnych nie można zbudować odpowiedniego trójkąta proszę rzucić wyjątek typu ex_trojkat. Kody źródłowe klas dostępne są na stronie www przedmiotu w pliku trojkat.cpp.