Wzorce funkcji (szablony)

Podobne dokumenty
Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Programowanie i struktury danych

Język C++ wykład VIII

2. Klasy cz. 2 - Konstruktor kopiujący. Pola tworzone statycznie i dynamicznie - Funkcje zaprzyjaźnione - Składowe statyczne

Programowanie w C++ Wykład 12. Katarzyna Grzelak. 28 maja K.Grzelak (Wykład 12) Programowanie w C++ 1 / 27

Dla każdej operacji łącznie tworzenia danych i zapisu ich do pliku przeprowadzić pomiar czasu wykonania polecenia. Wyniki przedstawić w tabelce.

Programowanie w C++ Wykład 11. Katarzyna Grzelak. 13 maja K.Grzelak (Wykład 11) Programowanie w C++ 1 / 30

C-struktury wykład. Dorota Pylak

Programowanie obiektowe - Przykładowe zadania egzaminacyjne (2005/2006)

Szablony funkcji i klas (templates)

Szablony funkcji i szablony klas

C-struktury wykład. Dorota Pylak

Szablony klas, zastosowanie szablonów w programach

Zaawansowane programowanie w C++ (PCP)

Podstawy algorytmiki i programowania - wykład 5 C-struktury cd.

Wstęp do Programowania 2

Wprowadzenie do szablonów szablony funkcji

Wykład II. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Podstawy algorytmiki i programowania - wykład 4 C-struktury

Wprowadzenie do szablonów szablony funkcji

Aby uzyskać zaliczenie w pierwszym terminie (do 30 stycznia 2018) rozliczyć trzeba co najmniej 8 projektów, po 4 z każdej z części: C++ oraz Python.

Programowanie obiektowe

FUNKCJE WZORCOWE. Wykład 10. Programowanie Obiektowe (język C++) Funkcje wzorcowe wprowadzenie (2) Funkcje wzorcowe wprowadzenie (1)

STL: Lekcja 1&2. Filozofia STL

Wstęp do Programowania 2

Szablony. Szablony funkcji

Programowanie w języku C++

Podstawy programowania skrót z wykładów:

Zaawansowane programowanie w języku C++ Funkcje uogólnione - wzorce

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 15 kwietnia K.Grzelak (Wykład 8) Programowanie w C++ 1 / 33

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy INNE SPOSOBY INICJALIZACJI SKŁADOWYCH OBIEKTU

Programowanie obiektowe w C++ Wykład 12

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) {

Programowanie w C++ Wykład 9. Katarzyna Grzelak. 14 maja K.Grzelak (Wykład 9) Programowanie w C++ 1 / 30

Co nie powinno być umieszczane w plikach nagłówkowych:

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) {

Część 4 życie programu

Wstęp do programowania

Plik klasy. h deklaracje klas

typ y y p y z łoż o on o e n - tab a lice c e w iel e owym m ar a o r we, e stru r kt k ury

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

Pojemniki Pojemnik to obiekt, którego zadaniem jest przechowywanie innych obiektów.

Programowanie w C++ Wykład 12. Katarzyna Grzelak. 20 maja K.Grzelak (Wykład 12) Programowanie w C++ 1 / 32

W2 Wprowadzenie do klas C++ Klasa najważniejsze pojęcie C++. To jest mechanizm do tworzenia obiektów. Deklaracje klasy :

Programowanie w języku C++

Dzisiejszy wykład. Wzorce funkcji Wzorce klas Tablica asocjacyjna Składowe statyczne

Operatory na rzecz typu TString

Struktury Struktura polami struct struct struct struct

Abstrakcyjny typ danych

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 5. Karol Tarnowski A-1 p.

Szablon klasy std::vector

Projektowanie klas c.d. Projektowanie klas przykład

Dziedziczenie & W slajdach są materiały zapożyczone z

Kurs programowania. Wykład 2. Wojciech Macyna. 17 marca 2016

Programowanie obiektowe w języku C++ dr inż. Jarosław Forenc

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 16 kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 27

Programowanie w C++ Wykład 14. Katarzyna Grzelak. 3 czerwca K.Grzelak (Wykład 14) Programowanie w C++ 1 / 27

Materiał Typy zmiennych Instrukcje warunkowe Pętle Tablice statyczne Wskaźniki Tablice dynamiczne Referencje Funkcje

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

PARADYGMATY PROGRAMOWANIA Wykład 3

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) { zdefiniuje. Integer::operator=(ri);

Język C++ wykład VI. uzupełnienie notatek: dr Jerzy Białkowski. Programowanie C/C++ Język C++ wykład VI. dr Jarosław Mederski.

W przypadku STL w specyfikacji nazwy pliku nagłówkowego brak rozszerzenia tj. <string> <string.h> zamiast

Programowanie w C++ Wykład 6. Katarzyna Grzelak. kwiecień K.Grzelak (Wykład 6) Programowanie w C++ 1 / 40

DYNAMICZNE PRZYDZIELANIE PAMIECI

Podstawy języka C++ Maciej Trzebiński. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. Praktyki studenckie na LHC IVedycja,2016r.

Zajęcia nr 5 Algorytmy i wskaźniki. dr inż. Łukasz Graczykowski mgr inż. Leszek Kosarzewski Wydział Fizyki Politechniki Warszawskiej

wykład IV uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C, a C++. wykład IV dr Jarosław Mederski Spis Język C++ - wstęp

Biblioteka standardowa C++

Programowanie - wykład 4

Jzyk C++ cz 3. Jarosław Gramacki Instytut Informatyki i Elektroniki ( $)*)+' *, - ( ' )*'.' '',*/ *, ','*0) 1 / ) %*+ 2'' 2" ( $%%) )'20 )*0) 1 / )

