Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Programowanie obiektowe 2013/2014 Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi.

Podobne prezentacje


Prezentacja na temat: "Programowanie obiektowe 2013/2014 Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi."— Zapis prezentacji:

1 Programowanie obiektowe 2013/2014 Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego Matuszyka

2 Dostęp do składników prywatnych int main() { punkt A; A.wpisz(); return 0; } void wypisz(punkt &A) { cout<<"x = "<<A.x<<endl; cout<<"y = "<<A.y<<endl; } class punkt { double x,y; public: void wpisz(); }; void punkt::wpisz() { cin>>x>>y; } void wypisz(punkt &A); BŁĄD Funkcje nie będące składnikami klasy nie mają dostępu do ich składników prywatnych

3 Dostęp do składników prywatnych int main() { punkt A; A.wpisz(); A.wypisz(); return 0; } class punkt { double x,y; public: void wpisz(); void wypisz(); }; void punkt::wpisz() { cin>>x>>y; } void punkt::wypisz() { cout<<"x = "<<x<<endl; cout<<"y = "<<y<<endl; }

4 Funkcja zaprzyjaźniona int main() { punkt A; A.wpisz(); wypisz(A); return 0; } void wypisz(punkt &A) { cout<<"x = "<<A.x<<endl; cout<<"y = "<<A.y<<endl; } class punkt { double x,y; public: void wpisz(); friend void wypisz(punkt &A); }; void punkt::wpisz() { cin>>x>>y; } void wypisz(punkt &A); Funkcja zaprzyjaźniona z klasą to funkcja, która ma dostęp do wszystkich zmiennych składowych klasy.

5 Funkcja zaprzyjaźniona class kolo; class punkt { double x,y; public: void wpisz(); friend bool czy(punkt &,kolo &); }; class kolo { double x,y,r; public: void wpisz(); friend bool czy(punkt &,kolo &); }; void punkt::wpisz() { cin>>x>>y; } void kolo::wpisz() { cin>>x>>y>>r; } bool czy(punkt &A, kolo &K) { if (sqrt(pow(A.x-K.x,2)+pow(A.y-K.y,2))<=K.r) return true; return false; } int main() { punkt A; kolo K; A.wpisz(); K.wpisz(); cout << czy(A,K) <<endl; return 0; }

6 Klasy zaprzyjaźnione class punkt { double x,y; }; class kolo { punkt O; double r; public: void wpisz(); }; void kolo::wpisz() { cin>>O.x>>O.y>>r; } class punkt { friend class kolo; double x,y; }; class kolo { punkt O; double r; public: void wpisz(); }; void kolo::wpisz() { cin>>O.x>>O.y>>r; }

7 Klasy zaprzyjaźnione 1.Przyjaźń jest jednostronna. Jeżeli klasa A deklaruje przyjaźń z klasą B to klasa A nie jest automatycznie traktowana przez klasę B jak przyjaciel. 2.Przyjaźń nie jest przechodnia. Jeżeli klasa A zadeklaruje przyjaźń z klasą B, klasa B zadeklaruje przyjaźń z klasą C to klasa C nie jest traktowana przez klasą A jak przyjaciel. 3. Przyjaźń nie jest dziedziczna. Jeżeli klasa A deklaruje przyjaźń z klasą B, a klasa C jest potomkiem klasy A to klasa C nie traktuje klasy B jako przyjaciela.

8 Zmienne statyczne Zmienna statyczna to zmienna wspólna dla wszystkich obiektów danej klasy. int main() { ulamek pierwszy,drugi; cout << pierwszy.mianownik << endl; cout << drugi.mianownik << endl; return 0; } #include using namespace std; class ulamek { public: int licznik; static int mianownik; }; int ulamek::mianownik=5;

9 Funkcje statyczne #include using namespace std; class punkt { double x,y; static int ruch; public: punkt(); punkt(double, double, int); void wypisz(); void przesun(double, double); static void pozwolenie() {ruch=!ruch;}}; int punkt::ruch=0; punkt::punkt(){ x=0;y=0;ruch=0;} punkt::punkt(double a, double b, int c) {x=a;y=b;ruch=c;} void punkt::wypisz() {cout<<"x = "<<x<<endl; cout<<"y = "<<y<<endl;} void punkt::przesun(double a, double b) {if (ruch) {x=x+a;y=y+b;}} int main() { punkt A(1,1,0); punkt B(2,2,0); A.przesun(1,2); A.wypisz(); punkt::pozwolenie(); //A.pozwolenie(); A.przesun(1,2); A.wypisz(); B.przesun(1,2); B.wypisz(); return 0; }

