Innehåll. Parametriserade typer. Klassmallar. Klassmallen Vektor Konstructor med std::initializer_list. Klassmallen Vektor Medlemsfunktioner

Relevanta dokument
Innehåll. 1 Funktionsmalllar. 2 Klassmallar. struct Name { string s; //... }; const Name & minimum ( const Name & a, const Name & b) { if(a.s < b.

Programmering i C++ EDA623 Mallar. EDA623 (Föreläsning 12) HT / 29

Innehåll. Exceptionella händelser (exceptions, undantag ) Felhantering Tre nivåer av felhantering: Nivå 2: exceptions (eller returvärde)

Innehåll. 1 Funktionsmallar. 2 Pekare och konstanter. 3 Typomvandlingar. struct Name { string s; //... };

Innehåll. Pekaren this Självreferens. Klasser Resurshantering, representation. Överlagring av operatorer. Överlagring av operatorer

Tentamen EDAF30 Programmering i C++

Innehåll. Typomvandlingar (casting) Implicita Typomvandlingar. Typomvandlingar (type casts) Explicita, namngivna typomvandlingar (C++-11)

Innehåll. Pekare Exempel

Innehåll. Pekare Exempel

Innehåll. 1 Kort om dynamisk polymorfism. 2 Arv i C++ 3 Multipelt arv. 4 Något om statisk polymorfism. class Container {

Innehåll. Resurshantering. Resource handles. Minnesallokering. Minnesallokering Exempel: allokering på stacken. 6. Resurshantering

Tentamen EDAF30 Programmering i C++

Tentamen EDAF30 Programmering i C++

Innehåll. Pekare. Datatyper Pekare, Arrayer och Referenser. Pekare Syntax. Pekare Syntax, operatorer. 4. Standard-containers. Pekare och arrayer

Programmering i C++ EDAF30 Dynamiska datastrukturer. EDAF30 (Föreläsning 11) HT / 34

2D1387, Programsystemkonstruktion med C++ 01/02 1

Programmering i C++ EDA623 Dynamiska datastrukturer. EDA623 (Föreläsning 11) HT / 31

Innehåll. Användardefinierade typer. Användardefinierade typer Kategorier. Konstruktorer. Konstruktorer Två sätt att skriva initiering av medlemmar

Innehåll. Typomvandlingar (casting) Implicita Typomvandlingar. Typomvandlingar (casting) Implicita Typomvandlingar

Innehåll. Konstruktorer vid arv Regler för basklassens konstruktor. Konstruktorer vid arv. Konstruktorer vid arv. Konstruktorer vid arv

Innehåll. Resource handles. Resurshantering. Minnesallokering. Minnesallokering Exempel: allokering på stacken. 7. Resurshantering, Felhantering

Tommy Färnqvist, IDA, Linköpings universitet

TDIU01 Programmering i C++

Innehåll. Klasserna vector och deque

Inlämningsuppgift, EDAF30, 2016

Programsystemkonstruktion med C++: Övning 2. Karl Palmskog september 2010

Innehåll. 1 volatile. 2 Kuriositeter. 3 Klasser och arv. 4 Råd och tumregler. 5 Mer om standard-containers. Trigraphs

Tillämpad programmering

Inlämningsuppgift, EDAF30, 2018

Föreläsning Datastrukturer (DAT036)

TDDC76 - Programmering och Datastrukturer

Del3 Klassanvändning, operatorer och pekare Ämnesområden denna föreläsning:

Tentamen *:85/2I4123 C

Innehåll. EDAf30: Programmering i C++, 7.5 hp. EDAf30: Programmering i C++, 7.5 hp Viktiga skillnader mot Java

Operatoröverlagring. endast operatorsymboler definierade i C++ kan överlagras = += -= *= /= %= ^= &= = <<= >>= < > <= >= ==!= && > ->*, [ ] ( )

Intro till standardbiblioteket. Eric Elfving

Föreläsning 7 Innehåll. Rekursion. Rekursiv problemlösning. Rekursiv problemlösning Mönster för rekursiv algoritm. Rekursion. Rekursivt tänkande:

Objektorientering - Arv och polymorfi. Eric Elfving Institutionen för datavetenskap

Programmering i C++ EDA623 Mer om klasser. EDA623 (Föreläsning 6) HT / 26

DD2387 Programsystemkonstruktion med C++ Tentamen 2

Generell (template) programmering. Effektiv C++ Slutliga tips Genomgång av gammal tenta. Daniel Aarno Allt som fungerar som x ÄR x

Algoritmer och datastrukturer 2012, föreläsning 6

Innehåll. 1 Deklarationer, scope och livstid. 2 Användardefinierade typer. 4 In- och utmatning. 5 Operatoröverlagring. 6 namnrymder (namespace)

TDIU01 - Programmering i C++, grundkurs

TDIU20 - Objektorienterad programmering i c++ - föreläsning 4

Tentamen EDAF30 Programmering i C++

Lektionsuppgifter. TDDI14 Objektorienterad programmering. Lektionsplanering Lektion Lektion Lektion

Innehåll. 1 Deklarationer, scope och livstid. 2 Användardefinierade typer. 4 Operatoröverlagring. 5 In- och utmatning. 6 namnrymder (namespace)

Algoritmbiblioteket (STL) Designstrategi Generiska algoritmer som fungerar på godtyckliga samlingsdatatyper, vilka har iteratorer.

Tentamen i TDP004 Objektorienterad Programmering Lösningsförslag

TDIU01 - Programmering i C++, grundkurs

Innehåll. Introduktion till objektorientering. OOP (objektorienterad programmering) Objekt, instanser, klasser

Tillämpad programmering

Datastrukturer i kursen. Föreläsning 8 Innehåll. Träd rekursiv definition. Träd

Föreläsning 9 Innehåll

Föreläsning 9 Datastrukturer (DAT037)

TDIU01 - Programmering i C++, grundkurs

Föreläsning 10 Innehåll. Diskutera. Inordertraversering av binära sökträd. Binära sökträd Definition

Inlämningsuppgiften. Föreläsning 9 Innehåll. Träd. Datastrukturer i kursen

DD2387 Programsystemkonstruktion med C++ Tentamen 1 Torsdag 7 januari 2016, 14:00-18:00

Övriga byggstenar. Övriga byggstenar. Några tips under programutveckling. Beroenden Pekare till funktioner Typkonvertering

Föreläsning 10 Innehåll

Föreläsning 11 Innehåll. Diskutera. Binära sökträd Definition. Inordertraversering av binära sökträd

Abstrakta datatyper. Primitiva vektorer. Deklarera en vektor

6 Rekursion. 6.1 Rekursionens fyra principer. 6.2 Några vanliga användningsområden för rekursion. Problem löses genom:

Programmering i C++ EDA623 Objektorienterad programutveckling. EDA623 (Föreläsning 5) HT / 33

EDAf30: Programmering i C++, 7.5 hp. EDAf30: Programmering i C++, 7.5 hp Administration. EDAf30: Programmering i C++, 7.5 hp Obligatoriska moment

Introduktion till arv

DD2387 Programsystemkonstruktion med C++ Tentamen 3 Onsdagen 7 januari, 14:00-18:00

Tentamen, Algoritmer och datastrukturer

Generiska konstruktioner. Kursbokens kapitel 13

Kapitel 4 - Mallar. Kapitel 4. Introduktion till mallar STL. 2D1387 Programsystemkonstruktion med C++ 1

Kapitel 4. Funktionsmallar. Mallar. Introduktion till mallar STL

Kapitel 4. Funktionsmallar. Mallar. Introduktion till mallar STL

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 9 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Programmering i C++ EDA623 Arv. EDA623 (Föreläsning 6) HT / 42

Innehåll. 1 Typdeklarationer och typomvandling 2 Resurshantering. 3 Objektorientering, kort repetition. 4 Klasser

Tentamen EDAF30 Programmering i C++

TDDC76 - Programmering och Datastrukturer

Klassen BST som definierar binära sökträd med tal som nycklar och enda data. Varje nyckel är unik dvs förekommer endast en

Föreläsning 9 Innehåll

Tentamen i Algoritmer & Datastrukturer i Java

Tentamen Programmeringsteknik II Inledning. Anmälningskod:

Programmering i C++ EDA623 Containerklasser och algoritmbibliotek. EDA623 (Föreläsning 10) HT / 33

Lägg uppgifterna i ordning. Skriv uppgiftsnummer och din kod överst i högra hörnet på alla papper.

TDDC76 - Programmering och Datastrukturer

Innehåll. Datatyper Pekare, Arrayer och Referenser. Pekare. Pekare Syntax. Pekare Syntax, operatorerna * och & 5. Pekare och arrayer. Algoritmer.

DAT043 - föreläsning 8

Tentamen C++-programmering

Tentamen i TDP004 Objektorienterad Programmering Teoretisk del

Trädtraversering. Binärt träd. Trädtraversering djupet-först. Trädtraversering bredden-först

Tentamen i TDP004 Objektorienterad Programmering Lösningsförslag

TDDC74 Programmering: Abstraktion och modellering Datortenta , kl 14-18

Tentamen Datastrukturer (DAT036/DAT037/DIT960)

Det finns många flaggor till g++,

Övningsuppgifter. TDIU04 Programmering i C++, standardbibliotek. Innehåll. Vt Lektion Lektion Lektion Lektion 4...

13 Prioritetsköer, heapar

Lägg uppgifterna i ordning. Skriv uppgiftsnummer och din kod överst i högra hörnet på alla papper.

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 4 Erik Nilsson, Institutionen för Datavetenskap, LiU

Att deklarera och att använda variabler. Föreläsning 10. Synlighetsregler (2) Synlighetsregler (1)

Transkript:

Innehåll EDAF30 Programmering i C++ 10. Generisk programmering. Mallar och funktionsobjekt Sven Gestegård Robertz Datavetenskap, LTH 2017 1 Funktionsobjekt Mallar med variabelt antal argument 10. Generisk programmering. Mallar och funktionsobjekt 2/1 Parametriserade typer Containerklasserna vector, deque och list utgör exempel på klasser med typparametrisering eller klassmallar Kompilatorn genererar utgående från en sådan klassmall alla olika typer av klasser som behövs beroende på aktuell typ insatt som typparameter Slipper manuellt skriva en ny klass för varje enskild komponentdatatyp för att implementera en viss sammansatt datastruktur Klasser kan parametriseras Exempel: container-klasser i standardbiblioteket std::vector std::deque std::list Container är ett generellt begrepp, oberoende av element-typen : 10. Generisk programmering. Mallar och funktionsobjekt 3/37 Generalisera Vektor av doubles till Vektor av vad-som-helst. Klassmall med element-typ som mall-parameter Exempel: class Vektor T* elem ; int sz; explicit Vektor ( int s); ~ Vektor () delete [] elem ; ; // copy och move... T& operator []( int i); const T& operator []( int i) const ; int size () const return sz ; : 10. Generisk programmering. Mallar och funktionsobjekt 4/37 Klassmallen Vektor Medlemsfunktioner Invariant: sz >= 0 (NB! deklarerad int sz, inte unsigned sz) elem pekar på en T[sz]; Vektor <T>:: Vektor (int s) if(s < 0) throw invalid_argument (" Negative size "); sz = s; elem = new T[sz ]; ; const T& Vektor <T>:: operator []( int i) const if(i < 0 size () <= i) throw range_error (" Vektor :: operator []"); return elem [i]; T& Vektor <T>:: operator []( int i) const auto & constme = * this ; return const_cast <T&>( constme [i ]); : 10. Generisk programmering. Mallar och funktionsobjekt 5/37 Klassmallen Vektor Konstructor med std::initializer_list Vi vill kunna initera vektorer enkelt: Vektor <int > vs 1,3,5,7,9; Vektor <T>:: Vektor ( initializer_list <T> l) :Vektor <T>( static_cast <int >(l.size ())) int pos 0; for ( const auto & e : l) elem [pos ++] = e; static_cast<int> behövs eftersom std::initializer_list<t>::size() returnerar en unsigned typ : 10. Generisk programmering. Mallar och funktionsobjekt 6/37

Mall-parametrar Typer eller värden template <typename T, int N> struct Buffer using value_type = T; constexpr int size () return N; T buf [N]; ; Buffer: som en array, som känner till sin storlek Inget overhead för heap-allokering mall-parametrar måste vara constexpr kan inte ha variabel storlek jfr std::array Storleken som värde-parameter till mallen Ett alias (value_type) och en constexpr-funktion (size()) Användare kan komma åt (läsa) mall-parametrarna : 10. Generisk programmering. Mallar och funktionsobjekt 7/37 Mall-parametrar och alias Alla standard-containers har alias value_type class Container using value_type = T;... ; template <typename Cont > typename Cont :: value_type & get_first (Cont & t) return t [0]; void example () Vektor <int > v2,4,3,5,4,6; cout << " first element of v is " << get_first (v) << endl ; Här behöver typename anges för att kompilatorn ska veta att namnet value_type är en typ innan den instantierat mallen : 10. Generisk programmering. Mallar och funktionsobjekt 8/37 Alias Binda parametrar Container från f8 Man kan använda using för att skapa alias för typer using size_t = unsigned int ; inklusive mallar using IntVektor = Vektor <int >; class Container virtual int size () const =0; virtual int& operator []( int o) =0; virtual ~ Container () virtual void print () const =0; ; class Vektor : public Container explicit Vektor ( int l); ~ Vektor (); int size () const override ; int & operator []( int i) override ; virtual void print () const override ; int *p; int sz; ; generalisera till godtycklig elementtyp : 10. Generisk programmering. Mallar och funktionsobjekt 9/37 : 10. Generisk programmering. Mallar och funktionsobjekt 10/37 Parametriserad Container och Vektor Definition av medlemsfunktioner class Container using value_type = T; virtual size_t size () const =0; virtual T& operator []( size_t o) =0; virtual ~ Container () virtual void print () const =0; ; class Vektor : public Container <T> Vektor ( size_t l = 0) :pnew T[l],szl ~ Vektor () delete [] p; size_t size () const override return sz ; T& operator []( size_t i) override return p[i ]; virtual void print () const override ; T *p; size_t sz; ; : 10. Generisk programmering. Mallar och funktionsobjekt 11/37 void Vektor <T>:: print () const for ( size_t i = 0; i!= sz; ++i) cout << p[i] << " "; Medlemsfunktioner i en klassmall är funktionsmallar print() fungerar för alla typer som har operator<< Duck typing : if it walks like a duck and quacks like a duck, it is a duck : 10. Generisk programmering. Mallar och funktionsobjekt 12/37

Kompilering av mallar Typkontrollen vid kompilering av en mall tittar på användningen av argumenten användningen, i definitionen av mallen... i stället för mot en typ i deklarationen (som för vanliga funktioner) skillnad mot den vanliga varianten, där typen (klassen) styr vad en operation betyder görs vid kompilering i C++ Kompilatorn måste se definitionen av mallen där den används Hela mallen måste ligga i header-filen Jämför med dynamiska språk som Python : 10. Generisk programmering. Mallar och funktionsobjekt 13/37 Definition av medlemsfunktioner void Vektor <T>:: print () const for ( size_t i = 0; i!= sz; ++i) cout << p[i] << " "; Specialisering av mallen för typen Foo: (medlemmar i en klassmall är mallar) template <> void Vektor <Foo >:: print () const for ( size_t i = 0; i!= sz; ++i) cout << "Foo(" <<p[i].x << ") "; Fungerar för alla typer som har operator<< men inte för element av typ struct Foo int x; ; Foo(int d=0) :xd : 10. Generisk programmering. Mallar och funktionsobjekt 14/37 Specialsering av mallar Funktionsobjekt Exempel kan specialiseras fullständigt partiellt Funktionsmallar kan specialiseras fullständigt men överlagring är alltid att föredra template < typename T> class Less_than const T val; Less_than ( const T& v) :valv bool operator ()( const T& x) return x < val ; ; void use_less_than () Less_than <int > lt5 5; Vektor <int > v1,7,6,2,8; for ( auto x : v) cout << x << " < 5:" << boolalpha << lt5(x) << endl ; : 10. Generisk programmering. Mallar och funktionsobjekt 15/37 : Funktionsobjekt 10. Generisk programmering. Mallar och funktionsobjekt 16/37 Funktionsobjekt Exempel Iteratorer Med en funktionsmall: template < typename C, typename P> int count_if ( const C& c, P pred ) int res 0; for ( const auto & x : c) if( pred (x)) ++ res ; return res ; kan vi använda vårt funktionsobjekt: void use_functors () Less_than <int > lt5 5; Vektor <int > v1,7,6,2,8; För att kunna använda vår Vektor<T> med range-for och standard-algoritmer behövs funktionerna begin() och end() const T* begin ( const Vektor <T> &v) T* begin (Vektor <T> &v) const T* end(const Vektor <T>& v) T* end(vektor <T>& v) cout << " count numbers < 5: " << count_if (v,lt5 ) << endl ; : Funktionsobjekt 10. Generisk programmering. Mallar och funktionsobjekt 17/37 : Funktionsobjekt 10. Generisk programmering. Mallar och funktionsobjekt 18/37

Iteratorer const-versionerna Iteratorer icke-const-versionerna För att kunna använda vår Vektor<T> med range-for och standard-algoritmer behövs funktionerna begin() och end() Const-versionerna const T* begin ( const Vektor <T> &v) return v. size ()? &v [0] : nullptr ; const T* end ( const Vektor <T>& v) return begin (v)+v. size (); Undvik kod-duplicering Använd const-versionerna Användningsexempel för const_cast icke-const-versionerna T* begin (Vektor <T> &v) return const_cast <T*>( begin (static_cast <const Vektor <T>&>(v ))); T* end(vektor <T>& v) return const_cast <T*>( end(static_cast <const Vektor <T>& >(v ))); : Funktionsobjekt 10. Generisk programmering. Mallar och funktionsobjekt 19/37 : Funktionsobjekt 10. Generisk programmering. Mallar och funktionsobjekt 20/37 Förklaring icke-const-versionerna Variadic templates En funktionsmall kan ha variabelt antal argument T* begin ( Container <T> &v) return const_cast <T*>( begin (static_cast <const Container <T>&>(v))); kan även skrivas T* begin ( Container <T> &v) const Container <T>& cv= v; skapa const-referens const T* cbegin = begin (cv ); returvärdet är const-pekare return const_cast <T*>( cbegin ); gör om till icke-const-pekare void println () basfall: inga argument template <typename T, typename... Tail > void println (T head, Tail... tail ) cout << head << " "; Skriv första elementet println ( tail...); rekursion: skriv ut resten void test_variadic () string a"hej"; int b 10; double c 17.42; long d 100; NB! Anropar const-versionen från icke-const-versionen. Aldrig åt andra hållet. println (a,b,c,d); : Funktionsobjekt 10. Generisk programmering. Mallar och funktionsobjekt 21/37 : Mallar med variabelt antal argument 10. Generisk programmering. Mallar och funktionsobjekt 22/37 Mallar, kommentarer Träd Mallar har parametrar typ-parametrar: deklareras med class eller typename värde-parametrar: deklareras som vanligt, t ex int N Kompilatorn behöver hela mallen för att kunna instansiera den den ska ligga i header-filen (om andra ska inkludera den) Överlagring: Funktioner kan överlagras funktionsmallar kan överlagras Klasser kan inte överlagras klassmallar kan inte överlagras Specialisering: kan specialiseras partiellt eller fullständigt Funktionsmallar kan bara specialiseras fullständigt, men Specialiseringar överlagras inte Ofta bättre/tydligare att överlagra med en vanlig funktion (inte mall) än att specialisera Binärt sökträd: Alla noder i vänstra delträdet har mindre nyckelvärden än roten och alla noder i högra har större värden : Mallar med variabelt antal argument 10. Generisk programmering. Mallar och funktionsobjekt 23/37 : 10. Generisk programmering. Mallar och funktionsobjekt 24/37

Träd Egenskap hos binära sökträd: Utskrift i inorder ger värdena i växande ordning (sorterat) 3 4 7 9 11 12 13 16 17 19 21 Sökning efter visst värde Nod * find ( Nod * root, int value ) if ( root == nullptr ) return nullptr ; else if ( value == root ->data ) return root ; else if ( value < root ->data ) return find (root ->left, value ); else return find (root ->right, value ); class Tree Tree () : root ( nullptr ) Tree (D d) : root new Node (d ) ~ Tree () delete root ; bool empty () const return root == nullptr ; D& value () const check (); return root ->data ; Tree & l_child () const check (); return root ->left ; Tree & r_child () const check (); return root ->right ; void insert (D d); D* find (D d); class Node... Node * root ; void check () const if( empty ()) throw range_error (" Empty tree "); ; Node som inre klass : 10. Generisk programmering. Mallar och funktionsobjekt 25/37 : 10. Generisk programmering. Mallar och funktionsobjekt 26/37 Nodklassen som inre klass Medlemsfunktioner i en klassmall är funktionsmallar class Tree //... class Node friend class Tree <D>; D data ; Tree <D> left ; Tree <D> right ; Node (D d) : data d ~ Node () ; ; void Tree <D>:: insert (D d) if( empty ()) root = new Node (d); else if( d< value ()) l_child (). insert (d); else r_child (). insert (d); D* Tree <D>:: find (D d) if( empty ()) return nullptr ; else if(d== value ()) return & value (); else if(d < value ()) return l_child (). find (d); else return r_child (). find (d); : 10. Generisk programmering. Mallar och funktionsobjekt 27/37 : 10. Generisk programmering. Mallar och funktionsobjekt 28/37 Användning: Ett träd med heltal void test_tree () Tree <int > t; t. insert (17); t. insert (11); t. insert (22); t. insert (19); try_find (t,22); try_find (t,19); try_find (t,23); 22 found 19 found 23 not found Hjälpfunktion: void try_find (Tree <T>& t, const T& v) auto res = t. find (v); if(res ) cout << * res << " found \n"; else cout << v << " not found \n"; Använda trädet för Person-objekt struct Person string pnr; string name ; Person ( string pn, string n) :pnrpn,name n ; Tree <Person > ps; ps. insert ( Person ("121110-1516 ", "Kalle ")); test_templates.cc: In instantiation of void Tree <D>:: insert (D) [ with D = Person ] : test_templates.cc 699 col 45 required from here test_templates.cc 606 col 16 error no match for operator < ( operand types are Person and Person ) else if( d<value ())...... : 10. Generisk programmering. Mallar och funktionsobjekt 29/37 : 10. Generisk programmering. Mallar och funktionsobjekt 30/37

Lösning: använd egenskapsklass för att ge jämförelseoperationerna Lägg till en typparameter till trädmallen template <class D, class E> class Tree using Comp = E; // Lokalt namn för typparametern // samma som fö rut class Node friend class Tree <D,E>; D data ; Tree <D,E> left ; Tree <D,E> right ; Node (D d) : data d ~ Node () ; // samma som fö rut ; med egenskapsklass Medlemsfunktionerna använder komparator-klassen template <class D, class E> D* Tree <D,E>:: find (const D& d) if( empty ()) return nullptr ; else if( Comp :: equal (d, value ()) ) // eller E:: equal return & value (); else if(e:: less_than (d,value ()) ) // eller Comp :: less_than return l_child (). find (d); else return r_child (). find (d); : 10. Generisk programmering. Mallar och funktionsobjekt 31/37 : 10. Generisk programmering. Mallar och funktionsobjekt 32/37 med egenskapsklass Comparator-klassmall för vanliga typer struct Comparator static bool less_than (T l, T r) return l < r; static bool equal (T l, T r) return l == r; ; Specialisering av Comparator för Person template <> // specialisering -> ingen parameter struct Comparator<Person > // Ange typen explicit här static bool less_than ( Person l, Person r) return l.pnr. compare (r.pnr ) < 0; static bool equal ( Person l, Person r) return l.pnr. compare (r.pnr ) == 0; ; : 10. Generisk programmering. Mallar och funktionsobjekt 33/37 Lägg till en defaultparameter för Comparator Kompilatorn väljer Comparator<D> template <class D, class E=Comparator <D>> class Tree // samma som förut ; Nu fungerar: Tree <char > tc; tc. insert ( A ); tc. insert ( c ); try_find (tc, a ); try_find (tc, c ); Tree <Person > ps; ps. insert ( Person ("131211-1233 ", "Lisa ")); ps. insert ( Person ("010203-9876 ", "Nisse ")); try_find (ps, Person (" 010203-9876 ", "Vem")); : 10. Generisk programmering. Mallar och funktionsobjekt 34/37 Läsanvisningar Referenser till relaterade avsnitt i Lippman Generisk programmering 16.1, 16.3 (16.4 16.5) : 10. Generisk programmering. Mallar och funktionsobjekt 36/37