Podstawy informatyki. Informatyka stosowana - studia niestacjonarne. Grzegorz Smyk. Wydział Inżynierii Metali i Informatyki Przemysłowej

Do czego służą klasy?

KLASY cz4. Dorota Pylak. destruktory składowe statyczne przeciążanie operatorów. wskaźniki

Zaawansowane programowanie w języku C++ Biblioteka standardowa

TEMAT : KLASY DZIEDZICZENIE

Operacje wejścia/wyjścia odsłona pierwsza

Programowanie w C++ Wykład 7. Katarzyna Grzelak. 23 kwietnia K.Grzelak (Wykład 7) Programowanie w C++ 1 / 40

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

Programowanie w C++ Wykład 6. Katarzyna Grzelak. 1 kwietnia K.Grzelak (Wykład 6) Programowanie w C++ 1 / 43

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

Podstawy Programowania Obiektowego

Programowanie w językach

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 4 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 44

Jak Windows zarządza pamięcią?

Wykład I. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy INNE SPOSOBY INICJALIZACJI SKŁADOWYCH OBIEKTU

Pliki wykład 2. Dorota Pylak

TEMAT : KLASY POLIMORFIZM

Tablice. Monika Wrzosek (IM UG) Podstawy Programowania 96 / 119

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie?

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 5 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 41

Algorytmy i Struktury Danych.

Strona główna. Strona tytułowa. Programowanie. Spis treści. Sobera Jolanta Strona 1 z 26. Powrót. Full Screen. Zamknij.

I - Microsoft Visual Studio C++

Stos liczb całkowitych

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 7 maja K.Grzelak (Wykład 8) Programowanie w C++ 1 / 31

obiekty funkcyjne - funktory

Transkrypt:

Wzorce funkcji (szablony) Wzorce funkcji (ang. function template) dają możliwość wielokrotnego wykorzystywania tego samego kodu funkcji dla różnych typów danych. Załóżmy, że chcemy zdefiniować funkcję min(), która wybiera mniejszą z dwóch liczb całkowitych lub rzeczywistych. a) Podejście tradycyjne: tworzymy dwie funkcje int min(int a, int b) if (a<b) return a; else return b; double min(double a, double b) if (a<b) return a; else return b; b) Zastosowanie wzorca funkcji: tworzymy jeden kod, z którego kompilator generuje potrzebne funkcje: template <class T> T min(t a, T b) if (a<b) return a; // return a < b? a : b; else return b; Kompilator na podstawie typów dostarczonych w wywołaniu funkcji generuje oddzielny kod do obsługi każdego wywołania wzorzec T min(t,t) programista pisze wzorzec funkcji funkcja wzorcowa int min(int,int) funkcja wzorcowa double min(double,double) funkcja wzorcowa Ulamek min(ulamek,ulamek) Analiza nagłówka wzorca min: słowa kluczowe template <class T> T min(t a, T b) nazwa zastępcza typu danych używana w definicji wzorca, zawsze musi być poprzedzona słowem class Nazwa zastępcza typu danych jest używana w definicji funkcji jako typ danych, kompilator zastąpi ją nazwą rzeczywistego typu danych podczas tworzenia określonej wersji funkcji. Uwaga: standard C++ wprowadza nowe słowo kluczowe typename: template <typename T> T min(t a, T b) które lepiej oddaje znaczenie tej konstrukcji. Jak to działa: wywołanie funkcji min() z aktualną listą parametrów powoduje wygenerowanie funkcji, w której typy wzorca zostaną zastąpione typami aktualnymi, czyli zostanie wygenerowana odpowiednia wersja funkcji int min(int, int) lub double min(double, double). Przykład użycia wzorca: int main() int i=2, j=5 ; double x=1.5, y=2.3 ; cout << "min(i,j) = "<< min(i,j) <<"\n" ; // int min(int, int) cout << "min(x,y) = "<< min(x,y) <<"\n" ; // double min (double, double) Pytanie: czy możemy użyć ten wzorzec dla napisów, na przykład: char *wsk1="piotr", *wsk2="adam"; cout << "min(wsk1,wsk2) = " << min(wsk1,wsk2) <<endl; 1