10 Funkcje statyczne 1.Do funkcji statycznej nie jest przekazywany wskaźnik this => (nie) można odwoływać się do zwykłych składników klasy. static void pozwolenie(punkt &A) {ruch=!ruch;A.x=-A.x;}}; 2.Funkcje statyczne można wywoływać na rzecz klasy (nie konkretnego jej obiektu).

11 Zwykła klasa #include using namespace std; class cmpx { friend cmpx suma(cmpx,cmpx); double re,im; public: cmpx(double a=0, double b=0) :re(a),im(b){} void wyp() {cout<<"re="<<re<<endl; cout<<"im="<<im<<endl;} }; cmpx suma(cmpx A,cmpx B) {cmpx C(A.re+B.re,A.im+B.im); return C;} int main() { cmpx A(1,2),B(3,4),C; C=suma(A,B); C.wyp(); return 0; }

12 Przeładowanie operatorów #include using namespace std; class cmpx { friend cmpx operator+(cmpx,cmpx); double re,im; public: cmpx(double a=0, double b=0) :re(a),im(b){} void wyp() {cout<<"re="<<re<<endl; cout<<"im="<<im<<endl;} }; cmpx operator+(cmpx A,cmpx B) {cmpx C(A.re+B.re,A.im+B.im); return C;} int main() { cmpx A(1,2),B(3,4),C,D; C=A+B; C.wyp(); D=operator+(A,B); D.wyp(); return 0; }

13 Definicja operatora typ_zwracany operator@(argumenty) typ_zwracany – dowolny (z wyjątkami!!!) @ - przeładowywany operator (np. + * -) argumenty – przynajmniej jeden z argumentów musi być obiektem danej klasy lub referencją do obiektu danej klasy (nie może być wskaźnikiem)

14 Definicja operatora Funkcja operatorowa może być: 1.funkcją globalną (nie dla każdego operatora), 2.nie-statyczną funkcją składową klasy (dla niektórych operatorów musi być statyczna). Globalną funkcję operatorową obowiązują prawa dostępu tak jak każdą inną funkcję!

15 Operatory, które nie można / można przeładować +-*/%^&|~ !=<>+=-=*=/=%= ^=&=|=<<>><<=>>===!= <=>=&&||++--,->*-> ()[]newnew[]deletedelete[] Operatory, których nie można przeładować: Operatory & * + - można przeładowywać w wersji jedno- i dwuargumentowej Operatory, które można przeładować:..*::? :

16 Uwagi dotyczące przeładowywania 1.Nie można tworzyć własnych operatorów. 2.Nie można przeładowywać operatorów dla typów wbudowanych. 3.Przeładowany operator może robić cokolwiek. 4.Może zwracać dowolny typ. Wyjątkiem są operatory: new new[] delete delete[] -> 5.Nie można zmieniać priorytetów operatorów. 6.Nie można zmieniać liczby argumentów, na których operatorów wykonuje działanie.

17 Uwagi dotyczące przeładowywania 7.Nie można zmieniać łączności operatorów. 8.Liczba argumentów przekazywanych do funkcji operatorowej jest zawsze równa: –liczbie argumentów na których pracuje operator – w przypadku gdy funkcja jest globalna, –o jeden mniej niż liczba argumentów na których pracuje operator – w przypadku gdy funkcja jest składową klasy. –WYJĄTEK OD POWYŻSZYCH: ()

18 Uwagi dotyczące przeładowywania 9.Co najmniej jeden z argumentów musi być obiektem (lub referencją do obiektu) klasy zdefiniowanej przez użytkownika – obojętnie który (nie zawsze obojętnie). 10.Argumenty funkcji operatorowej nie mogą być domniemane (WYJĄTEK: () ). 11.Operatory = & (wersja jednoargumentowa), new new[] delete delete[] są zawsze generowane automatycznie (operator = nie zawsze).

19 Funkcja składowa vs funkcja globalna 1.Jeżeli operator ma dopuszczać by po jego lewej stronie stał typ wbudowany to nie może być funkcją składową. 2.Dla typu enum funkcja operatorowa musi być funkcją globalną. 3.Przy użyciu operatora jako funkcji składowej w stosunku do pierwszego argumentu nie może zajść żadnej konwersji. 4.Operatory = [] () -> muszą być funkcjami składowymi klasy.

