Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

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

Podobne prezentacje


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

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

2 Przeładownie nazwy funkcji polega na tym, że w danym zakresie ważności jest więcej niż jedna funkcja o takiej samej nazwie. To, która z nich zostaje w danym przypadku uaktywniona, zależy od liczby i typu argumentów wywołania jej. 1 1 Grębosz J., Symfonia C++ standard

3 Wybór funkcji do przeładowania Warto rozważyć przeładowanie deklaracji funkcji gdy: –funkcje posiadają pewną cechę wspólną a mają działać na obiektach różnych typów int wypiszWynik( const jakas_klasa & A); int wypiszWynik( const double A[], unsigned int size); –funkcje w sensie abstrakcyjnym wykonują analogiczną czynność, która w języku naturalnym ma tę samą nazwę double potega( double x, double y); int potega( int x, int y); I odwrotnie: nie przeładowywać deklaracji, jeśli nie potrzebujemy tej samej nazwy dla różnych działań

4 Lista argumentów przy przeładowaniu Dwie funkcje mają różną listę argumentów gdy: Funkcje posiadają różną liczbę argumentów Funkcje posiadają różne typy argumentów (na tych samych pozycjach) Funkcje posiadają różną kolejność argumentów Typ zwracany przez przeładowaną funkcję nie jest brany pod uwagę! Definicje funkcji o takiej samej nazwie i które nie spełniają powyższych wymagań są wzajemnie niejednoznaczne

5 Różna liczba argumentów #include using namespace std; void napis(int a){cout<<"1 x int\n";} void napis(int a,int b){cout<<"2 x int\n";} void napis(int a,int b,int c){cout<<"3 x int\n";} int main() { napis(1); napis(1,2); napis(1,2,3); return 0; } 1 x int 2 x int 3 x int

6 Różne typy argumentów #include using namespace std; void napis(int a){cout<<"int\n";} void napis(double a){cout<<"double\n";} void napis(char a){cout<<"char\n";} int main() { napis(1); napis(1.5); napis('a'); napis(static_cast (1.5)); return 0; } int double char int

7 Różna kolejność argumentów #include using namespace std; void napis(int a, double b){cout<<"int, double\n";} void napis(double b, int a){cout<<"double, int\n";} int main() { napis(1,1.5); napis(1.5,1); return 0; } int, double double, int

8 Różne typy funkcji #include using namespace std; int zwroc(double a){return static_cast (a);} double zwroc(double a){return a;} int main() { int a=zwroc(1.5); double b=zwroc(1.5); return 0; } BŁĄD – funkcje nierozróżnialne cout<<zwroc(1.5);

9 Argumenty domniemane #include using namespace std; void napis(int a){cout<<"int\n";} void napis(int a, double b=0){cout<<"int, double\n";} int main() { napis(1,1.5); napis(1); return 0; } BŁĄD – pasuje do obu funkcji

10 typedef #include using namespace std; typedef int calkowity; void napis(int a){cout<<"int\n";} void napis(calkowity a){cout<<"calkowity\n";} int main() { return 0; } BŁĄD – funkcje nierozróżnialne

11 enum #include using namespace std; enum litera {a=1,b,c,d}; void napis(int a){cout<<"int\n";} void napis(litera l){cout<<"litera\n";} int main() { litera l=a; int i=1; napis(l); napis(i); return 0; } litera int

12 Tablica i wskaźnik #include using namespace std; void napis(int a[]){cout<<"tablica\n";} void napis(int *a){cout<<"wkaznik\n";} int main() { return 0; } BŁĄD int [] -> int * - trywialna konwersja

13 Tablice wielowymiarowe #include using namespace std; void napis(int a[2][3]){cout<<"tablica 2x3\n";} void napis(int a[3][4]){cout<<"tablica 3x4\n";} int main() { int tab1[2][3]={1,2,3,4,5,6}; int tab2[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; napis(tab1); napis(tab2); return 0; } tablica 2x3 tablica 3x4

14 Tablice wielowymiarowe #include using namespace std; void napis(int a[2][3]){cout<<"tablica 2x3\n";} void napis(int a[3][3]){cout<<"tablica 3x3\n";} int main() { return 0; } BŁĄD Pierwszy rozmiar tablicy nie jest brany pod uwagę

15 Referencja #include using namespace std; void napis(int a){cout<<"wartosc\n";} void napis(int &a){cout<<"referencja\n";} int main() { napis(1); int a=1; napis(a); return 0; } BŁĄD – dwuznaczne wywołanie

16 Typy: T, const T, volatile T #include using namespace std; void napis(int a){cout<<"int\n";} void napis(const int a){cout<<"const int\n";} void napis(volatile int a){cout<<"volatile int\n";} int main() { return 0; } BŁĄD const oraz volatile mówią kompilatorowi jak traktować zmienną wewnątrz funkcji

17 Typy: T*, const T*, volatile T* #include using namespace std; void napis(int *a){cout<<"int*\n";} void napis(const int *a){cout<<"const int*\n";} void napis(volatile int *a){cout<<"volatile int*\n";} int main() { int a=1; const int b=2; volatile int c=3; napis(&a); napis(&b); napis(&c); return 0; } int* const int* volatile int*

