p. 1 Vakgroep Informatietechnologie Structuur Deel II C++ Classes Namespaces Type casting Reference types Constructors en Destructors Memory Management operators Overloading van functies en operators Friendship and inheritance Polymorphism Virtual Functions Templates Standard Template Library Hfdst 1 Hfdst 2 Hfdst 3 Hfdst 4
p. 2 Vakgroep Informatietechnologie C++ functie syntax Const qualifier Garandeert dat functie geen aanpassingen doet aan de attributen van een klasse Op constante objecten kunnen enkel constante functies opgeroepen worden {type} opt functie_naam(proto_lijst) {const} opt ; niet_lege_proto_lijst ::= {type {naam} opt } {, type {naam} opt } 0+ lege_proto_lijst ::=
p. 3 Vakgroep Informatietechnologie Operator Overloading Syntax : niet_lege_arg_lijst ::= {type {naam} opt } {, type {naam} opt } 0+ lege_arg_lijst ::= {return_type} 1 operator operator_naam (arg_lijst) {const} opt ;
p. 4 Vakgroep Informatietechnologie Operator overloading: opties 3 opties : 1. als klassemember gedeclareerd: toegang tot private attributen linkeroperand = object zelf, rechteroperand = argument 2. buiten klasse gedeclareerd: toegang tot private attributen via publieke methoden (bijv. set/get methodes) linkeroperand = 1e argument, rechteroperand = 2e argument 3. Als friend in klasse gedeclareerd: : toegang tot private attributen (zie Hfdst 3 Slides) linkeroperand = 1e argument, rechteroperand = 2e argument
p. 5 Vakgroep Informatietechnologie Betekenis argumenten-lijst class A{ … const A operator +(const A& a) const; A& operator=(const A& a); }; A a1, a2, a3; a3 = a1+a2; // equivalent : // a3.operator=(a1.operator+(a2));.h-file:.cpp-file:
p. 6 Vakgroep Informatietechnologie Voorbeelden van operatoren naamreturn_typearg_lijstconst (J/N) +const Aconst A& aJ -const Aconst A& aJ ==boolconst A& aJ - (unair)const A(geen)J Gedeclareerd in klasse A (operaties op objecten van klasse A):
p. 7 Vakgroep Informatietechnologie Voorbeelden van operatoren (2) naamreturn_typearg_lijstConst (J/N) =A&const A& aN <boolconst A& aY ++(prefix)A&(geen)N +=A&const A& aN
p. 8 Vakgroep Informatietechnologie Postfix versus prefix Prefix operator is default Voor postfix operator is onderscheid nodig: class A { public: A& operator++(); //Prefix increment operator (++x) A operator++(int); //Postfix increment operator (x++) A& operator--(); //Prefix decrement operator (--x) A operator--(int); //Postfix decrement operator (x--) }; int argument geeft aan dat het om postfix-operator gaat (int-waarde wordt NIET gebruikt !!)
p. 9 Vakgroep Informatietechnologie Andere operatoren Andere operatoren: * % >= -= [ ] Overladen van &&, || : geen kortsluitingsregel meer !! (sterk afgeraden om te overladen) Idem voor,(komma)-operator : geen left to right evaluatie meer !! (sterk afgeraden om te overladen) > (iostream operatoren -> zie volgend Hfdst!)
p. 10 Deel II: Programmeertaal C++ 3. Friends, overerving, polymorfisme en virtuele functies Prof.Dr.Ir. Filip De Turck
p. 11 Vakgroep Informatietechnologie Structuur Hoofdstuk Friendship Overerving Polymorfisme Virtuele Functies
p. 12 Vakgroep Informatietechnologie Friend Functies Friend functie van een klasse Geen member functie! Heeft directe toegang tot private attributen en methoden Zelfde rechten als member functies zelf keyword friend voor functie declaratie Gespecifieerd in de klasse definitie Buiten klasse gedefinieerd niet in scope van klasse (klasse_naam:: )
p. 13 Vakgroep Informatietechnologie Friend Functies Directe toegang aan private attributen van een klasse Geen overhead en efficienter dan toegang tot private attributen via publieke member-functies (spaart extra functie oproepen) Gevolg: non-member operatoren worden best als friends gedeclareerd!
p. 14 Vakgroep Informatietechnologie Friend Klassen Volledige klassen kunnen friends zijn Voorbeeld: Klasse Y is friend van klasse Z: Alle member functies van klasse Y zijn friends van klasse Z NIET omgekeerd Friend-schap wordt toegekend, niet genomen Syntax: friend class Y In de klasse declaratie van de klasse Z
p. 15 Vakgroep Informatietechnologie Concept Friends in OO Volgens strict OO principe dienen alle operatoren en functies member functies te zijn Friend concept schendt eigenlijk de OO basisprincipes! Toch gebruikt in C++ vooral bij operator overloading voor efficientie-verhoging
p. 16 Vakgroep Informatietechnologie Operator overloading met friends Voorbeeld overloaden > operator (iostream-operatoren) : Return value: istream& (voor >>) en ostream& (voor <<) Noodzakelijk voor cascade: bijv. cout << “a1 = ” << a1 << endl << “a2 = ” << a2 << endl ; Werken in op bijv. cin of cout (linkeroperand) Gevolg: kunnen geen memberfunctie van zelf-gedefinieerde klasse zijn! Best: friend-functie van zelf-gedefinieerde klasse
p. 17 Vakgroep Informatietechnologie Code voorbeeld > overloading Cfr Minerva site, Folder: Documents/Slides/C++_Examples_Savitch/overloading
p. 18 Vakgroep Informatietechnologie Overerving: structuur Basisconcept overerving Afgeleide klassen Constructoren van afgeleide klasses Het keywoord protected Herdefinitie van member-functies Geavanceerde topics: Assignment-operatoren en copy-constructoren Destructoren in afgeleide klassen Meervoudige overerving
p. 19 Vakgroep Informatietechnologie Afgeleide klassen (Eng.: Derived Classes), Overerving (Eng.:Inheritance) Een nieuwe klasse erft over van een andere klasse Basisklasse “Algemene" klasse van de welke de andere afgeleid zijn Afgeleide klasse Nieuwe klasse Heeft automatisch van de basisklasse: Member variabelen Member functies Kan additionele member functies en variabelen toevoegen
p. 20 Vakgroep Informatietechnologie Afgeleide klassen class A { public: void setVarA (int i); int getVarA (); private: int varA; }; class B : public A { public: void setVarB (int i); int getVarB (); private: int varB; }; B b; b.setVarA(8); b.setVarB(11); basisklasse afgeleide klasse in *.h- files gebruik in *.cpp- files
p. 21 Vakgroep Informatietechnologie Constructoren in afgeleide klassen Constructoren van de basisklasse worden NIET overgeerfd in de afgeleide klassen! Ze kunnen opgeroepen worden in de constructor van de afgeleide klasse De constructor van de basisklasse dient alle member variabelen van de basisklasse te initialiseren De constructor van de afgeleide klasse roept de constructor van de basisklasse op (in de initialisatie sectie!) Vervolgens worden de members van de afgeleide klasse geinitialiseerd
p. 22 Vakgroep Informatietechnologie Constructor van afgeleide klassen class A { public: A(); A(int i); void setVarA (int i); int getVarA (); private: int varA; }; class B : public A { public: B(); B(int i); B(int vara, int varb); void setVarB (int i); int getVarB (); private: int varB; }; A::A():varA(0) {} A::A(int i):varA(i) {} B::B():A(),varB(0) {} B::B(int i):A(),varB(i) {} B(int vara, int varb):A(vara), varB(varb){} basisklasse afgeleide klasse in *.h- files implementatie in *.cpp- files
p. 23 Vakgroep Informatietechnologie Constructor van afgeleide klasse Indien constructor van afgeleide klasse GEEN constructor van de basisklasse oproept: wordt de default constructor van de basisklasse automatisch opgeroepen default constructor=constructor zonder argumenten Opletten: indien initialisatie van pointer-waarden vereist!
p. 24 Vakgroep Informatietechnologie Private data van basisklasse Afgeleide klasse heeft geen directe toegang tot private members (variabelen en functies) van basisklasse Enkel indirecte toegang tot private data via publieke member-functies Private member-functies: enkel bruikbaar in klasse zelf, niet in afgeleide klassen veelal: private functie = hulpfunctie
p. 25 Vakgroep Informatietechnologie keywoord protected Laat toegang toe tot member variabelen en functies in afgeleide klasse In de klasse waar het gedefinieerd is : zelfde eigenschappen als private In afgeleide klasse: protected members van basisklasse eveneens protected Zodat ook toegankelijk voor verdere afleidingen
p. 26 Vakgroep Informatietechnologie Herdefinitie van member-functies In declaratie van afgeleide klasse (*.h bestand) : Declaraties van nieuwe member-functies Ook: declarations van overgeerfde member-functies die nieuwe implementatie krijgen NIET gedeclareerde overgeerfde member-functies: Worden automatisch onveranderd overgeerfd In de implementatie van de afgeleide klasse (*.cpp bestand) : Definitie van de nieuwe member-functies Herdefinitie van de overgeerfde member-functies zoals gedeclareerd Herdefinitie NIET hetzelfde als overloading!
p. 27 Vakgroep Informatietechnologie Toegang tot geherdefinieerde functie in hogere klasse class A { public: A(); A(int i); void setVarA (int i); int getVarA (); void print(); private: int varA; }; class B : public A { public: B(); B(int i); B(int vara, int varb); void setVarB (int i); int getVarB (); void print(); private: int varB; }; A a; B b; a.print(); b.print(); b.A::print(); // !!! basisklasse afgeleide klasse in *.h- files gebruik in *.cpp- files
p. 28 Vakgroep Informatietechnologie Functies die NIET overgeerfd worden Alle “gewone" functies worden overgeerfd in een afgeleide klasse Uitzonderingen: Constructoren Destructoren Copy constructor indien niet gedeclareerd wordt er een default copy constructor aangemaakt Assignment (=) operator idem, indien niet gedeclareerd, default aangemaakt Vooral opletten indien allocatie van pointers!
p. 29 Vakgroep Informatietechnologie Assignment Operator class A { public: A(); A(int i); void setVarA (int i); int getVarA (); A& operator=(const A& a); private: int varA; }; class B : public A { public: B(); B(int i); B(int vara, int varb); void setVarB (int i); int getVarB (); B& opera tor=(const B& b); private: int varB; }; B& B::operator = (const B& b){ A::operator=(b); … // assign extra members of B } basisklasse afgeleide klasse in *.h- files implementatie in *.cpp- files
p. 30 Vakgroep Informatietechnologie Copy constructor class A { public: A(); A(int i); A(const A& a); void setVarA (int i); int getVarA (); A& operator=(const A& a); private: int varA; }; class B : public A { public: B(); B(int i); B(int vara, int varb); B(const B& b); void setVarB (int i); int getVarB (); B& operator=(const B& b); private: int varB; }; B::B(const B& b): A(b){ … // copy extra members of B } basisklasse afgeleide klasse in *.h- files implementatie in *.cpp- files
p. 31 Vakgroep Informatietechnologie Destructoren in afgeleide klasses Wanneer de destructor van de afgeleide klasse opgeroepen wordt: Roept deze AUTOMATISCH de destructor van de basisklasse Hoeft niet expliciet opgeroepen te worden Destructor in afgeleide klasse hoeft enkel aandacht te hebben voor extra members in de afgeleide klasse Vertrouwt erop dat destructor van basisklasse correct werkt!
p. 32 Vakgroep Informatietechnologie Volgorde destructor aanroep class A { public: ~A(); … private: … }; class B : public A { public: ~B(); … private: … }; class C : public B { public: ~C(); … private: … }; { C c; … } // c out of scope // ~C wordt opgeroepen, ~B wordt opgeroepen, ~A wordt opgeroepen, (in deze volgorde) Omgekeerde volgorde van constructor-aanroep in *.cpp bestand :
p. 33 Vakgroep Informatietechnologie Protected en Private Overerving Nieuwe manier van overerven Zeldzaam gebruikt! Protected overerving: Vb. klasse B Publieke members in basisklasse A worden protected in de afgeleide klasse B Private overerving: Vb. klasse C Alle members in basisklasse A worden private in de afgeleide klasse B class A { public: ~A(); … private: … }; class B : protected A { public: … private: … }; class C : private A { public: … private: … };
p. 34 Vakgroep Informatietechnologie Meervoudige Overerving Een afgeleide klasse kan meerdere basisklassen hebben Zie vb. klasse C hiernaast Opletten voor dubbelzinnigheden! class A { public: ~A(); … private: … }; class B { public: … private: … }; class C : public A, B { public: … private: … };
p. 35 Vakgroep Informatietechnologie Voorbeeld code Cfr Minerva site, Folder: Documents/Slides/C++_Examples_Savitch/inheritance
p. 36 Vakgroep Informatietechnologie Polymorfisme Een functie kan meerdere uitvoeringen hebben Geimplementeerd aan de hand van virtuele functies Zeer belangrijk principe van object-georienteerd programmeren
p. 37 Vakgroep Informatietechnologie Virtuele functies: structuur Virtual Function Basics “Late binding” concept Implementatie van virtuele functies Abstracte klassen en pure virtuele functies Pointers en Virtuele Functies Downcasting and upcasting
p. 38 Vakgroep Informatietechnologie Virtuele Functies: Basis class Figure{ public: void draw(); void drawCenter(); private: int x; int y; }; class Circle: public Figure{ public: void draw(); private: double radius; }; class Rectangle: public Figure{ public: void draw(); private: int height; int width; } ; void Figure::drawCenter() { // bepaal centrum draw(); // teken in centrum } Voorbeeld :
p. 39 Vakgroep Informatietechnologie Virtuele Functies: Basis Nieuwe klasse: class Triangle: public Figure{ public: void draw(); private: //3 endpoint coordinates }; Welke draw () ?? Antw: uit klasse Figure, beter zou zijn: uit onderliggende klasse Rectangle r; Circle c; r. drawCenter(); c.drawCenter(); Triangle r; r.drawCenter(); moet draw() uit onderliggende klasse oproepen! maar: nieuwe klasse Triangle bestond toen nog niet !!
p. 40 Vakgroep Informatietechnologie Virtuele Functies: Basis Essentie Virtuele Functie : kan gebruikt worden vooraleer ze gedefinieerd is !! Koppeling met functie-code gebeurt bij gebruik (afhankelijk van oproepend object), niet bij implementatie Wordt late binding or dynamic binding genoemd Virtuele functies implementeren late binding Zeer belangrijk principe bij OO Programmeren In Java: alle functies zijn virtueel Oplossing: gebruik virtuele functies
p. 41 Vakgroep Informatietechnologie Gebruik Virtuele Functies class Figure{ public: virtual void draw(); void drawCenter(); private: int x; int y; }; class Circle: public Figure{ public: virtual void draw(); private: double radius; }; class Rectangle: public Figure{ public: virtual void draw(); private: int height; int width; } ; class Triangle: public Figure{ public: virtual void draw(); private: //3 endpoint coordinates }; void Figure::drawCenter() { // bepaal centrum draw(); // teken in centrum }
p. 42 Vakgroep Informatietechnologie Voorbeeld code Cfr Minerva site, Folder: Documents/Slides/C++_Examples_Savitch/polymorphism
p. 43 Vakgroep Informatietechnologie Overschrijven van virtuele functies Eng.: Overriding of virtual function Indien de functie definitie verandert in een afgeleide klasse Terminologie: "overschrijven“ van een virtuele functie Zelfde als geherdefinieerd (Eng.:redefined) Herdefinitie: term voor niet virtuele functies
p. 44 Vakgroep Informatietechnologie Waarom niet alle functies virtueel ? Virtuele functies hebben duidelijke voordelen Een belangrijk nadeel: overhead! Meer storage ruimte voor virtuele functie tabel Late binding gebeurt bij uitvoering: tragere uitvoering! Dus indien virtuele functies niet nodig zijn: best niet gebruiken In C++: keuze van programmeur, Java: geen keuze
p. 45 Vakgroep Informatietechnologie Pure Virtuele Functies Een basisklasse kan soms geen betekenisvolle implementatie geven voor sommige member- functies Bijv. enkel afgeleide klassen kunnen dit Bijv. class Figure, draw()-functie geen betekenisvolle implementatie Oplossing: maak er een pure virtuele functie van: syntax: virtual void draw() = 0; Analoog aan abstract keywoord van Java
p. 46 Vakgroep Informatietechnologie Abstracte Basisklassen Pure virtuele functies vereisen geen definitie Verplicht alle afgeleide klassen om hun eigen versie te definieren Klasse met 1 of meerdere pure virtuele functies is: abstracte basis-klasses kan alleen als basisklasse gebruikt worden geen objecten kunnen ervan geinstantieerd worden Indien in een afgeleide klasse alle pure virtuele functies niet gedefinieerd worden: Wordt het ook een abstracte basisklasse
p. 47 Vakgroep Informatietechnologie Abstracte Basisklassen class Figure{ public: virtual void draw()=0; void drawCenter(); private: int x; int y; }; class Circle: public Figure{ public: virtual void draw(); private: double radius; }; class Rectangle: public Figure{ public: virtual void draw(); private: int height; int width; } ; class Triangle: public Figure{ public: virtual void draw(); private: //3 endpoint coordinates }; void Figure::drawCenter() { // bepaal centrum draw(); // teken in centrum }
p. 48 Vakgroep Informatietechnologie Toekenning afgeleide klassen class A { public: void setVarA (int i); int getVarA (); private: int varA; }; class B : public A { public: void setVarB (int i); int getVarB (); private: int varB; }; A a; B b; a=b; // OK b=a; // niet OK ! basisklasse afgeleide klasse in *.h- files gebruik in *.cpp- files
p. 49 Vakgroep Informatietechnologie Toekenning afgeleide klassen class A { public: void setVarA (int i); int getVarA (); private: int varA; }; class B : public A { public: void setVarB (int i); int getVarB (); private: int varB; }; A a; B b; b.setVarA(12); b.setVarB(7); a=b; // OK cout << a.getVarA() << endl; //OK cout << a.getVarB() << endl; // NIET OK! In sommige gevallen aangewezen => Gebruik pointers naar dynamische variabelen !
p. 50 Vakgroep Informatietechnologie Toekenning pointers naar klassen class Figure{ public: virtual void draw(); void drawCenter(); private: int x; int y; }; class Rectangle: public Figure{ public: virtual void draw(); private: int height; int width; } ; Figure* fp1; Rectangle* rp1; rp1=new Rectangle; fp1=rp1; fp1->draw(); //roept draw van Rectangle op Figure* fp2 = new Rectangle; fp2->draw(); //roept draw van Rectangle op
p. 51 Vakgroep Informatietechnologie Virtuele Destructoren Figure *pf = new Rectangle; … delete pf; Aanroept enkel destructor van basisklasse!! Oplossing: maak destructor virtueel Wordt aanzien als een goede methodologie om alle destructoren virtueel te maken
p. 52 Vakgroep Informatietechnologie Casting Figure f; Circle c; … c = static_cast (f); //NIET TOEGELATEN Een basisklasse kan niet naar een afgeleide klasse gecast worden, maar omgekeerd wel: f = c; // TOEGELATEN f = static_cast (c); //EVENEENS TOEGELATEN Upcasting is geen probleem!
p. 53 Vakgroep Informatietechnologie Downcasting Downcasting is gevaarlijk! Casting naar een afgeleid type Veronderstelt dat informatie toegevoegd wordt Kan uitgevoerd worden met dynamic_cast Werkt alleen met pointer types Figure *fp; fp = new Circle; Circle *cp = dynamic_cast (fp); if (cp) { //gelukt} else { //mislukt } Downcasting wordt zelden gebruikt wegens pitfalls Alle member functies dienen virtueel te zijn
p. 54 Vakgroep Informatietechnologie Interne werking van Virtuele Functies Interne werking afgeschermd van het gebruik Compiler creëert virtuele functie tabel Houdt pointers bij voor elke virtuele member-functie Wijst naar de locatie van de correcte code voor die functie