20 Operator przypisania Operator przypisania nie jest generowany: 1.Jeżeli klasa ma składnik const, 2.Jeżeli klasa ma składnik będący referencją. 3.Jeżeli w skład klasy wchodzi inna klasa, która ma operator przypisania zdefiniowany jako private. 4.Jeżeli klasa ma klasę podstawową, w której operator przypisania zdefiniowany jako private. Operatora przypisania się nie dziedziczy.

21 Operator przypisania Automatycznie wygenerowany operator przypisania wykonuje podstawienie składnik po składniku -> mogą wystąpić podobne problemy jak w przypadku automatycznie wygenerowanego konstruktora kopiującego!!!

22 Co powinien robić operator przypisania? 1.Sprawdzić czy nie kopiuje do samego siebie (A=A). 2.Zlikwidować dotychczasowe wnętrze. 3.Zbudować obiekt jeszcze raz na podobieństwo obiektu wzorcowego. 4.Zwracać skopiowany albo wzorcowy obiekt (są takie same).

23 Program z przeładowanymi operatorami > oraz = I/V #include using namespace std; class wektor { friend ostream &operator<<(ostream &ekran, const wektor &A); friend istream &operator>>(istream &klawiatura, wektor &A); int n; double *W; public: wektor(int a=1); wektor(int a, double *A); ~wektor(); wektor &operator=(const wektor &A); };

24 Program z przeładowanymi operatorami > oraz = II/V wektor::wektor(int a):n(a) { W=new double[n]; for (int i=0;i<n;i++) W[i]=0; } wektor::wektor(int a, double *A):n(a) { W=new double[n]; for (int i=0;i<n;i++) W[i]=A[i]; } wektor::~wektor() { delete W; }

25 Program z przeładowanymi operatorami > oraz = III/V wektor &wektor::operator=(const wektor &A) { if (&A==this) return *this; delete W; n=A.n; W=new double[n]; for (int i=0;i<n;i++) W[i]=A.W[i]; return *this; }

26 Program z przeładowanymi operatorami > oraz = V/V int main() { double tab[]={1,2}; wektor X(2,tab),Y(3); cout<<"Wektor X:\n"<<X<<endl; cout<<"Podaj wektor Y\n"; cin>>Y; cout<<"Wektor Y:\n"<<Y<<endl; Y=X; cout<<"Wektor Y:\n"<<Y<<endl; return 0; }

27 Operator << Co to jest cout? – obiekt klasy ostream! Pytanie: Czy funkcja operator<< powinna być: 1.funkcją globalną 2.funkcją składową klasy (KTÓREJ)?

28 Operator << ODPOWIEDŹ: funkcją globalną, ponieważ: nie może być funkcją składową klasy ostream – oczywiste może być funkcją składową klasy wektor, ale wówczas trzeba stosować zapis: X << cout; który jest równoznaczny z zapisem: X.operator<<(cout);

29 Program z przeładowanymi operatorami > oraz = IV/V ostream &operator<<(ostream &ekran, const wektor &A) { for (int i=0;i<A.n;i++) ekran<<A.W[i]<<endl; return ekran; } istream &operator>>(istream &klawiatura, wektor &A) { for (int i=0;i<A.n;i++) klawiatura>>A.W[i]; return klawiatura; }

30 Dlaczego operatory > oraz = zwracają to co zwracają? Aby możliwe było wywołanie kaskadowe: a = b = c; cout << a << endl; cin >> a >> b;

31 Operator [] #include using namespace std; class wektor { … double & operator[](int a); ZWRACA REFERENCJĘ };

32 Operator [] double &wektor::operator[](int a) { return W[a]; } int main() { … double tab[]={1,2,3}; wektor X(3,tab); cout<<"Wektor X:\n"<<X<<endl; cout<<X[1]<<endl; return 0; }

33 Dlaczego ta referencja jest taka ważna? Załóżmy, że funkcja zwraca wartość double wektor::operator[](int a); Wówczas zapis: X[1]=5; wywoła błąd (2=5 – kompilator zaprotestuje)

34 Operator () 1.Jako jedyny może przyjmować dowolną liczbę argumentów -> może być przeładowany. 2.Argumentu mogą być domniemane. 3.Jeżeli chcemy go umieścić po prawej stronie operatora przypisania to musi zwracać referencję (jak w przypadku operatora []). 4.Można go zastosować do indeksacji tablic wielowymiarowych.

35 Operator -> 1.Operator -> jest jednoargumentowy, pomimo że po jego obu stronach musi coś stać. 2.Działa na argumencie stojącym po jego lewej stronie. 3.Nie interesuje go co stoi po jego lewej stronie.

