Programowanie obiektowe III rok EiT

Slides:



Advertisements
Podobne prezentacje
C++ wykład 9 ( ) Szablony.
Advertisements

C++ wykład 2 ( ) Klasy i obiekty.
C++ wykład 4 ( ) Przeciążanie operatorów.
Język C/C++ Funkcje.
Programowanie obiektowe
C++ Paweł Rzechonek Instytut Informatyki Uniwersytetu Wrocławskiego
Deklaracje i definicje klas w C++ Składowe, pola, metody Konstruktory
Klasa listy jednokierunkowej Przekazywanie parametrów do funkcji
Programowanie obiektowe
Programowanie obiektowe PO PO - LAB 4 Wojciech Pieprzyca.
Standardowa biblioteka języka C++
Klasy i obiekty.
Wzorce.
Static, const, volatile.
Języki programowania C++
Szablony (wzorce) Przykład 1: Szablon klasy -
ODE Triggery. Wstęp n Triggery są trójką zdarzenie-warunek-akcja (event-condition- action). n Zdarzenia mogą być proste lub złożone, co zostanie omówione.
Struktury.
C++ wykład 2 ( ) Klasy i obiekty.
Zasady zaliczenia Warunki uzyskania zaliczenia:
Typy prywatne 1 Typy prywatne W Adzie typy prywatne (private types) służą do bezpiecznego udostępniania danych zdefiniowanych w pakiecie, z którego korzysta.
Projektowanie i programowanie obiektowe II - Wykład II
nowe operatory & . (kropka) * operator rzutowy -> , (przecinek)
Programowanie obiektowe III rok EiT
Podstawy informatyki (4)
Programowanie obiektowe III rok EiT
Programowanie obiektowe III rok EiT
Informatyka I Wykład 10 WSKAŹNIKI I ADRESY Jerzy F. Kotowski.
T: Różnice pomiędzy programowaniem strukturalnym a obiektowym
Jerzy F. Kotowski1 Informatyka I Wykład 11 STRUKTURY I UNIE.
Programowanie obiektowe III rok EiT
Programowanie obiektowe III rok EiT dr inż. Jerzy Kotowski Wykład VIII.
Jerzy F. Kotowski1 Informatyka I Wykład 14 DEKLARATORY.
Programowanie obiektowe – zastosowanie języka Java SE
JAVA c.d.. Instrukcji wyboru SWITCH używamy, jeśli chcemy w zależności od wartości pewnego wyrażenia wykonać jeden z kilku fragmentów kodu. Jest to w.
Programowanie obiektowe III rok EiT dr inż. Jerzy Kotowski Wykład XIII.
Programowanie obiektowe III rok EiT dr inż. Jerzy Kotowski Wykład IX.
Programowanie obiektowe III rok EiT
Java – coś na temat Klas Piotr Rosik
Inicjalizacja i sprzątanie
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.
Podstawy informatyki 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 3 ( )
Kurs języka C++ – wykład 9 ( )
Treści multimedialne - kodowanie, przetwarzanie, prezentacja Odtwarzanie treści multimedialnych Andrzej Majkowski informatyka +
K URS JĘZYKA C++ – WYKŁAD 10 ( ) Szablony.
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 2 ( ) Klasy i obiekty.
Programowanie obiektowe Wykład 9 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/15 Dariusz Wardowski.
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.
Dziedziczenie Wykład 7 Dziedziczenie sekwencyjne
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.
PO13-1 / 19 Wykład 13 Wyjątki i ich zgłaszanie Wyłapywanie wyjątków Obsługa wyjątków Wykorzystanie polimorfizmu Filtrowanie wyjątków Błędy w konstruktorach.
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.
K URS JĘZYKA C++ – WYKŁAD 3 ( ) Przenoszenie Składowe statyczne Funkcje wbudowane Argumenty domyślne.
C++ mgr inż. Tomasz Turba Politechnika Opolska 2016.
Kurs języka C++ – wykład 3 ( )
(według:
Programowanie Obiektowe – Wykład 2
Kurs języka C++ – wykład 4 ( )
Programowanie obiektowe – zastosowanie języka Java SE
Założenia projektowe Javy
PGO Przeciążanie metod i konstruktorów
Zapis prezentacji:

Programowanie obiektowe III rok EiT 2017-03-28 10:39:22 Programowanie obiektowe III rok EiT dr inż. Jerzy Kotowski Wykład XII

Program wykładu Język C++ Klasówka Klasy, c.d. Przykład problemu przeciążanie (przeładowanie) operatorów 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

Reguły przeciążania operatorów Przeciążenia operatora dokonuje się definiując swoją własną funkcję, która: Nazywa się operator@ gdzie @ jest operatorem, o którego przeładowanie nam chodzi. Co najmniej jeden z argumentów jest obiektem danej klasy. Składnia: typ operator@(argumenty) Lista operatorów, które mogą być przeładowane: + - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- , ->* -> new delete () [] Operatory & * - + mogą być przeciążane w zarówno w wersji jednoargumentowej jak i dwuargumentowej. Lista operatorów, które nie mogą być przeciążane: . .* :: ?:

Reguły przeciążania operatorów c.d. Przeciążać można wymienione operatory i tylko te. Za wyjątkiem operatorów new i delete nie ma ograniczeń na typ zwracanej wartości. Nie można zmieniać priorytetu operatora. Nie można zmieniać liczby argumentów operatora. Nie można zmieniać łączności operatora. Ten sam operator można przeciążyć wielokrotnie. Przynajmniej jeden z argumentów musi być typu zdefiniowanego przez użytkownika. Nie ma znaczenia który. Jeżeli funkcja operatorowa jest zdefiniowana jako funkcja zewnętrzna (tzn. nie jako funkcja składowa w klasie) to liczba argumentów na liście musi się zgadzać z liczbą, na której pracuje operator. W przypadku operatora definiowanego jako funkcja składowa lista argumentów nie zawiera lewego operandu. Jest nim obiekt typu klasa, w której dokonuje się takiego przeciążenia. Operatory predefiniowane: = & , new delete

Przeciążamy co popadnie .. \test0.sln Program vect1.cpp class vect { int *p; int size; public: int ub; // upper bound = size-1 vect(int n=10); // konstruktor z domniemanym argumentem vect(const vect &v); // konstruktor kopiujący ~vect() { delete p; } // destruktor vect& operator =(const vect &v); // operator podstawiania int operator ==(const vect &v) const;// porównanie wektorów int& operator[](int i); // operator indeksowy vect operator+(const vect &v) const;// dodawanie wektorów vect operator-(const vect &v) const;// odejmowanie wektorów int operator*(const vect &v) const; // iloczyn skalarny vect operator*(int a) const;// mnożenie wektora przez skalar void operator !() const; // print };

Opis interfejsu klasy Operator podstawiania i operator indeksowy udostępniają odpowiednie obiekty. Przeciążenie operatora podstawiania jest niezbędne do poprawnej pracy programu. Wszystkie pozostałe przeciążone operatory obiecują nie zmieniać swoich operandów. Podobnie deklaruje konstruktor kopiujący. Wielokrotnie korzystano ze słowa kluczowego this np. w składni vect temp(*this); Mnożenie wektora przez liczbę zdefiniowano jako funkcję składową w klasie. Było to możliwe bo lewy argument jest w tym przypadku obiektem klasy. Mnożenie liczby przez wektor zdefiniowano jako funkcję zewnętrzną ze względu na to, że lewy argument jest obiektem typu build-in. Definicja ta korzysta z funkcji składowej i jest bardzo prosta ale formalnie jest niezbędna: vect operator*(int a, const vect &v) { return v*a; }

Kod klienta - opis Zakładamy trzy wektory trójelementowe a, b, c. Do dwóch pierwszych coś podstawiamy za pomocą przeciążonego operatora indeksowego. Do wektora c podstawiamy wartość wyrażenia 2*a-b. Wyprowadzamy wartości wektorów a, b, c przy pomocy przeciążonego operatora logicznej negacji. Na koniec wyprowadzamy wartość iloczynu skalarnego a*b. Prawidłowy jest napis vect d[5]; Jest to 5-elementowa tablica obiektów typu vect zakładanych przy pomocy konstruktora domniemanego, to znaczy 10-elementowych. Użycie: d[2][3] = 7; W powyższej instrukcji użyto dwóch różnych operatorów indeksowych: wbudowanego i przeciążonego.

Klasa histogram .. \test0.sln Cel: przeciążenie operatora << dopisującego nową wartość do histogramu. Interfejs klasy zawiera tylko niezbędne elementy. Na potrzeby kodu klienta potrzebne są poniższe własności klasy: Dynamiczna rezerwacja pamięci Klasa ma mieć zabezpieczenie przed wyjściem poza obszar histogramu. Łączność operatora << w celu umożliwienia napisów typu: h << a << b; histogram.cpp

Definicja klasy histogram class histogram { double min; // dolna granica double max; // górna granica int przedz; // liczba przedziałów double * adlk; // wskaźnik do tablicy liczników double szer; // szerokość przedziału public: histogram(double=0.0,double=1.0,int=10); // konstruktor ~histogram (){ delete [] adlk; } // destruktor histogram & operator << (double); // dorzuca wartość int operator [] (int); // licznik - zwraca wartość pola };

Najważniejsze elementy klasy Przeciążony operator udostępnia „siebie” co rozwiązuje problem łączności operatora: histogram& return (*this); histogram& histogram::operator<<(double w) { int np=(w-min)/szer; if((np >= 0)&&(np<=przedz-1)) adlk[np]++; //tylko "dobre" wartości return (*this); } int histogram::operator [] (int n) if((n<0) || (n>=przedz)) n=0; return adlk[n];

Kod klienta void main(void) { const int lprzedz=4; double min=0, max=5, szer=(max-min)/lprzedz; histogram h(min,max,lprzedz);// cztery przedziały od 0 do 5 h << 1.5 << 2.4 << 3.8 << 3.0 << 2.0 << 3.5 << 2.8 << 4.6; h << 12.0 << -3.5; for (int i=0;i<10;i++) h << i/2.0; cout << "Przedzial liczba\n"; for(i=0;i<lprzedz;i++) cout << "[" << i*szer << ", " << (i+1)*szer << "]\t" << h[i] << "\n"; getch(); }

Przeciążanie operatorów inkrementacji i dekrementacji Nienazwany argument pozwala przeciążać operatory inkrementacji i dekrementacji jako składowe klasy tak, aby można było odróżnić znaczenia post i prefiksowe. Przypomnienie: void Ala(int) Nienazwany argument występuje w definicji i w prototypie. Operator z jednym argumentem udaje operator dwuargumentowy i ten drugi argument może być argumentem nienazwanym. Odpowiada to składni x operator y, gdzie pierwszy argument to “ja sam” a drugiego może nie być. Czyli: x++ to przeciążenie operatora z dwoma a ++x przeciążenie operatora z jednym argumentem. Przykład: class String { public: String& operator ++(); String operator ++(int); };

Klasa String .. \test0.sln class String{ // String dynamiczny IV.cpp char *s; int len; static Stan; public: String(void); String(int n); String(const char *p); String(const String& str); ~String() { delete s; } int lenght() const { return(len); } String& operator =(const String &str);// operator podstawiania void print() const {cout << s << "\nLenght: " << len << "\n";} void operator !() const {print();} // print operator char *() const { return(s); }// operator konwersji static void switch_stan(void); String& operator ++(void); // małe na duże i zwraca nowy String operator ++(int); // małe na duże i zwraca stary String& operator --(void); // duże na małe i zwraca nowy String operator --(int); // duże na małe i zwraca stary friend String operator +(const String str1, const String str2);};

Interesujące elementy klasy String Klasa String podobnie jak poprzednio ma cztery konstruktory Konstruktor kopiujący korzysta z przeciążonego operatora podstawiania Pojawił się przeciążony operator dodawania zdefiniowany jako funkcja globalna zaprzyjaźniona z klasą: friend String operator +(const String str1, const String str2); Wszędzie gdzie jest to możliwe pojawiło się słowo kluczowe const Dokonano przeciążenia jednoargumentowego operatora logicznego ! String& operator ++(void); zamienia małe litery na duże i zwraca nowy string jako referencję String operator ++(int); zamienia małe litery na duże i zwraca stary string przez kopiowanie String& operator --(void); zamienia duże litery na małe i zwraca nowy string jako referencję String operator --(int); zamienia duże litery na małe i zwraca stary string przez kopiowanie

Wybrane definicje funkcji String::String(const String& str) { s=0; (*this)=str; } String& String::operator ++(void) { char mm = 'A' - 'a'; for(int i=0; i<len; i++) if(s[i] >='a' && s[i] <='z') s[i] += mm; return (*this); } String String::operator ++(int) { String temp(*this); char mm = 'A' - 'a'; for(int i=0; i<len; i++) if(s[i] >='a' && s[i] <='z') s[i] += mm; return temp; } String operator +(const String str1, const String str2) { String temp(str1.len+str2.len); strcpy(temp.s,str1.s); strcat(temp.s,str2.s); return temp;}

Coś za coś Operator dodawania obiektów klasy String: String operator +(const String str1, const String str2) można zdefiniować jako funkcję składową w klasie: String String::operator +(const String& str) const Korzyści: Niepotrzebna jest już przyjaźń Straty: Nie ma możliwości dokonywania niejawnej konwersji argumentów. Związane jest to z faktem, że napis a+b jest równoważny napisowi a.operator+(b). Nie można zatem w kodzie klienta napisać na przykład c=a+b jeżeli a nie jest typu String. Ewentualne pytanka na klasówkę: W jaki sposób wykonywana jest linia: cout << a+b; W jaki sposób wykonywana jest linia: cout << str1+b; Czy kompilator przeżyje coś takiego: cout << str1+str2;

Analogie – klasa Complex class Complex { double Re,Im; public: Complex(float x=0, float y=0): Re(x), Im(y){} void print() { cout << Re << "+" << Im << "i "; } // operator double() { return(sqrt(Re*Re+Im*Im)); } trzeba usunąć!!! friend Complex operator+(Complex z1, Complex z2); }; Complex operator+(Complex z1, Complex z2) { // Operator dodawania przeciążony jako funkcja globalna Complex temp; temp.Re=z1.Re+z2.Re; temp.Im=z1.Im+z2.Im; return temp; } void main(void) { Complex a(1,5),b(0,-2),c; cout << "\na= "; a.print(); cout << "\nb= "; b.print(); c=1+a+b; cout << "\n1+a+b= "; c.print(); // Niejawna konwersja argumentu getch(); Należy usunąć konwersję na typ double bo prowadzi ona do niejednoznaczności w wyrażeniu 1+a: error C2666: 'operator`+'' : 2 overloads have similar conversions