Techniki Programowania przeładowanie funkcji Łukasz Madej Katedra Informatyki Stosowanej i Modelowania Wykłady opracowane we współpracy z Danutą Szeligą, Łukaszem Sztangretem
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
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); double potega( int x, int y); I odwrotnie: nie przeładowywać deklaracji, jeśli nie potrzebujemy tej samej nazwy dla różnych działań
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
Różna liczba argunemtów 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"; napis(1); napis(1,2); napis(1,2,3);
Różne typy argumentów void napis(int a)cout<<"int\n"; void napis(double a)cout<<"double\n"; void napis(char a)cout<<"char\n"; napis(1); napis(1.5); napis('a'); napis(int (1.5));
Różna kolejność argumentów void napis(int a, double b)cout<<"int, double\n"; void napis(double b, int a)cout<<"double, int\n"; napis(1,1.5); napis(1.5,1);
Różne typy funkcji BŁĄD cout<<zrwoc(1.5); int zwroc(double a)return int(a); double zwroc(double a)return a; int a=zwroc(1.5); double b=zwroc(1.5);
typedef typedef int calkowity; void napis(int a)cout<<"int\n"; void napis(calkowity a)cout<<"calkowity\n"; int a=1; calkowity b=1; napis(a); napis(b); BŁĄD calkowity to inna nazwa int
enum enum litera a=1,b,c,d; void napis(int a)cout<<"int: "<<a<<endl"; void napis(litera l)cout<<"litera: <<l<<endl; litera l=d; int i=1; 4 napis(l); napis(i); 1 system("pause");
Tablica i wskaźnik void napis(int a[])cout<<"tablica\n"; void napis(int *a)cout<<"wkaznik\n"; int tab[]=1,2,3; napis(tab); BŁĄD int [] -> int * - trywialna konwersja
Tablice wielowymiarowe void napis(int a[2][3])cout<<"tablica 2x3\n"; void napis(int a[3][4])cout<<"tablica 3x4\n"; 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); tablica 2x3 napis(tab2); tablica 3x4
Tablice wielowymiarowe void napis(int a[2][3])cout<<"tablica 2x3\n"; void napis(int a[3][3])cout<<"tablica 3x3\n"; int tab1[2][3]=1,2,3,4,5,6; int tab2[3][3]=1,2,3,4,5,6,7,8,9; napis(tab1); napis(tab2); BŁĄD Pierwszy rozmiar tablicy nie jest brany pod uwagę int [][3]
Referencja void napis(int a)cout<<"wartosc\n"; void napis(int &a)cout<<"referencja\n"; int a=1; napis(a); BŁĄD Identyczne wywołanie funkcji
Typy: T, const T, volatile T 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 a=1; napis(a); BŁĄD const oraz volatile mówią kompilatorowi TYLKO jak traktować zmienną wewnątrz funkcji
Typy: T*, const T*, volatile T* 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 a=1; const int b=2; volatile int c=3; napis(&a); napis(&b); napis(&c); int* const int* voltaile int*
Wskaźnik do przeładowanej funkcji void napis(int a)cout<<"int\n"; void napis(double a)cout<<"double\n"; void napis(char a)cout<<"char\n"; void (*wsk1)(int)=napis; void (*wsk2)(double)=napis; void (*wsk3)(char)=napis; wsk1(1); wsk2(1.5); wsk3('a'); int double char
Konwersje kilku argumentów void f(double a, int b)cout<<"double, int\n"; void f(int a, double b)cout<<"int, double\n"; f(1,2.3); f(1.2,3); f(1,2); BŁĄD Obie konwersje są takie same
Zasłanianie nazw BŁĄD int i=1; cout << i << endl; int i=2; cout << i << endl; cout << ::i << endl; cout << i << endl; int i=3; cout << i << endl; cout << ::i << endl; cout << i << endl; cout << ::i << endl; //int i=4; system("pause"); 1 2 1 2 3 1 2 1
Co pojawi się na ekranie double promien; cout<<"podaj promień koła"<<endl; cin>>promien; //podajemy np. 1 oblicz_pole_kola(promien); system("pause"); void oblicz_pole_kola(double r) double pole; pole = 0.0; pole = 3.14*r*r; cout<<"obliczone pole kola to: "<<pole<<endl; Błąd brak deklaracji
void oblicz_pole_kola(double r); double promien, pole_kola; cout<<"podaj promień koła"<<endl; cin>>promien; //podajemy np. 1 pole_kola = oblicz_pole_kola(promien); cout<<"pole koła to: "<<pole_kola<<endl; system("pause"); void oblicz_pole_kola(double r) double pole; pole = 0.0; pole = 3.14*r*r; return pole; Błąd funkcja nic nie zwraca
int oblicz_pole_kola(double r); double promien, pole_kola; cout<<"podaj promień koła"<<endl; cin>>promien; //podajemy np. 1 pole_kola = oblicz_pole_kola(promien); cout<<"pole koła to: "<<pole_kola<<endl; system("pause"); int oblicz_pole_kola(double r) double pole; pole = 0.0; pole = 3.14*r*r; return pole; 3
void f(int x, double &y); int a=10; double b; b = 3.25; cout<<a<<" "<<b<<endl; f(a,b); cout<<a<<" "<<b<<endl; system("pause"); 10 3.25 10 6.25 void f(int x, double &y) x*=2; y +=3; cout<<x<<" "<<y<<endl; 20 6.25
Jeżeli wskaźnik pokazuje na element tablicy można użyć go zgodnie z notacją typową dla tablic: double tab[5] = -2,-1,0,1,2; double * ptr; ptr = &tab[0]; // lub: ptr = tab; for (int i = 0; i < 5; i++) cout << ptr[i] << ' ' << tab[i] << endl; -2,-1,0,1,2-2,-1,0,1,2
Wskaźnik taki można przesuwać po elementach tablicy: double tab[5] = -2,-1,0,1,2; ptr++; for (int i = 0; i < 4; i++) cout << *ptr << ' ' << tab[i] << endl; ptr++; -1,0,1,2-2,-1,0,1
int *fun() int *wsk=new int[5]; for (int i=0; i<5; i++) wsk[i]=i; return wsk; 0 1 2 3 4 int *w; w=fun(); for (int i=0; i<5; i++) cout << w[i] << endl; system("pause");
int tab[]=0,1,2,3,4; int *wsk1,*wsk2; wsk1=&tab[1]; wsk2=&tab[4]; cout << wsk2-wsk1 << endl; system("pause"); 3
int tab[5]=1,2,3,4,5; int *wsk; wsk=tab; for (int i=0;i<5;i++) cout<<*wsk<<"\t"<<wsk<<endl; wsk++;