36 Operator -> Wywołanie: obiekt->skladnik; jest równoważne: (obiekt.operator->())->skladnik; Operator powinien zwracać: wskaźnik, obiekt (lub referencję) takiej klasy, która ma również przeładowany operator ->

37 Operatory new new[] delete delete[] new new[] delete delete[] 1. Operatory te są statycznymi funkcjami składowymi klasy. 2. Muszą zwracać void *.2. Muszą zwracać void. 3. Jako argument przyjmują typ size_t. 3. Jako argument przyjmują void *. 4. Nie mogą być wirtualne. 5. Istnieje możliwość przeładowania globalnej wersji operatora.

38 Program z przeładowanymi operatorami new new[] delete delete[]I/III #include using namespace std; class wektor { … static void *operator new(size_t rozmiar); static void *operator new[](size_t rozmiar); static void operator delete(void *wsk); static void operator delete[](void *wsk); };

39 Program z przeładowanymi operatorami new new[] delete delete[]II/III void *wektor::operator new(size_t rozmiar) { return new char[rozmiar]; } void *wektor::operator new[](size_t rozmiar) { return new char[rozmiar]; } void wektor::operator delete(void *wsk) { delete wsk; return; } void wektor::operator delete[](void *wsk) { delete[] wsk; return; }

40 Program z przeładowanymi operatorami new new[] delete delete[]III/III int main() { … double tab[]={1,2,3,4,5}; int n=3; wektor *X; X=new wektor(5,tab); cout<<*X<<endl; delete X; X=new wektor[n]; for (int i=0; i<n; i++) cin >> X[i]; for (int i=0; i<n; i++) cout << X[i]; delete[] X; return 0; }

41 Operatory ++A --A A++ A-- Operatory ++A oraz A++ działają na jednym argumencie i maja takie same nazwy. Jak je przeładować? Operator ++A jest definiowany jako jednoargumentowy. Operator A++ jest definiowany jako dwuargumentowy. Analogiczna sytuacja jest z operatorami --A oraz A--.

42 Program z przeładowanymi operatorami ++A oraz A++ wektor &wektor::operator++() { for (int i=0; i<n; i++) W[i]++; return *this; } wektor wektor::operator++(int) { wektor wek(*this); for (int i=0; i<n; i++) W[i]++; return wek; } #include using namespace std; class wektor { … wektor &operator++(); wektor operator++(int); };

43 Program z przeładowanymi operatorami ++A oraz A++ int main() { … double tab[]={1,2}; wektor X(2,tab),Y,Z; cout<<"\nWektor X:\n"; cout<<X<<endl; Y=X++; cout<<"\nWektor X:\n"; cout<<X<<endl; cout<<"\nWektor Y:\n"; cout<<Y<<endl; Z=++X; cout<<"\nWektor X:\n"; cout<<X<<endl; cout<<"\nWektor Z:\n"; cout<<Z<<endl; return 0; }

44 Cała klasa wektor class wektor { friend ostream &operator<<(ostream &ekran, const wektor &A); friend istream &operator>>(istream &klawiatura, wektor &A); int n; double *W; public: wektor(int a=1); wektor(int a, double *A); ~wektor(); wektor &operator=(const wektor &A); double &operator[](int a); static void *operator new(size_t rozmiar); static void *operator new[](size_t rozmiar); static void operator delete(void *wsk); static void operator delete[](void *wsk); wektor &operator++(); wektor operator++(int); };

45 Brakuje konstruktora kopiującego #include using namespace std; class wektor { … wektor(const wektor &A); … }; wektor::wektor(const wektor &A):n(A.n) { W=new double[n]; for (int i=0; i<n; i++) W[i]=A.W[i]; }

46 Prezentacja udostępniona na licencji Creative Commons: Uznanie autorstwa, Na tych samych warunkach 3.0. Pewne prawa zastrzeżone na rzecz autorów. Zezwala się na dowolne wykorzystywanie treści pod warunkiem wskazania autorów jako właścicieli praw do prezentacji oraz zachowania niniejszej informacji licencyjnej tak długo, jak tylko na utwory zależne będzie udzielana taka sama licencja. Tekst licencji dostępny jest na stronie: http://creativecommons.org/licenses/by-sa/3.0/deed.pl


Pobierz ppt "Programowanie obiektowe 2013/2014 Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi."

Podobne prezentacje


Reklamy Google