18 Typy: T&, const T&, volatile T& #include using namespace std; void napis(int &a){cout<<"int&\n";} void napis(const int &a){cout<<"const int&\n";} void napis(volatile int &a){cout<<"volatile int&\n";} int main() { int a=1; const int b=2; volatile int c=3; napis(a); napis(b); napis(c); return 0; } int& const int& volatile int&

19 Wskaźnik do przeładowanej funkcji #include using namespace std; void napis(int a){cout<<"int\n";} void napis(double a){cout<<"double\n";} void napis(char a){cout<<"char\n";} int main() { void (*wsk1)(int)=napis; void (*wsk2)(double)=napis; void (*wsk3)(char)=napis; wsk1(1); wsk2(1.5); wsk3('a'); wsk1(1.5); return 0; } int double char int

20 Wskaźnik do przeładowanej funkcji #include using namespace std; void napis(int a){cout<<"int\n";} void napis(double a){cout<<"double\n";} void wywolaj1(void (*wsk)(int)){ cout<<"void (*wsk)(int)\n"; wsk(1);} void wywolaj2(void (*wsk)(double)){ cout<<"void (*wsk)(double)\n"; wsk(1.5);} int main() { wywolaj1(napis); wywolaj2(napis); return 0; } void (*wsk)(int) int void (*wsk)(double) double

21 Konwersje przy dopasowaniu Kompilator dopasowując deklarację funkcji może przeprowadzić konwersje argumentów Dla każdego argumentu może zostać przeprowadzona oddzielna ścieżka konwersji, o określonej jakości Rozważana w dopasowaniu funkcja F1 jest lepsza od innej rozważanej funkcji F2 jeżeli: –Ścieżka konwersji F1 dla każdego argumentu jest nie gorsza niż ścieżka dla F2 ORAZ –Dla co najmniej jednego argumentu ścieżka konwersji jest lepsza dla F1 Ogólnie jakość konwersji zależy od stopnia jej skomplikowania oraz stratności

22 Etapy dopasowania 1.Dopasowanie dokładne –dopasowanie dokładne z trywialną konwersją 2.Dopasowanie na zasadzie awansowania 3.Dopasowanie z użyciem konwersji standardowych 4.Dopasowanie z użyciem konwersji zdefiniowanych przez użytkownika 5.Dopasowanie do funkcji z wielokropkiem

23 Konwersje przy dopasowaniu 1.Dopasowanie dosłowne Dopasowanie dosłowne z trywialną konwersją int [] -> int* 2.Dopasowanie z awansem float -> double char signed char unsigned char-> int -> unsigned int short int unsigned short int

24 Konwersje przy dopasowaniu 2.Dopasowanie z awansem c.d. bool -> int wchar_t enum-> int -> unsigned int -> long -> unsigned long 3.Dopasowanie za pomocą konwersji standartowych 1.typu całkowitego int -> unsigned int unsigned int -> int

25 Konwersje przy dopasowaniu 3.Dopasowanie za pomocą konwersji standartowych c.d. 2.typu zmiennoprzecinkowego double -> float float -> double 3.pomiędzy typem całkowitym a zmiennoprzecinkowym zmiennoprzecinkowy -> całkowity całkowity -> zmiennoprzecinkowy 5.wskaźników dowolny wskaźnik nie-const i nie-volatile -> void* wsk. do klasy pochodnej -> wsk. do klasy podstawowej 6.referencji ref. do klasy pochodnej -> ref. do klasy podstawowej

26 Konwersje przy dopasowaniu 4.Dopasowanie za pomocą konwersji definiowanych przez użytkownika 5.Dopasowanie do funkcji z wielokropkiem void f(int a){cout<<"int";} void f(double a){cout<<"double";} void f(...){cout<<"...";} f("aaa");

27 Konwersje wskaźników Konwersje wskaźników nie zachodzą! 1.int* -> double* - przykład z poprzedniego wykładu 2.int* -> int [] – tablica zna swój rozmiar, wskaźnik nie wie czy pokazuje na pojedynczy element, czy na tablicę 3.wskaźnik pokazujący na funkcję wywoływaną z argumentem typu int nie może pokazywać na funkcję wywoływaną z parametrem typu char UWAGA! Nawet typ zwracany jest tutaj istotny!

28 Przykłady konwersji void fun(double a){cout<<"double\n";} void fun(int a){cout<<"int\n";} int main() { float a=1.5; fun(a); } double

29 Przykłady konwersji void f(int a){cout<<"int\n";} void f(float a){cout<<"float\n";} int main() { double a=3.4; f(a); } BŁĄD

30 Przykłady konwersji void fun(double a){cout<<"double\n";} void fun(int a){cout<<"int\n";} int main() { char a='A'; fun(a); } int

31 Przykłady konwersji void fun(double a){cout<<"double\n";} void fun(char a){cout<<"char\n";} int main() { int a=1; fun(a); } BŁĄD