Wzorce klas Wzorce klas (szablony, ang. templates) pozwalają realizować zależne od typu danych wersje klas ogólnych. Pojęcia: konkretyzacja (ang. instantiation) - przysposobienie klasy do przechowywania konkretnych obiektów parametry typów (ang. type parameters) - ogólne identyfikatory typów wykozrystane do definicji wzorca Przykład definicji klasy Punkt: class Punkt int x; int y; public: Punkt(int xx=0, int yy=0) x = xx ; y = yy ; void DrukujWsp();... ; void Punkt::Drukuj() cout << "Wspolrzedne : " << x << " " << y << endl ; Chcemy tę definicję uogólnić, tak aby współrzędne mogły być różnych typów: template <class T> class Punkt T x ; T y ; public : Punkt (T xx=0, T yy=0) // definicja funkcji inline x = xx ; y = yy ; void Drukuj(); // funkcja zdefiniowana na zewnątrz klasy ; template <class T> void Punkt<T>::Drukuj() cout << "Wspolrzedne : " << x << " " << y << endl ; Przykład funkcji testującej: int main () // deklaracja obiektu parametryzowanej klasy Punkt<int> ai(3, 5); Punkt<double> ad(3.5, 2.3) ; ai.drukuj(); ad.drukuj(); 2

Przykład - klasa vector Klasa vector pozwala przechowywać obiekty różnych typów, nazywana jest kontenerem (ang. container class w języku polskim spotyka się tłumaczenia kolekcja, kontener, zasobnik) : vector <int> a; // wektor pusty elementów typu int vector <double> b(2); // wektor o 2 elementach typu double vector <string> c(5); // wektor o 5 elementach typu string Stanowi alternatywę dla tablicy, typu wbudowanego w język C++: int tab1[10]; // tablica wbudowana vector<int> tab2(10); // tablica jako wektor o określonej długości Korzystanie z klasy vector wymaga dołączenia pliku nagłówkowego: i przestrzeni nazw std. Przykład: przygotowujemy książkę telefoniczną // wersja a) "tradycyjna" z tablicą wbudowaną: struct Pozycja string nazwisko; int numer; ; Pozycja ksiazka_tel[1000]; void drukuj_pozycje(int i) cout << ksiazka_tel[i].nazwisko <<' ' << ksiazka_tel[i].numer <<endl; Wada: tablica wbudowana ma stały rozmiar // wersja b) z wykorzystaniem klasy vector struct Pozycja string nazwisko; int numer; ; <vector> Pozycja ksiazka_tel(1000); // wektor o 1000 elementów void drukuj_pozycje(int i) // korzysta się tak samo jak z tablicy cout << ksiazka_tel[i].nazwisko <<' ' << ksiazka_tel[i].numer <<endl; // zwiększenie rozmiaru o n: funkcja resize() void dodaj_pozycje(int n) ksiazka_tel.resize(ksiazka_tel.size()+ n); 3

Wstawianie wartości do wektora // metoda 1: za pomocą funkcji push_back() vector<int> v; // pusty wektor o elementach typu int for (int i=0 ; i<10; i++) v.push_back(i); // dodaj na końcu wektora wartość i vector<string> s; string tekst; while ( cin >> tekst) s.push_back(tekst); // pusty wektor o elementach typu string // dodaj na końcu wektora napis vector<int> v1; int t[4]=1,2,3,4; for (int i=0;i<4; ++i) v1.push_back(tab[i)); // metoda 2: vector<int> v0 ; // wektor pusty int t[4]=1,2,3,4; vector<int> v1(4, 99) ; // wektor o 4 elementach typu int o wartości 99 vector<int> v2(7, 0) ; // wektor o 7 elementach typu int o wartości 0 vector<int> v3(t, t+2) ; // wektor zbudowany z tablicy t: // pierwsze 2 elementów vector<int> v4(v1); // inicjalizacja innym wektorem Działania na wektorach for (i=0 ; i<v1.size(); i++) // dostęp do elementów wektora cout << v[i] << " " ; cout << "\n"; for (i=0 ; i<v2.size(); i++) // dostęp do elementów wektora v2[i] = i*i ; v1.push_back(99) ; // dodanie elementu na końcu v2.pop_back() ; // usunięcie elementu z końca v3 = v2 ; // przypisywanie wektorów v1.assign (t+1, t+3) ; // przypisywanie wartości wektorowi v1: // od elementu t[1] do elementu t[3] 4