32 Konwersje kilku argumentów #include using namespace std; void f(double a, int b){cout<<"double, int\n";} void f(int a, double b){cout<<"int, double\n";} int main() { f(1,2.3); f(1.2,3); f(1,2); return 0; } BŁĄD Obie konwersje są takie same

33 Funkcja zwracająca większą wartość int wieksza(int a,int b) { return (a > b) ? a : b; } int main() { int a,b; a=5; b=2; cout<<wieksza(a,b)<<endl; double c,d; c=2.5; d=2.2; cout<<wieksza(c,d)<<endl; return 0; } 5 2

34 ctrl+c, ctrl+v int wieksza(int a,int b) { return (a > b) ? a : b; } double wieksza(double a,double b) { return (a > b) ? a : b; } int main() { int a,b; a=5; b=2; cout<<wieksza(a,b)<<endl; double c,d; c=2.5; d=2.2; cout<<wieksza(c,d)<<endl; return 0; } 5 2.5

35 Szablon funkcji template typ wieksza(typ a, typ b) { return (a > b) ? a : b; } int main() { int a,b; a=5; b=2; cout<<wieksza(a,b)<<endl; double c,d; c=2.5; d=2.2; cout<<wieksza(c,d)<<endl; return 0; } Parametr szablonu Argumenty funkcji

36 Funkcje szablonowe Kompilator generuje funkcję szablonową gdy: wywołujemy funkcję, odwołujemy się do jej adresu. Funkcja szablonowa z jednym zestawem parametrów generowana jest tylko raz. Podobnie jak w przypadku przeładowań nazw funkcji typ rezultatu funkcji się nie liczy.

37 Kilka przykładów template typ1 wieksza(typ1 a, typ2 b, typ1 c) {…} template typ wieksza(typ a, typ *b) {…} template typ wieksza(typ a, int b) {…} template typ_w wieksza(typ1 a, typ2 b, typ1 c, typ_w) {...}

38 Problemy z typami definiowanymi template typ wieksza(typ a, typ b) { return (a > b) ? a : b; } class zespolona { public: double re,im; }; int main() { zespolona A,B; A.re=5; A.im=2; B.re=1; B.im=3; cout<<wieksza(A,B)<<endl; return 0; }

39 Problemy z typami wbudowanymi template double funkcja(typ a) { double m=a.modul(); return m; } class zespolona { public: double re,im; double modul(){ return sqrt(re*re+im*im);} }; int main() { zespolona A; A.re=5; A.im=2; cout<<funkcja(A)<<endl; cout<<funkcja(1)<<endl; return 0; }

40 Funkcja specjalizowana template typ wieksza(typ a, typ b) { cout<<"Funkcja szablonowa\n"; return (a > b) ? a : b; } int wieksza(int a,int b) { cout<<"Funkcja specjalizowana\n"; return (a > b) ? a : b; } int main() { cout<<wieksza(1,2)<<endl; cout<<wieksza(1.5,2.7)<<endl; return 0; } 2 2.7

41 Kolejność argumentów funkcji template typ1 wieksza(typ1 a, typ2 b) { return (a > b) ? a : b; } int main() { double a=3.5; int b=2; cout<<wieksza(a,b)<<endl; cout<<wieksza(b,a)<<endl; return 0; } 3.5 3

42 Konflikt template typ1 wieksza(typ1 a, typ2 b) { return (a > b) ? a : b; } template typ2 wieksza(typ1 a, typ2 b) { return (a > b) ? a : b; } Szablony różnią się tylko typem zwracanym

43 Obiekty lokalne typu typ template typ dzialanie(typ a, typ b) { typ w; w=3*a+b; return w; } int main() { int a=3; int b=2; cout<<dzialanie(a,b)<<endl; return 0; } 11

44 Typy pochodne template void zmiana(typ &a, typ &b) { typ c=a; a=b; b=c; } int main() { int a=3; int b=2; cout<<a<<b<<endl; zmiana(a,b); cout<<a<<b<<endl; return 0; } 32 23

45 Typy pochodne template void zmiana(typ &a, typ &b) { typ c=a; a=b; b=c; } int main() { char *a="AAA"; char *b="BBB"; cout<<a<<b<<endl; zmiana(a,b); cout<<a<<b<<endl; return 0; } AAABBB BBBAAA

46 Szablon generujący funkcje inline template inline typ wieksza(typ a, typ b) { return (a > b) ? a : b; }

47 Obiekty lokalne statyczne template void funkcja(typ a) { static int licznik=0; licznik++; cout<<licznik<<endl; } int main() { funkcja(1); funkcja(1.0); funkcja(5); funkcja('a'); return 0; } 11211121

48 Run-Time Type Identyfication #include using namespace std; template void funkcja(typ a) { cout<<typeid(a).name()<<endl; } int main() { funkcja(1); funkcja(1.0); funkcja(5); funkcja('a'); return 0; } int double int char

49 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 "Podstawy informatyki 2013/2014 Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi."

Podobne prezentacje


Reklamy Google