W jaki sposób wektor rośnie? Aby samemu zmieniać rozmiar wektora dynamicznie trzeba: przydzielić nową, większą pamięć, skopiować poprzednią zawartość pamięci w nowe miejsce, zwolnić poprzednią, niepotrzebną już pamięć, jeśli elementy są obiektami typu klasy, trzeba zdefiniować i użyć odpowiednie konstruktory i destruktory Jak jest to realizowane w klasie vector? Rezygnuje się ze zwiększania wektora przy każdym wstawianiu. Jeżeli wektor musi się zwiększyć, jest on zwiększany nadmiarowo, tak, że będzie można wstawić wiele elementów bez potrzeby przydzielania pamięci. Ile wynosi nadmiar, zależy od implementacji. Dla różnych typów mogą to być różne wartości. Dla każdego wektora definiowany jest więc: rozmiar (ang. size) - ilość elementów wektora, pojemność (ang. capacity) - liczba elementów, które trzeba wstawić, zanim zwiększy się przydział pamięci. Przykład: class Punkt int x,y; ; int main() vector<int> x; cout << "x: rozmiar= " << x.size() << " pojemosc= " << x.capacity() << endl; for (int i=0; i<300; ++i) x.push_back(i); cout << "x: rozmiar= " << x.size() << " pojemosc= " << x.capacity() << endl; Wyniki (g++ Linux): x: rozmiar= 0 pojemnosc= 0 x: rozmiar= 1 pojemnosc= 1 x: rozmiar= 2 pojemnosc= 2... x: rozmiar= 8 pojemnosc= 8 x: rozmiar= 9 pojemnosc= 16 // podwojenie... x: rozmiar=16...pojemnosc= 16 x: rozmiar=17...pojemnosc= 32... x: rozmiar= 300 pojemnosc= 512 5

Przykład: drukowanie składowych wektora rozdzielanych spacją using namespace std ; void drukuj(vector<int> &); int main() int t[] = 1,2,3,4,5,6,7,8,9,10 ; vector<int> v(t,t+10); drukuj(v); return 0; void drukuj(vector<int> &v) cout << '' ; for (int i=0 ; i<v.size(); i++) // dostęp do elementów wektora cout << v[i] << ' ' ; cout << '' << endl; To samo z przeciążaniem operatora wyjścia, składowe rozdzielane przecinkiem using namespace std ; ostream &operator<<(ostream &,const vector<int> &); int main() int t[] = 1,2,3,4,5,6,7,8,9,10 ; vector<int> v(t,t+10); cout << v << endl; return 0; ostream &operator<<(ostream &S, const vector<int> &v) S<<''; for(int i=0;i<v.size();i++) if(i) S <<','; S <<v[i]; S <<''; return S; 6

Przykład: wczytanie pliku do wektora; każdy element wektora zawiera jeden wiersz tekstu #include <string> #include <fstream> int main() vector<string> v; ifstream we("plik.txt"); string wiersz; while(getline(we, wiersz, '\n')) v.push_back(wiersz); for (int i=0; i<v.size(); i++) cout << i << ": " << v[i] << endl; Przykład: wczytanie pliku do wektora, każdy element wektora zawiera pojedynczy wyraz #include <string> #include <fstream> int main() vector<string> v; ifstream we("plik.txt"); string wyraz; while(we >> wyraz) v.push_back(wyraz); for (int i=0; i<v.size(); i++) cout << i << ": " << v[i] << endl; Wyświetl plik tekstowy wierszami od końca, numeruj wiersze #include <string> #include <fstream> int main() vector<string> v; ifstream we("plik.txt"); string wiersz; while(getline(we, wiersz, '\n')) v.push_back(wiersz); int licznik = v.size(); for(int i = 0; i < licznik; i++) int nrwiersza = licznik-i-1; cout << nrwiersza << ": " << v[nrwiersza] << endl; 7

Wyświetl plik tekstowy wyraz po wyrazie (wyrazy są oddzielane spacjami) #include <string> #include <fstream> int main() vector<string> v; ifstream we("plik.txt"); string slowo; while(we>>slowo) v.push_back(slowo); int licznik = v.size(); for(int i = 0; i < licznik; i++) cout << v[i] << endl; Przykład: wyszukiwanie binarne, gdy tablica jest zdefiniowana jako obiekt klasy. const int nieznaleziono=-1; int binszukaj(const vector<int> &t, int x) int dolnagranica=0; int gornagranica=t.size()-1; while (dolnagranica <= gornagranica) int aktind = (dolnagranica + gornagranica)/2; if (x==t[aktind]) return aktind; if (x<t[aktind]) gornagranica=aktind-1; else dolnagranica=aktind+1; return nieznaleziono; 8