Objectgeoriënteerd Programmeren in C++

Slides:



Advertisements
Verwante presentaties
Stage bij Technische Informatica
Advertisements

Inleiding programmeren in C++ Life Science & Technology 26 januari Universiteit Leiden.

Elektrotechniek Elektrotechniek is een heel breed vakgebied.
Universiteit Leiden Inleiding programmeren in C++ Life Science & Technology 16 februari
Programmeren en Software Engineering 2

Embedded systemen Embedded software.
Project Software Engineering
Jaar 1Jaar 2Jaar 3Jaar 4 Opleidingsprofiel Elektrotechniek De CarrièreDe Basis Afstuderen PropedeuseKern Stage EP1EP2EQ1EQ2ECS Minor ECNECA regulier Minor.
Algoritmen en Datastructuren (ALDAT)
OOS Object geOrienteerd Software-ontwerp - 3
Microcontroller Programmeren in C
Hogeschool HZ Zeeland 19 augustus 2003augustus 2003 Data Structuren & Algoritmen Week 1.
Inleiding programmeren in C++ Life Science & Technology 23 februari Universiteit Leiden.
Inleiding in de Civiele Techniek
Ronde (Sport & Spel) Quiz Night !
Jaar 1Jaar 2Jaar 3Jaar 4 Opleidingsprofiel Elektrotechniek De CarrièreDe Basis Afstuderen PropedeuseKern Stage EP1EP2EQ1EQ2ECS Minor ECNECA regulier Minor.
Digitale Elektronica en Processoren
Jaar 1Jaar 2Jaar 3Jaar 4 Opleidingsprofiel Elektrotechniek De CarrièreDe Basis Afstuderen PropedeuseKern Stage EP1EP2EQ1EQ2ECS Minor ECNECA regulier Minor.
EVMINX4 Week 3 Algoritmen en Datastructuren (ALDAT)
Gestructureerd programmeren in C
Van domeinklasse tot implementatie
Hoe pas je de interacties in in je analyse van je domein?
Inleiding programmeren in C++ Life Science & Technology 19 januari Universiteit Leiden.
PROS2 Les 11 Programmeren en Software Engineering 2.
GESPRG Les 14 Gestructureerd programmeren in C. 174 Details! The devil is in the details.

HM-ES-th1 Les 1 Hardware/Software Codesign with SystemC.
Jaar 1Jaar 2Jaar 3Jaar 4 Opleidingsprofiel Elektrotechniek De CarrièreDe Basis Afstuderen PropedeuseKern Stage EP1EP2EQ1EQ2ECS Minor ECNECA regulier Minor.

Inleiding Software Engineering
Ontwerpen van Informatiesystemen met
Interaction diagrams: Sequence Diagram
1 Voorwaarden hergebruik Modulair ontwerp Low coupling High cohesion.
1 Uit ons domein: Verzameling programmatuur voor het toewijzen van afstudeerders aan examinatoren. Invoer van voorkeuren Toewijzen Overzichten Practicum.
Promo site ICT haagsehoge school Opleidingen: Informatica Technische informatica Communication & multimedia design Informatiedienstverlening en –management.
Jaar 1Jaar 2Jaar 3Jaar 4 Opleidingsprofiel Elektrotechniek De CarrièreDe Basis Afstuderen PropedeuseKern Stage EP1EP2EQ1EQ2ECS Minor ECNECA regulier Minor.
MICPRG Les 11 Microcontroller Programmeren in C. 112 Datastructuren in C Werkgeheugen (PC en microcontroller): Statische datastructuren (vaste grootte):
GESPRG Les 9 Gestructureerd programmeren in C dimensionale array Array van array’s int i = 31; int a[4] = {7, 23, 6, 2}; int m[2][4] = { {1, 1,
Laatste toets Vrijdag 8 november van 8.30 – uur Locatie: EDUC-BETA Stof: Alles! Slides Boek Werkcollegeopgaven Practicumopgaven.
C++ handboek : C++ Leen Ameraal 6e druk academic service.
Inleiding programmeren in C++ Life Science & Technology 2 februari Universiteit Leiden.
Inleiding programmeren in C++ Life Science & Technology 9 februari Universiteit Leiden.
Werken aan Intergenerationele Samenwerking en Expertise.
Inleiding programmeren in C++ Life Science & Technology Inleiding
Software-ontwikkeling I
A H M F K EB C x 85 Korte zijde bij C 2 e secties volte 14 m en op afstand komen ( 0,5 rijbaan)
A H M F K EB C x 92 Galop Binnenruiters grote volte bij A en C -partnerruil- Volgende korte zijde in.
ZijActief Koningslust 10 jaar Truusje Trap
OO Analyse in de praktijk OO Analyse in de praktijk V Enkele Design Patterns.
Herhaling Java-programmatie en geautomatiseerd testen (vervolg)
Ontwikkeld door CWB3. Opbouw Presentatie 1.Wat is GeoSport? 2.Ontwerp 1.Gebruikte ontwerpmethodieken 2.Ervaring 3.Implementatie 1.Gebruikte technologieën.
Nieuwe Meesters Delft Erfgoed = saai! 1. Nieuwe Meesters Delft Erfgoed = overal! 2.
ECHT ONGELOOFLIJK. Lees alle getallen. langzaam en rij voor rij
De financiële functie: Integrale bedrijfsanalyse©
1 Zie ook identiteit.pdf willen denkenvoelen 5 Zie ook identiteit.pdf.
Jaar 1Jaar 2Jaar 3Jaar 4 Opleidingsprofiel Elektrotechniek De CarrièreDe Basis Afstuderen PropedeuseKern EP1EP2EQ1EQ2 2 × Minor ECNECA duaal Minor Kern.
ZijActief Koningslust
Jaar 1Jaar 2Jaar 3Jaar 4 Opleidingsprofiel Elektrotechniek De CarrièreDe Basis Afstuderen PropedeuseKern 2 × Stage EP1EP2EQ1EQ2ECS 2 × Minor ECNECA voltijd.
Hoorcollege 1a Praktische zaken. Gameprogrammeren Doel van het vak: Games programmeren (de game loop, sprites, audio, physics, animatie…) Basisprogrammeertechnieken.
Tircms03-p les 1 C++ voor C-kenners Voor Technische Informatica.
UML 2. Activiteitendiagrammen2. Activiteitendiagrammen.
Gameprogrammeren: Introductie
Keuzedeel Verdieping Software
De programmeertaal C++
Arjan Egges & Paul Bergervoet
Tinpro015b-les 1 C++ voor C-kenners Voor Technische Informatica.
Keuzedeel Verdieping Software
Software Development fundamentals
Transcript van de presentatie:

Inhoud Les 1 Les 4 Les 7 Les 10 Les 13 Les 16 Les 19 Les 2 Les 5 Les 8 OGOPRG 3 april 2017 Inhoud Les 1 Les 4 Les 7 Les 10 Les 13 Les 16 Les 19 Les 2 Les 5 Les 8 Les 11 Les 14 Les 17 Les 20 Les 3 Les 6 Les 9 Les 12 Les 15 Les 18 Les 21 © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 1 © Harry Broeders

Werkvormen OGOPRG OGOPRG-co1 + OGOPRG-pr1 = 112 SBU. Toetsing: 3 april 2017 Werkvormen OGOPRG OGOPRG-co1 + OGOPRG-pr1 = 112 SBU. 21 uur theorie. 14 uur practicum. 77 uur zelfstudie = 9,5 uur/week zelfstudie! Toetsing: Schriftelijke toets OGOPRG-co1 in week 8 en 10 van dit kwartaal. OGOPRG-pr1 practicumopgaven worden afgetekend op het practicum. Alle opgaven moeten voldoende zijn. © Harry Broeders

Inhoud Herbruikbaarheid Aanpasbaarheid Uitbreidbaarheid OGOPRG 3 april 2017 Inhoud Objectgeoriënteerd Programmeren in C++. responsibility driven design (ontwerpen uitgaande van verantwoordelijkheden). information hiding (het afschermen van informatie door middel van het scheiden van interface en implementatie). abstraction (het afschermen van complexiteit door middel van het scheiden van interface en implementatie). inheritance (het mogelijk maken van een nieuwe vorm van hergebruik, ... is een ... in plaats van ... heeft een ...). polymorphism (veelvormigheid mogelijk gemaakt door dynamic binding). Objectgeoriënteerd Ontwerpen met UML. klasse- en objectdiagrammen. use-case-diagram. sequence- en collaborationdiagrammen. toestands- en activiteitendiagrammen. Herbruikbaarheid Aanpasbaarheid Uitbreidbaarheid © Harry Broeders

Plaats in curriculum Bouwt verder op GESPRG en MICPRG. OGOPRG 3 april 2017 Plaats in curriculum Bouwt verder op GESPRG en MICPRG. Voorbereiding voor ECV: RTSYST Real-Time Systemen (verplicht) ALGODS Algoritmen en Datastructuren (keuze) Voorbereiding voor minor Embedded Systems © Harry Broeders

Leermiddelen Blackboard OGOPRG. http://bd.eduweb.hhs.nl/ogoprg: Boek: 3 april 2017 Leermiddelen Blackboard OGOPRG. http://bd.eduweb.hhs.nl/ogoprg: Sheets, handouts. Studiewijzer. Practicumopdrachten. Dictaat: Objectgeoriënteerd Programmeren in C++. Boek: Warmer & Kleppe, Praktisch UML, 5de editie ISBN 9789043020558. Ontwikkelomgeving: Microsoft Visual Studio Express 2012 for Windows Desktop. Visual Paradigm for UML 10.0. © Harry Broeders

GESPRG en MICPRG zijn het fundament voor OGOPRG. Zie dictaat blz. 1. 3 april 2017 Een stapje verder... ...met programmeren en ontwerpen. Waarom? Van gestructureerd naar objectgeoriënteerd. C++ is een uitbreiding op C: alles wat in C kan, kan ook in C++. veel wat in C kan, kan in C++ beter (struct, array, c-string enz). GESPRG en MICPRG zijn het fundament voor OGOPRG. Zie dictaat blz. 1. © Harry Broeders

Dat is een lang verhaal... Gestructureerde programmeertalen: OGOPRG 3 april 2017 Dat is een lang verhaal... Gestructureerde programmeertalen: ±1945 assembler, ±1957 FORTRAN, ±1960 Algol60, ±1972 C (1989 std ANSI C) Software crisis: Software niet op tijd geleverd. Software duurder dan afgesproken. Software niet foutloos. Idee voor de oplossing: Herbruikbare software componenten maken. Deze componenten gebruiken bij maken van grote uitbreidbare en onderhoudbare software systemen. Objectgeoriënteerde programmeertalen: ±1967 Simula, ±1976 Smalltalk, ±1983 C++ (1998 std C++), ±1995 Java (Sun), ±2000 C# (Microsoft). © Harry Broeders

... maar ook een kort verhaal OGOPRG 3 april 2017 ... maar ook een kort verhaal © Harry Broeders

... maar ook een kort verhaal OGOPRG 3 april 2017 ... maar ook een kort verhaal © Harry Broeders

Huiswerk: Dictaat blz. 1 t/m 12 en practicumopdracht 1. OGOPRG 3 april 2017 Inleiding C++ Bjarne Stroustrup: “C++ is designed to: be a better C. support data abstraction. support object-oriented programming. support generic programming.” Huiswerk: Dictaat blz. 1 t/m 12 en practicumopdracht 1. © Harry Broeders

Practicumopdracht 1a #include <iostream> #include <string> OGOPRG 3 april 2017 Practicumopdracht 1a #include <iostream> #include <string> using namespace std; int main() { cout << "Geef je email adres: "; string mailAdres; cin >> mailAdres; string::size_type indexAt = mailAdres.find("@"); if (indexAt != string::npos) { cout << "Gebruiker: " << mailAdres.substr(0, indexAt) << endl; cout << "Machine: " << mailAdres.substr(indexAt + 1) << endl; } else { cout << mailAdres << " is geen geldig email adres!" << endl; cout << "Druk op de return-toets." << endl; cin.get(); cin.get(); return 0; © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 2 © Harry Broeders

Vraag Welke software hoeft nooit uitgebreid of veranderd te worden? OGOPRG 3 april 2017 Vraag Welke software hoeft nooit uitgebreid of veranderd te worden? Software die niemand gebruikt. © Harry Broeders

OGOPRG 3 april 2017 Nieuw! Objectgeoriënteerd Programmeren is een nieuwe manier van denken ... ... over hoe we code en informatie in een computerprogramma kunnen structureren. Programmeer paradigma’s: imperative (C, Pascal). functional (LISP, Haskell). logic (Prolog). object oriented (C++, Java, C#). generic (ADA, C++). © Harry Broeders

Objectgeoriënteerd Denken OGOPRG 3 april 2017 Objectgeoriënteerd Denken De manier van probleem oplossen die gebruikt wordt bij de objectgeoriënteerde programmeertalen en ontwerpmethoden lijkt vaak op de manier van probleem oplossen die mensen in het dagelijks leven ook gebruiken. © Harry Broeders

Voorbeeld Ik wil mijn oma een bosje bloemen sturen. object OGOPRG 3 april 2017 Voorbeeld Ik wil mijn oma een bosje bloemen sturen. object message + arguments receiver's responsibility method (information hiding) © Harry Broeders

Vraag Wat is het verschil tussen een message en een functie? OGOPRG 3 april 2017 Vraag Wat is het verschil tussen een message en een functie? Een message heeft een bepaalde receiver. De method die bij de message hoort is afhankelijk van de receiver. De receiver van een message kan ook tijdens run-time worden bepaald. Dynamic binding between the message (function name) and method (code). © Harry Broeders

Vraag Waarom weet ik zoveel van mijn bloemiste? class OGOPRG 3 april 2017 Vraag Waarom weet ik zoveel van mijn bloemiste? class instance (object) hierarchy inheritance (base and derived) © Harry Broeders

Method binding Zoek in class van het receiver object. OGOPRG 3 april 2017 Method binding Zoek in class van het receiver object. Als daar geen method is zoek dan in de base class van de class van het receiver object. Als daar geen method is zoek dan in de base class van de base class van de class van het receiver object. Enzovoort. Een method uit de base class kan overriden worden door een method in een derived class. © Harry Broeders

Verband tussen classes OGOPRG 3 april 2017 Verband tussen classes Aggregation = heeft een (of meer) Inheritance = is een (speciaal soort) UML klassendiagram. © Harry Broeders

OGOPRG 3 april 2017 UML sequentiediagram © Harry Broeders

Steeds meer abstractie OGOPRG 3 april 2017 Steeds meer abstractie Functions. Avoid duplicating code. Information hiding. Modules. Data and information hiding. Abstract data types. Instantiation. Generic functions en generic ADT’s. Templates. Classes. Messages. Inheritance. Polymorphism. Geschiedenis van programmeertechnieken. © Harry Broeders

Doel van object oriëntatie OGOPRG 3 april 2017 Doel van object oriëntatie Construeren van herbruikbare software componenten. Gebruiken van deze componenten bij het construeren van grote aanpasbare en uitbreidbare systemen. Huiswerk: Bestudeer hoofdstuk 2 t/m 2.1 van het dictaat. Software IC © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 3 © Harry Broeders

Herbruikbare component: Breuk OGOPRG 3 april 2017 Herbruikbare component: Breuk Waarom wil je programma’s maken die rekenen met breuken in plaats van met floating point getallen (double)? Waarom wil je een component Breuk maken? Hoe doe je dat in C? Wat zijn de nadelen van de C oplossing? Hoe kan het beter in C++? Wat zijn de voordelen van de C++ oplossing? Kan het nog mooier? Dictaat H2.2 t/m 2.28 (4 lessen). © Harry Broeders

Breuk in C Gebruik struct voor dataopslag. OGOPRG 3 april 2017 Breuk in C Gebruik struct voor dataopslag. Gebruik functies voor bewerkingen. Struct type declaratie typedef struct { /* een breuk bestaat uit: */ int boven; /* een teller en */ int onder; /* een noemer */ } Breuk; Breuk normaliseer(Breuk b); Breuk som(Breuk b1, Breuk b2); Breuk som(Breuk b1, Breuk b2) { Breuk s; s.boven = b1.boven * b2.onder + b1.onder * b2.boven; s.onder = b1.onder * b2.onder; s = normaliseer(s); return s; } Prototypes of Functie declaraties Functie definitie © Harry Broeders

Kan overal in het programma staan! OGOPRG 3 april 2017 Gebruik Breuk b1, b2, b3; b1.boven = 5; b1.onder = 12; b2.boven = 4; b2.onder = 9; b3 = som(b1, b2) Kan overal in het programma staan! Nadelen Breuk in C b1.onder = 0 is een “ramp die wacht om te gebeuren”. Programmeur die het beter denkt te weten kan zelf breuken gaan optellen: b3.teller = b1.teller + b2.teller; b3.noemer = b1.noemer + b2.noemer; Verschillende programmeurs kunnen in verschillende delen van het programma de Breuk component uitbreidingen: B.v. functies: maal, times, en multiply. OOPS! © Harry Broeders

Eigenschappen van C Breuk OGOPRG 3 april 2017 Eigenschappen van C Breuk Onderhoudbaarheid. Fout in component is niet gemakkelijk te vinden. Iedereen kan data van component “verzieken”. Iedereen kan algoritme implementeren zonder implementatie van de component te gebruiken. Als er “iets” niet goed gaat met component (b.v. vermenigvuldigen van breuken) moeten we het hele programma doorzoeken. Aanpasbaarheid en uitbreidbaarheid. Iedereen kan component aanpassen en uitbreiden. Herbruikbaarheid. Onduidelijk welke functies bij component horen en welke functies bij deze applicatie horen (en toevallig deze component gebruiken). Slecht! Te Goed! Slecht! © Harry Broeders

Breuk in C++ Gebruik class voor dataopslag en bewerkingen. OGOPRG 3 april 2017 Breuk in C++ Gebruik class voor dataopslag en bewerkingen. Class declaratie class Breuk { public: void leesin(); void drukaf() const; void plus(Breuk b); private: int boven; int onder; void normaliseer(); }; void Breuk::plus(Breuk b) { boven = boven * b.onder + onder * b.boven; onder *= b.onder; normaliseer(); } Public memberfuncties = interface Private data members Private memberfunctie Memberfunctie definitie © Harry Broeders

Gebruik Voordelen Breuk in C++ b1.onder = 0 geeft compilerfout. OGOPRG 3 april 2017 Gebruik Breuk a, b; a.leesin(); b.leesin(); a.plus(b); a.drukaf(); Voordelen Breuk in C++ b1.onder = 0 geeft compilerfout. Programmeur die het beter denkt te weten kan zelf geen breuken gaan optellen (zonder Breuk::plus te wijzigen). Component Breuk kan slechts op 1 plaats in het programma uitgebreid worden. © Harry Broeders

Eigenschappen van C++ Breuk OGOPRG 3 april 2017 Eigenschappen van C++ Breuk Goed! Onderhoudbaarheid. Fout in component is gemakkelijk te vinden. Als er “iets” niet goed gaat met component hoef je alleen de implementatie van de component te doorzoeken. Fout moet in memberfuncties van de component zitten. Je kunt niet (eenvoudig) om de interface van de class heenwerken. (Je kan zelf geen plus maken als je niet bij boven en onder kunt komen.) Aanpasbaarheid en uitbreidbaarheid. Component kan maar op 1 plaats uitgebreid worden. Private delen kunnen aangepast worden zonder dat de interface veranderd. Dus zonder dat de code die de component gebruikt dit merkt! Zie practicum opgave 2c. Herbruikbaarheid. Duidelijk welke functies bij component horen. Goed! Redelijk. Huiswerk: Bestudeer paragraaf 2.2 van het dictaat. © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 4 © Harry Broeders

Kenmerken van objecten OGOPRG 3 april 2017 Kenmerken van objecten In de vorige lessen hebben we de volgende objecten leren kennen: Sonja en Corien (van de class Bloemiste) en a en b (van de class Breuk). Kenmerken: Geheugen (state). Elk object heeft zijn “eigen” geheugen. Gedrag (behavior). Alle objecten van dezelfde class hebben hetzelfde gedrag. Identiteit (identity). Elk object heeft een “eigen” identiteit (b.v. een naam). © Harry Broeders

Class Breuk (versie 1) class Breuk { Data members public: OGOPRG 3 april 2017 Class Breuk (versie 1) class Breuk { public: Breuk(); Breuk(int t); Breuk(int t, int n); int teller() const; int noemer() const; void plus(Breuk b); void abs(); private: int boven; int onder; void normaliseer(); }; Data members Memberfuncties: Constructors Vraag-functies. Doe-functies. int main() { Breuk a, b(-2), c(21, -9); // ... © Harry Broeders

Class Breuk (versie 1) int main() { Breuk a, b(-2), c(21, -9); OGOPRG 3 april 2017 Class Breuk (versie 1) int main() { Breuk a, b(-2), c(21, -9); cout << a.teller() << "/" << a.noemer() << endl; cout << b.teller() << "/" << b.noemer() << endl; cout << c.teller() << "/" << c.noemer() << endl; c.abs(); cin.get(); return 0; } © Harry Broeders

Implementatie constructors OGOPRG 3 april 2017 Implementatie constructors Breuk::Breuk(): boven(0), onder(1) { } Breuk::Breuk(int t): boven(t), onder(1) { Breuk::Breuk(int t, int n): boven(t), onder(n) { normaliseer(); Initialization list int main() { Breuk h("half"); return 0; } Werkt dit? Wat moet je doen om dit wel te laten werken? © Harry Broeders

Roep destructor c.~Breuk() aan en geef geheugen van c weer vrij OGOPRG 3 april 2017 Constructor Compiler roept de constructor automatisch aan. Reserveer geheugen op de stack voor c en roep constructor c.Breuk(21, -9) aan { Breuk c(21, -9); // ... } Roep destructor c.~Breuk() aan en geef geheugen van c weer vrij © Harry Broeders

Constructor en type conversie OGOPRG 3 april 2017 Constructor en type conversie Compiler roept de constructor automatisch aan als dat nodig is voor type conversie. Reserveer geheugen op de stack en roep constructor Breuk(5) aan De C++ compiler denkt met je mee! Als je dat niet wilt moet je explicit voor de constructor zetten. c.plus(Breuk(5)); { Breuk c(21, -9); // ... c.plus(5); } Roep destructor aan en geef geheugen van Breuk(5) weer vrij © Harry Broeders

Class Breuk Werkt dit? class Breuk { public: void leesin(); OGOPRG 3 april 2017 Class Breuk class Breuk { public: void leesin(); void drukaf() const; int teller() const; int noemer() const; void plus(Breuk b); void abs(); private: int boven; int onder; void normaliseer(); }; int main() { Breuk a, b; a.drukaf(); a.leesin(); b = a; b.drukaf(); Breuk c(a); c.drukaf(); return 0; } Werkt dit? © Harry Broeders

Je kunt al deze functies ook zelf definiëren! OGOPRG 3 april 2017 Gratis bij elke class! constructor zonder argument (default constructor). Deze constructor roept de default constructor aan van alle data members. copy constructor. Deze constructor roept de copy constructor aan van alle data members. assignment operator (operator=). Deze assignment operator roept de assignment operator aan van alle data members. destructor. Deze destructor roept de destructor aan van alle data members. Je kunt al deze functies ook zelf definiëren! © Harry Broeders

const Breuk / const memberfuncties OGOPRG 3 april 2017 const Breuk / const memberfuncties Je kunt een constante Breuk definiëren. const Breuk kwart(1, 4); cout << kwart.teller() << '/' << kwart.noemer() << endl; // mag dit ? kwart.plus(5); // mag dit ? Hoe weet de compiler dat? © Harry Broeders

Class Breuk (versie 1) class Breuk { Vraag-functies: public: OGOPRG 3 april 2017 Class Breuk (versie 1) class Breuk { public: Breuk(); Breuk(int t); Breuk(int t, int n); int teller() const; int noemer() const; void plus(Breuk b); void abs(); private: int boven; int onder; void normaliseer(); }; Vraag-functies: Return type Geen argumenten const Doe-functies: Geen return type (void) Meestal argumenten Breuk b(3, 4); const Breuk kwart(1, 4); cout << b.teller() << endl; b.plus(kwart); cout << kwart.teller() << endl; kwart.plus(b); © Harry Broeders

Huiswerk! Bestudeer dictaat 2.3 t/m 2.10. OGOPRG 3 april 2017 Huiswerk! Bestudeer dictaat 2.3 t/m 2.10. Compileert dit programma bij gebruik van versie 1 van Breuk? Wat is de lengte en breedte van r1 en r2? class Rechthoek { public: // ... (geen constructors) private: Breuk lengte; Breuk breedte; }; int main() { Rechthoek r1; // ... Rechthoek r2(r1); } © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 5 © Harry Broeders

Gebruik Breuk is vergelijkbaar met int! OGOPRG 3 april 2017 Class Breuk Breuk a, b; a.leesin(); b.leesin(); a.plus(b); a.drukaf(); Kan het beter? Stel hergebruik Breuk component is succes! Helpfiles FAQ Gebruik Breuk is vergelijkbaar met int! Breuk a, b; cin >> a >> b; a += b; cout << a; Veel werk! Moeite waard? © Harry Broeders

Operator overloading a.operator+=(b); a += b; De C++ compiler OGOPRG 3 april 2017 Operator overloading a.operator+=(b); a += b; De C++ compiler denkt met je mee! © Harry Broeders

Operator overloading is simpel! ? OGOPRG 3 april 2017 Breuk in C++ class Breuk { public: void leesin(); void drukaf() const; void operator+=(Breuk b); private: int boven; int onder; void normaliseer(); }; void Breuk::operator+=(Breuk b) { boven = boven * b.onder + onder * b.boven; onder *= b.onder; normaliseer(); } Operator overloading is simpel! ? © Harry Broeders

Breuk is een succes! Mag a += b += c met int? Oplossing? OGOPRG 3 april 2017 Breuk is een succes! Mag a += b += c met int? Wat betekent het dan? Oplossing? b += c; a += b; Kan dat niet beter? © Harry Broeders

Fix Breuk::operator+= OGOPRG 3 april 2017 Fix Breuk::operator+= class Breuk { public: void leesin(); void drukaf() const; Breuk operator+=(Breuk b); private: int boven; int onder; void normaliseer(); }; Breuk Breuk::operator+=(Breuk b) { boven = boven * b.onder + onder * b.boven; onder *= b.onder; normaliseer(); return *this; } class Breuk { public: void leesin(); void drukaf() const; Breuk operator+=(Breuk b); private: int boven; int onder; void normaliseer(); }; Breuk Breuk::operator+=(Breuk b) { boven = boven * b.onder + onder * b.boven; onder *= b.onder; normaliseer(); return ?????; } Pas op! Deze code is niet correct. Zie volgende sheet. © Harry Broeders

Breuk is geen succes! Oplossing? reference OGOPRG 3 april 2017 © Harry Broeders

Is dit goed voor de onderhoudbaarheid? OGOPRG 3 april 2017 Reference In C++ zijn er 3 “soorten” variabelen: “Gewone” variabelen. Pointers. References. Een reference is een andere naam voor een variabele die al bestaat. int i; int& j = i; //initialisatie is verplicht! i = 3; cout << j << endl; // een reference is een "pseudoniem" Is dit goed voor de onderhoudbaarheid? © Harry Broeders

Gebruik reference Je kunt een reference gebruiken als: OGOPRG 3 april 2017 Gebruik reference Je kunt een reference gebruiken als: Globale variabele. Lokale variabele. Parameter. Return type. © Harry Broeders

Call by value void swap(int p, int q) { int t = p; p = q; q = t; } OGOPRG 3 april 2017 Call by value void swap(int p, int q) { int t = p; p = q; q = t; } // ... int i = 3; int j = 4; swap(i, j); Deze code werkt niet goed! Weet je nog waarom? Oplossing? © Harry Broeders

p wijst naar i q wijst naar j OGOPRG 3 april 2017 Call by reference in C void swap(int* p, int* q) { int t = *p; *p = *q; *q = t; } // ... int i = 3; int j = 4; swap(&i, &j); p wijst naar i q wijst naar j © Harry Broeders

Call by reference in C++ OGOPRG 3 april 2017 Call by reference in C++ void swap(int& p, int& q) { int t = p; p = q; q = t; } // ... int i = 3; int j = 4; swap(i, j); p is andere naam voor i q is andere naam voor j Onder de “motorkap” wordt een reference geïmplementeerd met een pointer. © Harry Broeders

OGOPRG 3 april 2017 Reference return Je kunt een reference ook teruggeven vanuit een functie. int& max(int& a, int& b) { if (a > b) return a; else return b; } int main() { int x = 2, y = 7, z; max(x, y) = 0; z = max(x, y); // ... Een functie die een reference teruggeeft kan ook links van een = teken gebruikt worden (is een lvalue). © Harry Broeders

Fix Breuk::operator+= OGOPRG 3 april 2017 Fix Breuk::operator+= class Breuk { public: void leesin(); void drukaf() const; Breuk& operator+=(Breuk b); private: int boven; int onder; void normaliseer(); }; Breuk& Breuk::operator+=(Breuk b) { boven = boven * b.onder + onder * b.boven; onder *= b.onder; normaliseer(); return *this; } Met behulp van een reference kunnen we ook onnodige kopietjes voorkomen. © Harry Broeders

Fix Breuk::operator+= OGOPRG 3 april 2017 Fix Breuk::operator+= class Breuk { public: void leesin(); void drukaf() const; Breuk& operator+=(const Breuk& b); private: int boven; int onder; void normaliseer(); }; Breuk& Breuk::operator+=(const Breuk& b) { boven = boven * b.onder + onder * b.boven; onder *= b.onder; normaliseer(); return *this; } Waarom const? © Harry Broeders

Huiswerk! Bestudeer dictaat 2.11 t/m 2.20. OGOPRG 3 april 2017 Huiswerk! Bestudeer dictaat 2.11 t/m 2.20. Een reference lijkt op een pointer. Wat zijn de verschillen? Noem 3 situaties waar een copy constructor nodig is. Waarom zijn de parameters van max (zie boven) geen int of const int& ? Zorg dat dit programmadeel werkt: int main() { Breuk a, b, c; // ... c = a + b; } © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 6 © Harry Broeders

Operator+ overloading OGOPRG 3 april 2017 Operator+ overloading Gratis! Zelf maken { Breuk a, b, c; c = a + b; } c.operator=(a.operator+(b)); Wat moet operator+ eigenlijk doen? Wat moet het parametertype zijn? Breuk Goed const Breuk& Beter! Voorkomt onnodig kopietje. Wat moet het returntype zijn? Breuk& Fout! Je hebt geen variabele die al bestaat. const Breuk Beter! Geeft een fout bij: a + b = c; © Harry Broeders

Breuk::operator+ Waarom const? class Breuk { public: // ... OGOPRG 3 april 2017 Breuk::operator+ class Breuk { public: // ... Breuk& operator+=(const Breuk& rechts); const Breuk operator+(const Breuk& rechts) const; private: int boven; int onder; void normaliseer(); }; const Breuk Breuk::operator+(const Breuk& rechts) const { Breuk hulpje(*this); hulpje += rechts; return hulpje; } Waarom const? © Harry Broeders

Breuk::operator+ De volgende implementaties zijn niet juist! OGOPRG 3 april 2017 Breuk::operator+ De volgende implementaties zijn niet juist! const Breuk Breuk::operator+(const Breuk& rechts) { Breuk hulpje(*this); hulpje += rechts; return hulpje; } // Hint: const Breuk kwart(1, 4); Breuk b(2, 3), c; c = kwart + b; const vergeten! const Breuk& Breuk::operator+(const Breuk& rechts) const { Breuk hulpje(*this); hulpje += rechts; return hulpje; } Return andere naam voor een “dode” variabele! const Breuk& Breuk::operator+(const Breuk& rechts) const { *this += rechts; return *this; } Receiver mag niet veranderen! © Harry Broeders

Breuk::operator+ probleem! OGOPRG 3 april 2017 Breuk::operator+ probleem! Breuk(5) { Breuk a, b; b = a + 5; b = 5 + a; } b.operator=(a.operator+(5)); b.operator=(5.operator+(a)); Microsoft error: binary '+' : no global operator found which takes type 'Breuk'. GNU gcc error: No match for 'operator+' in '5 + a'. Oplossing? © Harry Broeders

Globale operator+ overloading OGOPRG 3 april 2017 Globale operator+ overloading Je kunt de globale operator+ overloaden. class Breuk { public: // ... Breuk& operator+=(const Breuk& rechts); const Breuk operator+(const Breuk& rechts) const; private: }; const Breuk operator+(int links, const Breuk& rechts); const Breuk operator+(int links, const Breuk& rechts) { Breuk hulpje(links); hulpje += rechts; return hulpje; } © Harry Broeders

Fix: Breuk::operator+ OGOPRG 3 april 2017 Fix: Breuk::operator+ Breuk(5) { Breuk a, b; b = a + 5; b = 5 + a; } b.operator=(a.operator+(5)); b.operator=(operator+(5, a)); Kan dit niet eenvoudiger? © Harry Broeders

Globale operator+ overloading OGOPRG 3 april 2017 Globale operator+ overloading Alternatief: class Breuk { public: // ... Breuk& operator+=(const Breuk& rechts); private: }; const Breuk operator+(const Breuk& links, const Breuk& rechts); const Breuk operator+(const Breuk& links, const Breuk& rechts) { Breuk hulpje(links); hulpje += rechts; return hulpje; } © Harry Broeders

Fix: Breuk::operator+ OGOPRG 3 april 2017 Fix: Breuk::operator+ Breuk(5) { Breuk a, b; b = a + 5; b = 5 + a; } b.operator=(operator+(a, 5)); Breuk(5) b.operator=(operator+(5, a)); © Harry Broeders

Operator== overloading OGOPRG 3 april 2017 Operator== overloading { Breuk a, b; if (a == b) /* ... */; } if (operator==(a, b)) Wat moet operator== eigenlijk doen? Waarom heb ik de globale operator== gebruikt en niet Breuk::operator== ? Wat moeten de parametertypes zijn? Breuk Goed const Breuk& Beter! Voorkomt onnodig kopietje. Wat moet het returntype zijn? bool Goed © Harry Broeders

Operator== overloading OGOPRG 3 april 2017 Operator== overloading Je kunt de globale operator== overloaden. class Breuk { public: // ... int teller() const; int noemer() const; private: }; bool operator==(const Breuk& l, const Breuk& r); bool operator==(const Breuk& l, const Breuk& r) { return l.teller() == r.teller() && l.noemer() == r.noemer(); } © Harry Broeders

Breuk::operator== Waarom is de volgende implementatie niet juist! OGOPRG 3 april 2017 Breuk::operator== Waarom is de volgende implementatie niet juist! class Breuk { public: // ... private: int boven; int onder; }; bool operator==(const Breuk& l, const Breuk& r); bool operator==(const Breuk& l, const Breuk& r) { return l.boven == r.boven && l.onder == r.onder; } Error: boven en onder zijn private! Wat te doen als er geen teller() en noemer() memberfuncties zijn ? © Harry Broeders

Breuk::operator== Friend! class Breuk { public: // ... private: OGOPRG 3 april 2017 Breuk::operator== Friend! class Breuk { public: // ... private: int boven; int onder; friend bool operator==(const Breuk& l, const Breuk& r); }; bool operator==(const Breuk& l, const Breuk& r) { return l.boven == r.boven && l.onder == r.onder; } © Harry Broeders

A friend is someone who may touch your private parts. OGOPRG 3 april 2017 Friend Vriendschap in C++ gaat wel erg ver ... Geldt bij het gebruik van friend nog steeds het principe van information hiding? A friend is someone who may touch your private parts. © Harry Broeders

Denk aan OO “afschuiven”! OGOPRG 3 april 2017 Huiswerk! Bestudeer dictaat 2.21 t/m 2.27. Let op! 2.24 en 2.25 zijn niet behandeld (mag je overslaan). Maak een operator*= voor Breuk. Maak een operator* voor Breuk. Maak een operator!= voor Breuk. Maak een operator< voor Breuk. Maak een operator<= voor Breuk. Maak een operator> voor Breuk. Maak een operator>= voor Breuk. Denk aan OO “afschuiven”! © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 7 © Harry Broeders

Operator<< overloading OGOPRG 3 april 2017 Operator<< overloading We willen breuken op dezelfde manier afdrukken als integers. ostream aanpassen? { Breuk b(12, -9); cout << "b = " << b << endl; // ... } Bestaat al! Zelf maken Bestaat al! cout.operator<<("b = ").operator<<(b). operator<<(endl); Object van de class ostream © Harry Broeders

Operator<< overloading OGOPRG 3 april 2017 Operator<< overloading We willen breuken op dezelfde manier afdrukken als integers. Globale operator<< overloaden { Breuk b(12, -9); cout << "b = " << b << endl; // ... } Zelf maken Bestaat al! Bestaat al! operator<<(cout.operator<<("b = "), b).operator<<(endl); Object van de class ostream © Harry Broeders

Operator<< overloading OGOPRG 3 april 2017 Operator<< overloading operator<<(cout, a). operator<<(endl); { Breuk a; cout << a << endl; } Wat moet het eerste parametertype zijn? ostream De uitvoer moet niet naar een kopietje van het beeldschermgeheugen. ostream& Goed Wat moet het tweede parametertype zijn? Breuk Goed const Breuk& Beter! Voorkomt onnodig kopietje. Wat moet het returntype zijn? ostream De endl moet niet naar een kopietje van het beeldschermgeheugen. © Harry Broeders

Operator<< class Breuk { public: // ... private: int boven; OGOPRG 3 april 2017 Operator<< class Breuk { public: // ... private: int boven; int onder; friend ostream& operator<<(ostream& left, const Breuk& right); }; ostream& operator<<(ostream& left, const Breuk& right) { left << right.boven << '/' << right.onder; return left; } © Harry Broeders

OGOPRG 3 april 2017 Gemak van overerving Er zijn verschillende classes afgeleid van ostream. ostringstream Om te schrijven naar een string variabele. ofstream Om te schrijven naar een file. De overloaded operator<< kan ook met objecten van deze afgeleide classes worden gebruikt. ostream ostringstream ofstream © Harry Broeders

Gaat goed! Want ofstream “is een” ostream. OGOPRG 3 april 2017 Gemak van overerving class Breuk { // ... friend ostream& operator<<(ostream& left, const Breuk& right); }; int main() { Breuk b(12,-9); ofstream out("uitvoer.txt"); if (out) out << "b = " << b << endl; else cerr << "File uitvoer.txt kan niet geopend worden!" << endl; cin.get(); return 0; } Gaat goed! Want ofstream “is een” ostream. © Harry Broeders

Operator>> overloading OGOPRG 3 april 2017 Operator>> overloading We willen breuken op dezelfde manier inlezen als integers. istream aanpassen? { int i, j; Breuk b; cin >> i >> b >> j; // ... } Bestaat al! Zelf maken Bestaat al! cin.operator>>(i).operator>>(b). operator>>(j); Object van de class istream © Harry Broeders

Operator>> overloading OGOPRG 3 april 2017 Operator>> overloading We willen breuken op dezelfde manier inlezen als integers. Globale operator>> overloaden { int i, j; Breuk b; cin >> i >> b >> j; // ... } Zelf maken Bestaat al! Bestaat al! operator>>(cin.operator>>(i), b). operator>>(j); Object van de class istream © Harry Broeders

Operator>> overloading OGOPRG 3 april 2017 Operator>> overloading operator>>(cin, a). operator>>(i); { Breuk a; int i; cin >> a >> i; } Wat moet het eerste parametertype zijn? istream De invoer moet niet worden gelezen uit een kopietje van het toetsenbordbuffer. istream& Goed Wat moet het tweede parametertype zijn? Breuk De invoer moet niet naar een kopietje van a. Breuk& Goed Wat moet het returntype zijn? istream i moet niet worden gelezen uit een kopietje van het toetsenbordbuffer. © Harry Broeders

Deze operator>> hoeft geen friend te zijn van de class Breuk OGOPRG 3 april 2017 Operator>> istream& operator>>(istream& left, Breuk& right) { int teller; if (isdigit(left.peek()) && left >> teller) if (left.peek() == '/') { left.get(); int noemer; if (isdigit(left.peek()) && left >> noemer) right = Breuk(teller, noemer); else right = Breuk(teller); } right = Breuk(); return left; Deze operator>> hoeft geen friend te zijn van de class Breuk © Harry Broeders

OGOPRG 3 april 2017 Huiswerk! Bestudeer dictaat 2.28. © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 8 © Harry Broeders

Seperate compilation Memcell.h Memcell.cpp Memappl.cpp OGOPRG 3 april 2017 Seperate compilation Memcell.h #ifndef _Memcell_ #define _Memcell_ class MemoryCell { public: int Read() const; void Write(int x); private: int StoredValue; }; #endif Memcell.cpp #include "Memcell.h" int MemoryCell::Read() const { return StoredValue; } void MemoryCell::Write(int x) { StoredValue = x; Memappl.cpp #include <iostream> using namespace std; #include "Memcell.h" int main() { MemoryCell M; M.Write(5); cout << "Cell contents are " << M.Read() << endl; © Harry Broeders

Seperate compilation pre-compiler compiler linker Memcell.h OGOPRG 3 april 2017 Seperate compilation pre-compiler Memcell.h compiler class MemoryCell { // ... }; linker Memcell.cpp Memcell.obj Memcell.exe #include "Memcell.h" // ... int MemoryCell::Read() { Memappl.cpp Memappl.obj #include "Memcell.h" // ... MemoryCell M; © Harry Broeders

OGOPRG 3 april 2017 Project Microsoft Visual C++ 2013 © Harry Broeders

Copy – Paste is slecht voor de onderhoudbaarheid! OGOPRG 3 april 2017 Hergebruik void swap(int& p, int& q) { int t = p; p = q; q = t; } // ... int i = 3; int j = 4; swap(i, j); Copy – Paste is slecht voor de onderhoudbaarheid! Wat te doen als we twee variabelen van het type double willen verwisselen? Wat te doen als we twee objecten van de class Breuk willen verwisselen? © Harry Broeders

Generieke functie Gebruik een template functie. OGOPRG 3 april 2017 Generieke functie Gebruik een template functie. template <typename T> void swap(T& p, T& q) { T t = p; p = q; q = t; } // ... int i = 3; int j = 4; swap(i, j); Breuk b(1, 2); Breuk c(3, 4); swap(b, c); Een template is een “mal” waarmee verschillende functies “gemaakt” kunnen worden void swap(int& p, int& q) { int t = p; p = q; q = t; } void swap(Breuk& p, Breuk& q) { Breuk t = p; p = q; q = t; } © Harry Broeders

Class Dozijn In de class Dozijn kun je 12 integers opslaan. OGOPRG 3 april 2017 Class Dozijn In de class Dozijn kun je 12 integers opslaan. class Dozijn { public: void zetIn(int index, int waarde); int leesUit(int index) const; private: int data[12]; }; // ... Dozijn d; d.zetIn(3, 13); cout << "De plaats nummer 3 in d bevat de waarde: " << d.leesUit(3) << endl; © Harry Broeders

Class Dozijn void Dozijn::zetIn(int index, int waarde) { OGOPRG 3 april 2017 Class Dozijn void Dozijn::zetIn(int index, int waarde) { if (index >= 0 && index < 12) data[index] = waarde; } int Dozijn::leesUit(int index) const { return data[index]; return 0; /* ik weet niets beters */ ostream& operator<<(ostream& o, const Dozijn& d) { o << d.leesUit(0); for (int i = 1; i < 12; ++i) o << ", " << d.leesUit(i); return o; © Harry Broeders

Copy – Paste is slecht voor de onderhoudbaarheid! OGOPRG 3 april 2017 Class Dozijn int main() { Dozijn d1; for (int j = 0; j < 12; ++j) d1.zetIn(j, j * j); // vul d1 met kwadraten cout << "d1 = " << d1 << endl; cin.get(); return 0; } Copy – Paste is slecht voor de onderhoudbaarheid! d1 = 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121 Wat te doen als we 12 variabelen van het type double willen opslaan? Wat te doen als we 12 objecten van de class Breuk willen opslaan? © Harry Broeders

Generieke class Gebruik een template class. OGOPRG 3 april 2017 Generieke class Gebruik een template class. template<typename T> class Dozijn { public: void zetIn(int index, const T& waarde); const T& leesUit(int index) const; private: T data[12]; }; // ... Dozijn<int> di; Een template is een “mal” waarmee verschillende classes “gemaakt” kunnen worden class Dozijn { public: void zetIn(int index, const int& waarde); const int& leesUit(int index) const; private: int data[12]; }; © Harry Broeders

Generieke class Dozijn OGOPRG 3 april 2017 Generieke class Dozijn template<typename T> void Dozijn<T>::zetIn(int index, const T& waarde) { if (index >= 0 && index < 12) data[index] = waarde; } template<typename T> const T& Dozijn<T>::leesUit(int index) const { if (index < 0) index = 0; if (index > 11) index = 11; return data[index]; ostream& operator<<(ostream& o, const Dozijn<T>& d) { o << d.leesUit(0); for (int i = 1; i < 12; ++i) o << ", " << d.leesUit(i); return o; © Harry Broeders

Generieke class Dozijn OGOPRG 3 april 2017 Generieke class Dozijn int main() { Dozijn<int> d1; for (int j = 0; j < 12; ++j) d1.zetIn(j, j * j); // vul d1 met kwadraten cout << "d1 = " << d1 << endl; Dozijn<string> d2; d2.zetIn(0, "Drenthe"); d2.zetIn(1, "Flevoland"); // ... d2.zetIn(10, "Zeeland"); d2.zetIn(11, "Zuid-Holland"); cout << "d2 = " << d2 << endl; cin.get(); return 0; } d1 = 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121 d2 = Drenthe, Flevoland, Friesland, Gelderland, Groningen, Limburg, Noord-Brabant, Noord-Holland, Overijssel, Utrecht, Zeeland, Zuid-Holland Wat doen we als we meer/minder dan 12 elementen willen opslaan? © Harry Broeders

Generieke class Gebruik een tweede template parameter. OGOPRG 3 april 2017 Generieke class Gebruik een tweede template parameter. template<typename T, int N> class Rij { public: void zetIn(int index, const T& waarde); const T& leesUit(int index) const; int aantalPlaatsen() const; private: T data[N]; }; // ... Rij<char, 26> alfabet; Een template is een “mal” waarmee verschillende classes “gemaakt” kunnen worden class Rij { public: void zetIn(int index, const char& waarde); const char& leesUit(int index) const; int aantalPlaatsen() const; private: char data[26]; }; © Harry Broeders

OGOPRG 3 april 2017 Generieke class Rij template<typename T, int N> void Rij<T, N>::zetIn(int index, const T& waarde) { if (index >= 0 && index < N) data[index] = waarde; } template<typename T, int N> const T& Rij<T, N>::leesUit(int index) const { if (index < 0) index = 0; if (index > N - 1) index = N - 1; return data[index]; template<typename T, int N> int Rij<T, N>::aantalPlaatsen() const { return N; template<typename T, int N> ostream& operator<<(ostream& o, const Rij<T, N>& r) { o << r.leesUit(0); for (int i = 1; i < N; ++i) o << ", " << r.leesUit(i); return o; © Harry Broeders

Generieke class Rij int main() { Rij<int, 10> kwad; OGOPRG 3 april 2017 Generieke class Rij int main() { Rij<int, 10> kwad; for (int i = 0; i < kwad.aantalPlaatsen(); ++i) kwad.zetIn(i, i * i); cout << "kwad = " << kwad << endl; Rij<char, 26> alfabet; for (int i = 0; i < alfabet.aantalPlaatsen(); ++i) alfabet.zetIn(i, 'A' + i); cout << "alfabet = " << alfabet << endl; cout << "de derde letter van alfabet is " << alfabet.leesuit(2) << endl; cout << "de honderste letter van alfabet is " << alfabet.leesuit(99) << endl; cin.get(); return 0; } kwad = 0, 1, 4, 9, 16, 25, 36, 49, 64, 81 alfabet = A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z de derde letter van alfabet is C de honderste letter van alfabet is Z © Harry Broeders

Template class std::array C++11 OGOPRG 3 april 2017 Template class std::array C++11 std::array<T, N> in C++ vervangt de C array. Het aantal elementen N ligt vast na het compileren. Elementen kunnen worden opgevraagd met operator[]. Je kunt een std::array “gewoon” vergelijken, toekennen en kopiëren. Je kunt een std::array element voor element doorlopen met een range-based for. std::array heeft memberfuncties: size() geeft het aantal elementen (type: std::array<T, N>::size_type). at(n) geeft reference naar element n. Geeft een fout (exception) als element n niet bestaat. © Harry Broeders

Template class std::array C++11 #include <iostream> #include <array> using namespace std; int main() { // definieer array van 15 integers array<int, 15> a; // vul met kwadraten for (array<int, 15>::size_type i = 0; i < a.size(); ++i) { a[i] = i * i; } // druk af cout << a[i] << " "; cout << endl; // ...

Template class std::array C++11 #include <iostream> #include <array> using namespace std; int main() { // definieer array van 15 integers array<int, 15> a; // vul met kwadraten for (decltype(a.size()) i = 0; i < a.size(); ++i) { a[i] = i * i; } // druk af cout << a[i] << " "; cout << endl; // ... decltype geeft het type van een expressie Waarom werkt auto hier niet?

Template class std::array C++11 #include <iostream> #include <array> using namespace std; int main() { // definieer array van 15 integers array<int, 15> a; // vul met kwadraten int i = 0; for (int& e: a) { e = i * i; ++i; } // druk af for (int e: a) { cout << e << " "; cout << endl; // ...

Template class std::vector OGOPRG 3 april 2017 Template class std::vector std::vector<T> in C++ is een dynamische array. De std::vector kan groeien en krimpen. Elementen kunnen worden opgevraagd met operator[]. Je kunt een std::vector “gewoon” vergelijken, toekennen en kopiëren. Je kunt een std::vector element voor element doorlopen met een range-based for. std::vector heeft memberfuncties: size() geeft het aantal elementen (type: std::vector<T>::size_type). at(n) geeft reference naar element n. Geeft een fout (exception) als element n niet bestaat. push_back(e) voeg element e aan de vector toe. © Harry Broeders

Template class std::vector OGOPRG 3 april 2017 Template class std::vector #include <iostream> #include <vector> using namespace std; int main() { // definieer vector van integers vector<int> v; // vul met kwadraten for (int i = 0; i < 15; ++i) { v.push_back(i * i); } // druk af for (vector<int>::size_type i = 0; i < v.size(); ++i) { cout << v[i] << " "; cout << endl; // ... © Harry Broeders

Template class std::vector C++11 OGOPRG 3 april 2017 Template class std::vector C++11 #include <iostream> #include <vector> using namespace std; int main() { // definieer vector van integers vector<int> v; // vul met kwadraten for (int i = 0; i < 15; ++i) { v.push_back(i * i); } // druk af for (decltype(v.size()) i = 0; i < v.size(); ++i) { cout << v[i] << " "; cout << endl; // ... © Harry Broeders

Template class std::vector C++11 OGOPRG 3 april 2017 Template class std::vector C++11 #include <iostream> #include <vector> using namespace std; int main() { // definieer vector van integers vector<int> v; // vul met kwadraten for (int i = 0; i < 15; ++i) { v.push_back(i * i); } // druk af for (int e: v) { cout << e << " "; cout << endl; // ... © Harry Broeders

Huiswerk! Bestudeer dictaat 2.29. OGOPRG 3 april 2017 Huiswerk! Bestudeer dictaat 2.29. Bestudeer dictaat (heel) hoofdstuk 3. © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 9 © Harry Broeders

Hergebruik van classes OGOPRG 3 april 2017 Hergebruik van classes Aggregatie (Aggregation) ... heeft een (of meer) ... Overerving (Inheritance) ... is een (speciaal soort) ... © Harry Broeders

Een Rechthoek heeft een lengte en een breedte van het type Breuk. OGOPRG 3 april 2017 Aggregatie Aggregatie (Aggregation) ... heeft een (of meer) ... class Rechthoek { public: // ... private: Breuk lengte; Breuk breedte; }; Een Rechthoek heeft een lengte en een breedte van het type Breuk. © Harry Broeders

Een Bloemiste is een (speciaal soort) Winkelier. OGOPRG 3 april 2017 Overerving Overerving (Inheritance) ... is een (speciaal soort) ... class Winkelier { // ... }; class Bloemiste: public Winkelier { Een Bloemiste is een (speciaal soort) Winkelier. © Harry Broeders

Niet goed uitbreidbaar! OGOPRG 3 april 2017 ADT aanpak enum Soort {sintBernard, tekkel}; class Hond { private: Soort s; // ... public: Krant haalKrant(); void blaf(); }; Krant Hond::haalKrant() { blaf(); return krant; } Niet goed uitbreidbaar! void Hond::blaf() { switch (s) { case sintBernard: cout << "WOEF WOEF"; break; case tekkel: cout << "kef kef"; } © Harry Broeders

Message kan overridden worden. OGOPRG 3 april 2017 OO aanpak class Hond { private: // ... public: Krant haalKrant(); virtual void blaf(); }; Krant Hond::haalKrant() { blaf(); return krant; } void Hond::blaf() { cout << "blaf blaf"; Een Tekkel is een Hond. Een SintBernard is een Hond. Message kan overridden worden. © Harry Broeders

OO aanpak class SintBernard: public Hond { private: Whisky vat; OGOPRG 3 april 2017 OO aanpak class SintBernard: public Hond { private: Whisky vat; public: virtual void blaf(); }; void SintBernard::blaf() { cout << "WOEF WOEF"; } class Tekkel: public Hond { public: virtual void blaf(); }; void Tekkel::blaf() { cout << "kef kef"; } © Harry Broeders

Polymorfisme h is een polymorfe parameter. OGOPRG 3 april 2017 Polymorfisme void doeJeWerk(Hond& h) { Krant k = h.haalKrant(); // ... } h is een polymorfe parameter. doeJeWerk is een polymorfe functie. int main() { SintBernard Boris; Tekkel Harry; if (!weekend) doeJeWerk(Harry); else if (zaterdag) doeJeWerk(Boris); cin.get(); return 0; } Harry is van de class Tekkel maar een Tekkel is een Hond. Boris is van de class SintBernard maar een SintBernard is een Hond. © Harry Broeders

OGOPRG 3 april 2017 Uitbreidbaarheid Door de OO aanpak kan heel eenvoudig een nieuwe soort hond worden toegevoegd. Voeg zelf de classes DuitseHerder en MechelseHerder toe. Welke code moet nu gewijzigd worden? Welke code moet nu opnieuw gecompileerd worden? © Harry Broeders

Huiswerk! Bestudeer dictaat hoofdstuk 4 t/m 4.2. OGOPRG 3 april 2017 Huiswerk! Bestudeer dictaat hoofdstuk 4 t/m 4.2. Voeg zelf zelf de classes DuitseHerder en MechelseHerder toe. Gegeven is dat beide rassen Herdershonden zijn die een schapenkudde kunnen drijven en hoeden. Elk ras heeft een eigen blaf. Beantwoord de vragen op de vorige sheet. © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 10 © Harry Broeders

Uitwerking Huiswerk Voeg DuitseHerder en MechelseHerder toe. OGOPRG 3 april 2017 Uitwerking Huiswerk Voeg DuitseHerder en MechelseHerder toe. Welke code moet gewijzigd worden? Welke code moet gecompileerd worden? © Harry Broeders

OGOPRG 3 april 2017 Tiroler Herder © Toon van Driel © Harry Broeders

OGOPRG 3 april 2017 Tiroler Herder © Toon van Driel © Harry Broeders

Inline memberfuncties OGOPRG 3 april 2017 Inline memberfuncties class Hond { public: virtual void blaf() { cout << "blaf blaf"; } }; class SintBernard: public Hond { cout << "WOEF"; private: Whisky vat; Definitie van de memberfuncties staat in de class declaratie. Nadeel: Component kan niet zonder source geleverd worden. Voordeel: Minder typen. © Harry Broeders

Boodschap sturen via pointer OGOPRG 3 april 2017 Boodschap sturen via pointer class Hond { public: virtual void blaf() { cout << "blaf blaf" << endl; } }; int main() { Hond fikkie; fikkie.blaf(); Hond* phond(&fikkie); *phond.blaf(); (*phond).blaf(); phond->blaf(); Error: left of '.blaf' must have class/struct Ok Handige afkorting © Harry Broeders

? ? Slicing problem polymorfisme werkt alleen bij * en &. Waar blijft OGOPRG 3 april 2017 Slicing problem polymorfisme werkt alleen bij * en &. class Hond { public: virtual void blaf() { cout << "blaf" << endl; } }; class SintBernard: public Hond { cout << "WOEF" <<endl; private: Whisky vat; Waar blijft de whisky? ? ? Waarom geen: SintBernard& Waarom geen: SintBernard* int main() { SintBernard boris; Hond& rhond = boris; rhond.blaf(); Hond* phond = &boris; phond->blaf(); Hond hond = boris; hond.blaf(); Niet Polymorf ! © Harry Broeders

Oplossing voor het Slicing Problem OGOPRG 3 april 2017 Abstract Base Class class Hond { private: // ... public: Krant haalKrant(); virtual void blaf() = 0; }; Krant Hond::haalKrant() { blaf(); return krant; } Er kunnen geen objecten (variabelen) van een ABC gedefinieerd worden. Een class die overerft van Hond en blaf() override is geen ABC meer. Een class die overerft van Hond en blaf() niet override is een ABC. Puur virtueel Oplossing voor het Slicing Problem © Harry Broeders

Slicing problem polymorfisme werkt alleen bij * en &. Hond is een ABC OGOPRG 3 april 2017 Slicing problem polymorfisme werkt alleen bij * en &. Hond is een ABC class Hond { public: virtual void blaf() = 0; }; class SintBernard: public Hond { virtual void blaf() { cout << "WOEF" << endl; } private: Whisky vat; int main() { SintBernard boris; Hond& rhond = boris; rhond.blaf(); Hond* phond = &boris; phond->blaf(); Hond hond = boris; Error: 'Hond' : cannot instantiate abstract class due to following members: 'void Hond::blaf(void)' : is abstract © Harry Broeders

Slicing Problem Maak alle base classes abstract. Kan niet altijd: OGOPRG 3 april 2017 Slicing Problem Maak alle base classes abstract. Compiler voorkomt slicing! Kan niet altijd: Hergebruik class van een andere programmeur (evt. zonder source code). Je moet nu zelf slicing voorkomen! © Harry Broeders

Nodig bij practicumopdracht 3a OGOPRG 3 april 2017 Huiswerk! Bestudeer dictaat paragraaf 4.3 t/m 4.5 en 4.11. 4.3: Memberfunctie overriding. Vanuit de in de derived class overridden memberfunctie kun je de originele functie in de base class aanroepen. 4.4: Abstract base class. 4.5: Constructors bij inheritance. Vanuit de constructor van de derived wordt automatisch de constructor van de base class aangeroepen. Je kunt ook zelf vanuit de constructor van de derived class een constructor in de base class aanroepen. 4.11: Slicing problem. Nodig bij practicumopdracht 3a © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 11 © Harry Broeders

Overloading van memberfuncties OGOPRG 3 april 2017 Overloading van memberfuncties class Class { public: void f() const { cout << "Ik ben f()" << endl; } void f(int i) const { // overload f() cout << "Ik ben f(int)" << endl; }; int main() { Class object; object.f(); object.f(3); // ... Uitvoer: Ik ben f() Ik ben f(int) © Harry Broeders

Overloading en overerving OGOPRG 3 april 2017 Overloading en overerving class Base { public: void f() const { cout << "Ik ben f()" << endl; } }; class Derived: public Base { void f(int i) const { // Verberg f() cout << "Ik ben f(int)" << endl; Hiding-rule Error: 'Derived::f' : function does not take 0 arguments int main() { Base b; Derived d; b.f(); d.f(3); d.f(); d.Base::f(); } Uitvoer: Ik ben f() Ik ben f(int) Conclusie: Overloading en overerving gaan niet goed samen! © Harry Broeders

Reden voor de hiding-rule OGOPRG 3 april 2017 Reden voor de hiding-rule // Code van Bas class Base { public: // geen f(...) }; // Code van Dewi class Derived: public Base { void f(double d) const { cout << "Ik ben f(double)" << endl; } int main() { Derived d; d.f(3); // ... Uitvoer: Ik ben f(double) © Harry Broeders

Reden voor de hiding-rule OGOPRG 3 april 2017 Reden voor de hiding-rule // Aangepaste code van Bas class Base { public: // ... void f(int i) const { cout << "Ik ben f(int)" << endl; } }; // Code van Dewi niet gewijzigd int main() { Derived d; d.f(3); // Base::f(int) is hidden. Gelukkig maar! Conclusie: De hiding-rule verhoogt de onderhoudbaarheid! Uitvoer: Ik ben f(double) © Harry Broeders

Explicit overriding C++11 Sinds C++11 kun je expliciet aangeven dat je een memberfunctie wilt overridden. Dit voorkomt dat je een memberfunctie “per ongeluk” overload. Dit doe je door het woord override achter de memberfunctie te plaatsen. De compiler geeft nu een foutmelding als er geen overriding wordt gebruikt.

Explicit overriding C++11 OGOPRG 3 april 2017 Explicit overriding C++11 OOPS: virtual vergeten! class Base { public: void f(int i) const { cout << "Base::f(int) called." << endl; } virtual void g(int i) const { cout << "Base::g(int) called." << endl; }; class Derived: public Base { void f(int i) const override { cout << "Derived::f(int) called." << endl; virtual void g(int i) override { cout << "Derived::g(int) called." << endl; Error: 'Derived::f' : method with override specifier 'override' did not override any base class methods Error: 'Derived::g' : method with override specifier 'override' did not override any base class methods OOPS: const vergeten! © Harry Broeders

Final overriding C++11 Je hebt blaf() in Herdershond overridden maar je wilt niet dat blaf() in classes die afgeleid zijn van Herdershond opnieuw overridden wordt.

Final overriding C++11 class Herdershond: public Hond { public: virtual void blaf() final; // ... }; class DuitseHerder: public Herdershond { virtual void blaf(); Error: 'Herdershond::blaf()': declared as 'final' cannot be overridden by 'DuitseHerder::blaf'

Afscherming private: protected: public: Zie dictaat paragraaf 4.6. OGOPRG 3 april 2017 Afscherming private: alleen bereikbaar in member functies van de class zelf protected: alleen bereikbaar in member functies van de class en in member functies van "nakomelingen" van de class public: altijd bereikbaar via object Zie dictaat paragraaf 4.6. © Harry Broeders

Proeftentamen Tentamenopgaven over de tot nu toe behandelde stof. OGOPRG 3 april 2017 Proeftentamen Tentamenopgaven over de tot nu toe behandelde stof. © Harry Broeders

Nodig bij practicumopdracht 3c OGOPRG 3 april 2017 Huiswerk! Bestudeer dictaat paragraaf 4.6 t/m 4.10, 4.12 en 4.13. 4.6: protected members. 4.7: Voorbeeld: ADC kaarten. 4.8: Overloading en overriding van memberfuncties. 4.9: Expliciet overridden van memberfuncties. 4.10: Final overridden van memberfuncties. 4.12 Voorbeeld: Opslaan van polymorfe objecten in een vector. 4.13 Voorbeeld: Impedantie calculator. Nodig bij practicumopdracht 3c © Harry Broeders

Huiswerk! http://bd.eduweb.hhs.nl/ogoprg/pdf/proeftentamen_1.pdf OGOPRG 3 april 2017 Huiswerk! Maak het proeftentamen. http://bd.eduweb.hhs.nl/ogoprg/pdf/proeftentamen_1.pdf © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 12 © Harry Broeders

Huiswerk! Bestudeer boek: Warmer & Kleppe, Praktisch UML, 5de editie. OGOPRG 3 april 2017 Huiswerk! Bestudeer boek: Warmer & Kleppe, Praktisch UML, 5de editie. H1 en H2 H4 t/m 4.3 © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 13 © Harry Broeders

Software Engineering Fases OGOPRG 3 april 2017 Software Engineering Fases Wat wil de klant? Analyse (find the requirements). Hoe kun je het maken? Design (structured or OO). Waarmee kun je het maken? Implement (write the code). Werkt het? Test (verify and validate). Verification: Have we built the system right? Does the system satisfy its specification? Validation: have we built the right system? Does the specification satisfy the customer's expectation? © Harry Broeders

Software Engineering Waterval methode OGOPRG 3 april 2017 Software Engineering Waterval methode Traditionele methode. Geschikt voor projecten met weinig risico. Past goed bij gestructureerde aanpak. Spiraal methode (Evolutionaire methode.) Moderne methode. Geschikt voor projecten met veel risico (onzekerheid). Past goed bij OO aanpak. © Harry Broeders

Waterval = sequentieel OGOPRG 3 april 2017 Waterval = sequentieel Analyse Design Implement Test © Harry Broeders

Versnellen door in elkaar schuiven van waterval model geeft problemen! OGOPRG 3 april 2017 Tijdsdruk... Versnellen door in elkaar schuiven van waterval model geeft problemen! © Harry Broeders

Typische duur van één cyclus: 3 weken! OGOPRG 3 april 2017 Spiraal = cyclisch Analyse Test Typische duur van één cyclus: 3 weken! Implement Design © Harry Broeders

Modelleren Werkelijkheid model

Wat modelleren we? Analyse Ontwerp Implementatie OGOPRG 3 april 2017 Wat modelleren we? Analyse Maak een model van de te automatiseren werkelijkheid of van het op te lossen probleem. Domeinkennis  structuur. Functionele eisen  gedrag. Ontwerp Maak een model van de oplossing. Implementatie Maak een model van het programma. Bij OOA+OOD+OOP werken we steeds aan hetzelfde model (seamless development) © Harry Broeders

Unified Modeling Language OGOPRG 3 april 2017 Unified Modeling Language UML inleiding. Hoofdstuk 1 en 2. UML Klasse- en objectdiagram (1). Paragraaf 4.1 t/m 4.3, 4.4.2, 4.4.8, 4.4.9 en 4.4.17. UML Use-case-diagram. Paragraaf 8.1 t/m 8.6. UML Sequentie- en communicatiediagram. Paragraaf 10.1 t/m 10.4. UML Toestands- en Activiteitsdiagram. Paragraaf 12.1 t/m 12.3 en H15.1 t/m 15.3. UML Klassediagram (2) Paragraaf 4.4.4, 4.4.10 en 4.4.12. © Harry Broeders

Visual Paradigm for UML OGOPRG 3 april 2017 Visual Paradigm for UML Tekenen van UML diagrammen. Omzetten UML naar C++ (of Java, C#, Python enz). Omzetten C++ (of Java, C#, Python) naar UML. Beschikbaar in lokaal D1.052 (en ook thuis). © Harry Broeders

Visual Paradigm for UML SE

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 14 © Harry Broeders

Klassediagram Attributes = data members OGOPRG 3 april 2017 Klassediagram Attributes = data members Operations = member functions = messages In Visual Paradigm for UML kunnen attributes en operations “verborgen” worden. © Harry Broeders

Objectdiagram Object is een instantie van een Class OGOPRG 3 april 2017 Objectdiagram Object is een instantie van een Class Attributes = data members In Visual Paradigm for UML kunnen attributes met waarden “verborgen” worden. © Harry Broeders

OGOPRG 3 april 2017 Fases Analysis Design Tijdens het ontwikkelen van het model voeg je steeds meer details toe. Deze details kun je ook weer verbergen, zie: Project Options. © Harry Broeders

Code generatie Twee methoden Instant generator is the process of producing source code from class model. Round-trip engineering is the ability to generate model from source code and generate source code from model, and keep them synchronized.

Implementation = Code generatie OGOPRG 3 april 2017 Implementation = Code generatie Rekening.h #ifndef __Rekening_h__ #define __Rekening_h__ class Rekening { public: bool open(); void stort(double bedrag); bool neemOp(double bedrag); private: double saldo; }; #endif Code moet nog worden ingevuld! Rekening.cpp #include "Rekening.h" bool Rekening::open() { } void Rekening::stort(double bedrag) { } bool Rekening::neemOp(double bedrag) { } © Harry Broeders

Implementation = Code generatie OGOPRG 3 april 2017 Implementation = Code generatie © Harry Broeders

Associatie Labels: Altijd invullen! OGOPRG 3 april 2017 Associatie Labels: Altijd invullen! Multipliciteit: eventueel invullen. Rol: eventueel invullen. Leesrichting: gebruiken om “onnatuurlijke” leesrichting aan te geven. © Harry Broeders

Overerving (... is een ... ) Directeur.h #ifndef __Directeur_h__ OGOPRG 3 april 2017 Overerving (... is een ... ) Directeur.h #ifndef __Directeur_h__ #define __Directeur_h__ #include "Persoon.h" class Directeur: public Persoon { }; #endif © Harry Broeders

Aggregatie (... heeft een ...) OGOPRG 3 april 2017 Aggregatie (... heeft een ...) Fiets heeft: 2 Wielen 1 Frame © Harry Broeders

Een compositie is een speciaal soort aggregatie. OGOPRG 3 april 2017 Associatie Beginnende UML modelleerders gebruiken vaak ten onrechte compositie! Overerving Aggregatie Compositie Een compositie is een speciaal soort aggregatie. Compositie “bevat een” relatie. deel behoort maar bij 1 geheel levensduur deel <= levensduur geheel Aggregatie “heeft een” relatie. vaag gedefinieerd © Harry Broeders

Compositie (... bevat een ...) OGOPRG 3 april 2017 Compositie (... bevat een ...) Welke aggregaties zijn composities? Mens --- Nier Mens --- Hersenen PC --- Hard Disk PC --- CPU CPU --- Transistor Radio --- Transistor Let op! Het goede antwoord is afhankelijk van de applicatie. © Harry Broeders

Compositie (... bevat een ...) OGOPRG 3 april 2017 Compositie (... bevat een ...) #ifndef __Fiets_h__ #define __Fiets_h__ #include "Frame.h" class Fiets { public: Frame Unnamed_Frame_; }; #endif © Harry Broeders

Compositie (... bevat een ...) OGOPRG 3 april 2017 Compositie (... bevat een ...) © Harry Broeders

Compositie (... bevat een ...) OGOPRG 3 april 2017 Compositie (... bevat een ...) #ifndef __Fiets_h__ #define __Fiets_h__ #include "Frame.h" class Fiets { private: Frame hetFrame; }; #endif © Harry Broeders

Compositie (... bevat een ...) OGOPRG 3 april 2017 Compositie (... bevat een ...) #ifndef __Frame_h__ #define __Frame_h__ #include "Fiets.h" class Frame { public: Fiets* Unnamed_Fiets_; }; #endif © Harry Broeders

Compositie (... bevat een ...) OGOPRG 3 april 2017 Compositie (... bevat een ...) © Harry Broeders

Compositie (... bevat een ...) OGOPRG 3 april 2017 Compositie (... bevat een ...) #ifndef __Fiets_h__ #define __Fiets_h__ #include "Frame.h" class Fiets { private: Frame hetFrame; }; #endif #ifndef __Frame_h__ #define __Frame_h__ class Frame { }; #endif © Harry Broeders

OGOPRG 3 april 2017 Commentaar © Harry Broeders

Huiswerk! Bestudeer boek: Warmer & Kleppe, Praktisch UML, 5de editie. OGOPRG 3 april 2017 Huiswerk! Bestudeer boek: Warmer & Kleppe, Praktisch UML, 5de editie. H1 en H2 H4 t/m 4.3, 4.4.2 en 4.4.8. Vragen bij H2 en H4 (zie BB) Bedenk hoe je een aggregatie (geen compositie) kunt implementeren. Zie dictaat: paragraaf 4.12. © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 15 © Harry Broeders

We willen van Hond graag een Abstract Base Class maken! OGOPRG 3 april 2017 Voorbeeld Waarom? We willen van Hond graag een Abstract Base Class maken! © Harry Broeders

Pure virtual member function

Pure virtual member function Pure virtual memberfunctie wordt in UML cursief weergegeven.

Abstract Base Class

ABC wordt in UML cursief weergegeven. Abstract Base Class ABC wordt in UML cursief weergegeven.

Aggregatie implementatie OGOPRG 3 april 2017 Aggregatie implementatie Hoe kunnen we een 0..1 aggregatie implementeren in class SintBernard? WhiskeyVat data member? WhiskeyVat& data member? WhiskeyVat* data member? Andere naam voor een WhiskeyVat dat al bestaat. Onzin! Niet 0..1 maar 1. © Harry Broeders

Aggregatie implementatie #ifndef __SintBernard_h__ #define __SintBernard_h__ class WhiskeyVat; class SintBernard { public: WhiskeyVat* heeft_om_zijn_nek; void blaf(); }; #endif

Aggregatie implementatie #ifndef __WhiskeyVat_h__ #define __WhiskeyVat_h__ class SintBernard; class WhiskeyVat { public: SintBernard* heeft_om_zijn_nek; }; #endif

Aggregatie implementatie

Aggregatie implementatie

Aggregatie implementatie #ifndef __SintBernard_h__ #define __SintBernard_h__ class WhiskeyVat; class SintBernard { public: void blaf(); private: WhiskeyVat* vat; }; #endif

Aggregatie implementatie OGOPRG 3 april 2017 Aggregatie implementatie Hoe kunnen we een 0..5 aggregatie implementeren in class Kennel? array met Hond* -ers array<Hond*, 5> vector<Hond*> Beter! Maar niet beschikbaar in Visual Paradigm Goed! Wel beschikbaar in Visual Paradigm, ook bruikbaar voor 0..* © Harry Broeders

Aggregatie implementatie OGOPRG 3 april 2017 Aggregatie implementatie #include <vector> using namespace std; #ifndef __Kennel_h__ #define __Kennel_h__ class Hond; class Kennel { private: std::vector<Hond*> inwoners; }; #endif Liever niet! © Harry Broeders

Bedenk eerst welke messages je naar een Kennel moet kunnen sturen. OGOPRG 3 april 2017 Opdracht Schrijf een testprogramma voor de hiervoor gemaakte class Kennel. Zet een SintBernard genaamd boris in de Kennel genaamd k. Zet een Tekkel genaamd harry in de Kennel k. Zet een SintBernard genaamd felix in de Kennel k. Laat alle honden in de Kennel k blaffen. Haal harry uit de Kennel k. Bedenk eerst welke messages je naar een Kennel moet kunnen sturen. © Harry Broeders

Waarom Hond& als parameter? OGOPRG 3 april 2017 Uitwerking #include <vector> #ifndef __Kennel_h__ #define __Kennel_h__ class Hond; class Kennel { private: std::vector<Hond*> inwoners; public: void zetIn(Hond& h); void haalUit(Hond& h); void blafAllemaal(); }; #endif Waarom Hond& als parameter? © Harry Broeders

Test Driven Development OGOPRG 3 april 2017 Uitwerking Schrijf altijd eerst het testprogramma! #include <iostream> using namespace std; #include "Hond.h" #include "SintBernard.h" #include "Tekkel.h" #include "Kennel.h" int main() { SintBernard boris; Kennel k; k.zetIn(boris); Tekkel harry; k.zetIn(harry); SintBernard felix; k.zetIn(felix); cout << "Alle honden in de kennel blaffen:" << endl; k.blafAllemaal(); k.haalUit(harry); cin.get(); return 0; } Test Driven Development Gewenste uitvoer: © Harry Broeders

Kennel implementatie #include <algorithm> OGOPRG 3 april 2017 Kennel implementatie #include <algorithm> #include <iostream> using namespace std; #include "Kennel.h" #include "Hond.h" void Kennel::zetIn(Hond& h) { if (inwoners.size() < 5) inwoners.push_back(&h); else cout << "Kennel is al vol!" << endl; } void Kennel::haalUit(Hond& h) { inwoners.erase(find(inwoners.begin(), inwoners.end(), &h)); void Kennel::blafAllemaal() { for (auto hp: inwoners) hp->blaf(); © Harry Broeders

Huiswerk! Bestudeer boek: Warmer & Kleppe, Praktisch UML, 5de editie. OGOPRG 3 april 2017 Huiswerk! Bestudeer boek: Warmer & Kleppe, Praktisch UML, 5de editie. 4.4.8 en 4.4.9. Bestudeer dictaat: paragraaf 4.12. © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 16 © Harry Broeders

UML diagrammen Statische structuur van programma. OGOPRG 3 april 2017 UML diagrammen Statische structuur van programma. UML Klassediagram. Dynamisch gedrag van programma. UML Objectdiagram. UML Use-case-diagram. UML Sequentiediagram. UML Communicatiediagram. UML Toestandsdiagram. UML Activiteitsdiagram. Use-case-diagram beschrijft het gedrag van het programma gezien vanuit de gebruikers van het programma. © Harry Broeders

OGOPRG 3 april 2017 UML Use-case-diagram Wordt gebruikt voor vastleggen van de functionele eisen. Use-case Actor Systeemgrens © Harry Broeders

Use-case beschrijving OGOPRG 3 april 2017 Use-case beschrijving Naam Rekening openen Actor Baliemedewerker Aannamen Baliemedewerker heeft beschikking over de NAW-gegevens van de Klant. De Klant kan zich legitimeren. Beschrijving De baliemedewerker maakt aan het systeem bekend dat een nieuwe rekening aangemaakt moet worden en voert de NAW-gegevens van de Klant in. Als de klant een bedrijf is wordt het KvK nummer ingevoerd. Het systeem controleert of de Klant al rekeningen heeft en of de Klant rood staat op een van deze rekening. In dat geval treedt een uitzondering [rood staan] op. Het systeem maakt het nummer van de nieuwe rekening bekend aan de baliemedewerker. Uitzonderingen [rood staan] De baliemedewerker kan naar de use-case Geld storten overgaan om de Klant de gelegenheid te geven het tekort aan te vullen. Als het tekort is aangevuld wordt de use-case vervolgd bij stap 3. Resultaat De Klant heeft minstens 1 rekening. © Harry Broeders

Use-case beschrijving OGOPRG 3 april 2017 Use-case beschrijving © Harry Broeders

Communicatiediagram laat zien welke objecten elkaar berichten sturen. OGOPRG 3 april 2017 UML diagrammen Statische structuur van programma. UML Klassediagram. Dynamisch gedrag van programma. UML Use-case-diagram. UML Sequentiediagram. UML Communicatiediagram. UML Toestandsdiagram. UML Activiteitsdiagram. Sequentiediagram laat zien in welke volgorde objecten elkaar berichten sturen. Communicatiediagram laat zien welke objecten elkaar berichten sturen. © Harry Broeders

wekker stuurt boodschap zoem naar :Gebruiker OGOPRG 3 april 2017 Sequentiediagram Boek (p.119): Object Actor wekker stuurt boodschap zoem naar :Gebruiker Boodschap Tijd Actor kan boodschap sturen naar object. Object kan boodschap sturen naar actor, andere objecten en naar zichzelf. © Harry Broeders

Sequentiediagram Verbeterde versie: OGOPRG 3 april 2017 © Harry Broeders

Bevat dezelfde informatie als een sequentiediagram. OGOPRG 3 april 2017 Communicatiediagram Bevat dezelfde informatie als een sequentiediagram. © Harry Broeders

Conditionele boodschappen OGOPRG 3 april 2017 Conditionele boodschappen © Harry Broeders

Conditionele boodschappen OGOPRG 3 april 2017 Conditionele boodschappen © Harry Broeders

Iteratie van boodschappen OGOPRG 3 april 2017 Iteratie van boodschappen © Harry Broeders

Iteratie van boodschappen OGOPRG 3 april 2017 Iteratie van boodschappen void Kennel::blafAllemaal() { for (auto hp: inwoners) hp->blaf(); } Visual Paradigm kan geen Sequence Diagram tekenen vanuit C++ code. Visual Paradigm kan geen code (ook geen Java) genereren vanuit een Sequence Diagram © Harry Broeders

OGOPRG 3 april 2017 Boodschap aan jezelf © Harry Broeders

OGOPRG 3 april 2017 Constructor © Harry Broeders

OGOPRG 3 april 2017 Voorbeeld (vervolg...) © Harry Broeders

OGOPRG 3 april 2017 Opgave Maak een sequentiediagram waarin een testprogramma de volgende acties uitvoert: Zet een SintBernard genaamd boris in de Kennel genaamd k. Zet een Tekkel genaamd harry in de Kennel k. Laat alle honden in de Kennel k blaffen. © Harry Broeders

OGOPRG 3 april 2017 Uitwerking © Harry Broeders

Huiswerk! Bestudeer boek: Warmer & Kleppe, Praktisch UML, 5de editie. OGOPRG 3 april 2017 Huiswerk! Bestudeer boek: Warmer & Kleppe, Praktisch UML, 5de editie. Hoofdstuk 8 (behalve 8.5.3 en 8.7.6). Hoofdstuk 10 (behalve 10.7). Opgaven bij H8, H10 (zie BB). Maak opgaven van voorgaande sheets: Sequentiediagram. © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 17 © Harry Broeders

UML diagrammen Statische structuur van programma. OGOPRG 3 april 2017 UML diagrammen Statische structuur van programma. UML Klassediagram. Dynamisch gedrag van programma. UML Use-case-diagram. UML Sequentiediagram. UML Communicatiediagram. UML Toestandsdiagram. UML Activiteitsdiagram. Toestandsdiagram laat de toestanden en toestandsovergangen van een klasse zien. © Harry Broeders

Worden we hier veel wijzer van? OGOPRG 3 april 2017 Toestandsdiagram Toestand van een WhiskeyVat Worden we hier veel wijzer van? © Harry Broeders

OGOPRG 3 april 2017 Toestandsdiagram © Harry Broeders

Toestandsdiagram #include "WhiskyVat_sm.h" class WhiskyVat { private: OGOPRG 3 april 2017 Toestandsdiagram #include "WhiskyVat_sm.h" class WhiskyVat { private: WhiskyVatContext _fsm; public: WhiskyVat(): _fsm(*this) { } WhiskyVatContext& getContext() { return _fsm; void maakVol() { _fsm.maakVol(); void maakLeeg() { _fsm.maakLeeg(); }; © Harry Broeders

Toestandsdiagram #include "WhiskyVat.h" OGOPRG 3 april 2017 Toestandsdiagram #include "WhiskyVat.h" void state_Leeg(WhiskyVat *aWhiskyVat) { printf("Please select transition:\n"); printf("1. maakVol\n"); printf("0. quit\n"); int choice; scanf("%d", &choice); switch (choice) { case 1: aWhiskyVat->maakVol(); break; case 0: exit(0); } void state_Vol(WhiskyVat *aWhiskyVat) { /* idem */ © Harry Broeders

Toestandsdiagram int main(int argc, char **argv) { OGOPRG 3 april 2017 Toestandsdiagram int main(int argc, char **argv) { WhiskyVat lWhiskyVat; while (true) { printf("Current state: %s\n", lWhiskyVat.getContext().getState().getName()); if (&lWhiskyVat.getContext().getState() == &WhiskyVatFSM::Leeg) { state_Leeg(&lWhiskyVat); } else if (&lWhiskyVat.getContext().getState() == &WhiskyVatFSM::Vol) { state_Vol(&lWhiskyVat); © Harry Broeders

Toestandsdiagram Current state: WhiskyVatFSM::Leeg OGOPRG 3 april 2017 Toestandsdiagram Current state: WhiskyVatFSM::Leeg Please select transition: 1. maakVol 0. quit 1 Current state: WhiskyVatFSM::Vol 1. maakLeeg © Harry Broeders

OGOPRG 3 april 2017 Opgave Teken een toestandsdiagram dat het login proces van een online bankapplicatie modelleert. Om in te loggen moet de klant een rekeningnummer en een pincode invoeren in twee invoervelden. In deze invoervelden mogen alleen cijfers worden ingevoerd. Wisselen tussen invoervelden kan met de TAB toets. Als de ENTER toets wordt ingedrukt dan moeten het ingevoerde rekeningnummer en pincode worden gecontroleerd. Geldig: start transactie. Ongeldig: geef foutmelding en wis invoervelden. Als op de ESC toets wordt gedrukt moet de login procedure worden afgebroken. © Harry Broeders

OGOPRG 3 april 2017 Uitwerking © Harry Broeders

Een Activiteitsdiagram laat een stroom van activiteiten zien. OGOPRG 3 april 2017 UML diagrammen Statische structuur van programma. UML Klassediagram. Dynamisch gedrag van programma. UML Use-case-diagram. UML Sequentiediagram. UML Communicatiediagram. UML Toestandsdiagram. UML Activiteitsdiagram. Een Activiteitsdiagram laat een stroom van activiteiten zien. © Harry Broeders

Activiteitsdiagram Start Swimlane Activiteit Guard Beslispunt Splitsing Synchronisatie Einde Samenkomst

Huiswerk! Bestudeer boek: Warmer & Kleppe, Praktisch UML, 5de editie. OGOPRG 3 april 2017 Huiswerk! Bestudeer boek: Warmer & Kleppe, Praktisch UML, 5de editie. Hoofdstuk 12. Hoofdstuk 15. H12 en H15 (zie BB). Maak opgaven van voorgaande sheets: Toestandsdiagram. © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 18 © Harry Broeders

Globaal en lokaal geheugen OGOPRG 3 april 2017 Globaal en lokaal geheugen int global; void f(int parameter) { int local1; // ... } void main() { int local2; f(local2); De compiler bepaalt wanneer variabelen worden aangemaakt en opgeruimd. © Harry Broeders

OGOPRG 3 april 2017 Dynamisch geheugen Je kunt ook zelf beslissen wanneer een variabele (object) wordt aangemaakt en opgeruimd. Tekkel* hp = new Tekkel; hp->blaf(); delete hp; Reserveer geheugenruimte (bij Operating System) Geef geheugenruimte vrij (aan Operating System) © Harry Broeders

OGOPRG 3 april 2017 Dynamische array Het geheugen wordt aangevraagd als het programma runt  grootte hoeft niet bij compileren bekend te zijn. Statisch: Dynamisch: size_t s; cout << "Hoeveel Tekkels wil je? "; cin >> s; Tekkel a[s]; for (auto t: a) t.blaf(); const size_t s = 5; Tekkel a[s]; for (auto t: a) t.blaf(); Error: expected constant expression size_t s; cout << "Hoeveel Tekkels wil je? "; cin >> s; Tekkel* c = new Tekkel[s]; for (size_t i = 0; i < s; ++i) c[i].blaf(); delete[] c; Range-based for werkt hier niet. © Harry Broeders

Gebruik zoveel mogelijk standaard componenten zoals std::vector OGOPRG 3 april 2017 Dynamisch geheugen Krachtig: Je bepaalt zelf wanneer geheugen wordt aangemaakt of vrijgegeven. Gevaarlijk: Memory corruption. delete te veel of delete van verkeerde pointer. Memory leak. delete vergeten. Undefined behaviour. gebruik van een deleted variabele. Gebruik zoveel mogelijk standaard componenten zoals std::vector © Harry Broeders

Dynamische std::vector OGOPRG 3 april 2017 Dynamische std::vector Het geheugen wordt aangevraagd als het programma runt  grootte hoeft niet bij compileren bekend te zijn. Dynamisch: #include <vector> using namespace std; vector<Tekkel>::size_type s; cout << "Hoeveel Tekkels wil je? "; cin >> s; vector<Tekkel> v(s); for (Tekkel t: v) t.blaf(); © Harry Broeders

OGOPRG 3 april 2017 Constructor Wordt door de compiler aangeroepen als een variabele gemaakt wordt. class Breuk { public: Breuk(); Breuk(int t); Breuk(int t, int n); int teller() const; int noemer() const; void plus(Breuk b); private: int boven; int onder; void normaliseer(); }; void main() { Breuk a, b(-2), c(21,-9); // ... } © Harry Broeders

OGOPRG 3 april 2017 Destructor Wordt door de compiler aangeroepen als een variabele verwijderd wordt. class Breuk { public: Breuk(); Breuk(int t); Breuk(int t, int n); ~Breuk(); int teller() const; int noemer() const; void plus(Breuk b); private: int boven; int onder; void normaliseer(); }; Breuk::~Breuk() { cout << "De breuk met teller " << boven << " en noemer " << onder << " is overleden." << endl; } void main() { Breuk a, b(-2), c(21,-9); // ... } © Harry Broeders

Constructor en destructor OGOPRG 3 april 2017 Constructor en destructor Compiler roept de constructor en destructor automatisch aan. Reserveer geheugen op de stack voor a en roep constructor a.Breuk(21,-9) aan { Breuk a(21,-9); // ... } Roep destructor a.~Breuk() aan en geef geheugen van a weer vrij © Harry Broeders

Constructor en destructor OGOPRG 3 april 2017 Constructor en destructor Compiler roept de constructor en destructor automatisch aan. Reserveer geheugen op de heap en roep constructor Breuk(21,-9) aan { Breuk* bp = new Breuk(21,-9); // ... delete bp; } Roep destructor ~Breuk() aan en geef geheugen weer vrij © Harry Broeders

Je kunt al deze functies ook zelf definiëren! OGOPRG 3 april 2017 Gratis bij elke class! constructor zonder argument (default constructor). Deze constructor roept de default constructor aan van alle data members. copy constructor. Deze constructor roept de copy constructor aan van alle data members. assignment operator (operator=). Deze assignment operator roept de assignment operator aan van alle data members. destructor. Deze destructor roept de destructor aan van alle data members. Je kunt al deze functies ook zelf definiëren! © Harry Broeders

Default destructor probleem OGOPRG 3 april 2017 Default destructor probleem De automatisch door de compiler aangemaakte default destructor is niet virtual. ~SB() wordt niet aangeroepen! class Hond { public: virtual void blaf() = 0; }; class SB: public Hond { private: Whisky vat; SB() { vat.maakVol(); } virtual ~SB () { vat.maakLeeg(); } virtual void blaf() override { cout << "Woef woef" << endl; } int main() { Hond* Boris(new SB); Boris->blaf(); delete Boris; } © Harry Broeders

OGOPRG 3 april 2017 Virtual destructor Als een class nu of in de toekomst als basis class gebruikt wordt dan moet de destructor virtual zijn zodat van deze class afgeleide classes via een polymorphic pointer gedelete kunnen worden. C++11 class Hond { public: virtual ~Hond() = default; virtual void blaf() = 0; }; class SintBernard: public Hond { virtual ~SintBernard(); © Harry Broeders

OGOPRG 3 april 2017 Huiswerk! Voeg in practicum opgave 2b een destructor toe die meldt dat een Tijdsduur is overleden. Verklaar de uitvoer. Verander nu in opgave 2b elke const Tijdsduur& door een Tijdsduur. Verklaar de wijzigingen in de uitvoer. Bestudeer dictaat: Hoofdstuk 5 t/m 5.4. © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 19 © Harry Broeders

Aggregatie implementatie OGOPRG 3 april 2017 Aggregatie implementatie class SintBernard: public Hond { public: SintBernard(); virtual ~SintBernard(); virtual void blaf() override; private: WhiskeyVat* vat; }; Geef de implementatie van de constructor en de destructor. © Harry Broeders

Implementatie SintBernard::SintBernard(): vat(new WhiskeyVat) { OGOPRG 3 april 2017 Implementatie SintBernard::SintBernard(): vat(new WhiskeyVat) { vat->maakVol(); } virtual ~ SintBernard::SintBernard() { vat->maakLeeg(); delete vat; virtual void SintBernard::blaf() { cout << "WOEF WOEF" << endl; :SintBernard vat :WhiskeyVat Aangemaakt met new © Harry Broeders

Dit is niet goed! We moeten zelf een copy constructor definiëren. OGOPRG 3 april 2017 Copy constructor SintBernard a; SintBernard b(a); Default copy constructor: kopieert alle data members SintBernard::SintBernard(): vat(new WhiskeyVat) { vat->maakVol(); } a vat ? Dit is niet goed! We moeten zelf een copy constructor definiëren. b vat ? © Harry Broeders

Copy constructor a b Gewenst resultaat: vat vat OGOPRG 3 april 2017 © Harry Broeders

OGOPRG 3 april 2017 Copy constructor SintBernard::SintBernard(const SintBernard& r): Hond(r), vat(0) { if (r.vat != 0) vat = new WhiskeyVat(*(r.vat)); } Kun je ook een SintBernard in plaats van een const SintBernard& als parameter gebruiken? Nee! Want dan moet er een kopietje worden gemaakt en dan wordt de copy constructor aangeroepen, maar dan moet er een kopietje worden gemaakt en dan wordt de copy constructor aangeroepen, maar dan moet er een kopietje worden gemaakt en dan wordt de copy constructor aangeroepen maar, dan moet er een kopietje worden gemaakt en dan wordt de copy constructor aangeroepen maar, dan ... © Harry Broeders

Dit is niet goed! We moeten zelf een operator= definiëren. OGOPRG 3 april 2017 operator= SintBernard a; SintBernard b; b = a; Default assignment operator: assigned alle data members b.vat = a.vat; a vat Dit is niet goed! We moeten zelf een operator= definiëren. b vat © Harry Broeders

operator= a b Gewenst resultaat: vat vat OGOPRG 3 april 2017 © Harry Broeders

OGOPRG 3 april 2017 operator= SintBernard& SintBernard::operator=(const SintBernard& r) { SintBernard t(r); std::swap(vat, t.vat); return *this; } SintBernard& SintBernard::operator=(SintBernard r) { std::swap(vat, r.vat); return *this; } Kun je ook een SintBernard in plaats van een const SintBernard& als parameter gebruiken? Ja! Er wordt dan een overbodig kopietje gemaakt. Ja!!! Het maken van het kopietje t is dan overbodig! Wat is nut van SintBernard& return type en return *this? a = b = c; © Harry Broeders

Wanneer zelf definiëren? OGOPRG 3 april 2017 Wanneer zelf definiëren? Een class moet een zelf gedefinieerde copy constructor, operator= en destructor bevatten als: die class een pointer bevat en als bij het kopiëren van een object van de class niet de pointer, maar de data waar de pointer naar wijst moet worden gekopieerd en als bij een toekenning aan een object van de class niet de pointer, maar de data waar de pointer naar wijst moet worden toegekend en als bij het opruimen van een object van de class niet alleen de pointer, maar ook de data waar de pointer naar wijst moet worden opgeruimd. © Harry Broeders

Huiswerk! Bestudeer dictaat: Paragraaf 5.5 t/m 5.10. OGOPRG 3 april 2017 Huiswerk! Bestudeer dictaat: Paragraaf 5.5 t/m 5.10. © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 20 © Harry Broeders

Memberfuncties en data members OGOPRG 3 april 2017 Memberfuncties en data members Elk object heeft zijn eigen data members terwijl de memberfuncties door alle objecten van een bepaalde class "gedeeld" worden. class Hond { public: Hond(const string& n); void blaf(); private: string naam; }; Hond::Hond(const string& n): naam(n) { } void Hond::blaf() { cout << naam << " zegt: WOEF" << endl; © Harry Broeders

Memberfuncties en data members OGOPRG 3 april 2017 Memberfuncties en data members We willen bijhouden hoeveel objecten van de class Hond er op een bepaald moment bestaan. int aantalHonden = 0; //dit is een globale variabele class Hond { public: Hond(const string& n); ~Hond(); void blaf(); private: string naam; }; Hond::Hond(const string n): naam(n) { ++aantalHonden; } Hond::~Hond() { --aantalHonden; } © Harry Broeders

OGOPRG 3 april 2017 static Een static data member is een onderdeel van de class en wordt door alle objecten van de class gedeeld. class Hond { public: Hond(const string& n); ~Hond(); void blaf(); static int aantal(); private: string naam; static int aantalHonden; }; © Harry Broeders

OGOPRG 3 april 2017 static Een static data member is een onderdeel van de class en wordt door alle objecten van de class gedeeld. int Hond::aantalHonden = 0; Hond::Hond(const string& n): naam(n) { ++aantalHonden; } Hond::~Hond() { --aantalHonden; int Hond::aantal() { return aantalHonden; void Hond::blaf() { cout << naam << " zegt: WOEF" << endl; © Harry Broeders

static memberfuncties OGOPRG 3 april 2017 static memberfuncties Twee manieren van aanroepen: direct via de classnaam: class_naam::member_functie_naam(parameters) Voorbeeld: cout << Hond::aantal() << endl; via een object van de class: object_naam.member_functie_naam(parameters) Voorbeeld: cout << h1.aantal() << endl; Beperkingen t.o.v. een gewone memberfunctie: Een static memberfunctie heeft geen receiver (ook niet als hij via een object aangeroepen wordt). Een static memberfunctie heeft dus geen this pointer. Een static memberfunctie kan dus geen "gewone" memberfuncties aanroepen en ook geen "gewone" data members gebruiken. © Harry Broeders

OGOPRG 3 april 2017 static Een static data member is een onderdeel van de class en wordt door alle objecten van de class gedeeld. class Hond { public: Hond(const string& n); ~Hond(); void blaf(); static int aantal(); private: string naam; static int aantalHonden; }; UML boek: paragraaf 4.4.4. © Harry Broeders

OGOPRG 3 april 2017 static static in Visual Paradigm: © Harry Broeders

Huiswerk! Bestudeer boek: Bestudeer dictaat: Bestudeer BB: OGOPRG 3 april 2017 Huiswerk! Bestudeer boek: Paragraaf 4.4.4. Bestudeer dictaat: Paragraaf 6.1. Bestudeer BB: Extra voorbeelden over inheritance en polymorphisme. © Harry Broeders

Overzicht stof OGOPRG Dictaat: Boek: 3 april 2017 Overzicht stof OGOPRG Dictaat: Hoofstuk 1 t/m 6 (alleen 6.1, de rest van hoofdstuk 6 is voor de “liefhebbers”). Boek: Hoofdstuk 1 en 2. Hoofdstuk 4 (behalve 4.4.1, 4.4.3, 4.4.5, 4.4.6, 4.4.7, 4.4.10 t/m 4.4.16, 4.4.18, 4.6.8 en 4.6.9). Hoofdstuk 8 (behalve 8.5.3 en 8.7.6). Hoofdstuk 10 (behalve 10.7). Hoofdstuk 12. Hoofdstuk 15. Opgaven! Zie BB. © Harry Broeders

Afronden practicum Deze week klaar! Anders onvoldoende. Herkansing: OGOPRG 3 april 2017 Afronden practicum Deze week klaar! Anders onvoldoende. Herkansing: Alleen opdracht 4 nog niet klaar: Per email inleveren bij bd@hhs.nl vóór 17 april 2014. Nog meer opdrachten niet klaar: Aftekenen op 23 april. Afspraak maken voor einde van deze week! © Harry Broeders

Objectgeoriënteerd Programmeren in C++ OGOPRG 3 april 2017 Objectgeoriënteerd Programmeren in C++ OGOPRG Les 21 © Harry Broeders

OGOPRG 3 april 2017 ADT Array De grootte van een Array kan tijdens run-time bepaald worden. Bij het gebruik van [] wordt gecontroleerd of de index binnen de grenzen van de Array ligt. Implementatie van Array: 4 size 1 2 3 data 1 4 9 Aangemaakt met new © Harry Broeders

ADT Array class Array { public: explicit Array(int s); OGOPRG 3 april 2017 ADT Array class Array { public: explicit Array(int s); Array(const Array& r); Array& operator=(const Array& r); ~Array(); int& operator[](int index); const int& operator[](int index) const; int length() const; bool operator==(const Array& r) const; bool operator!=(const Array& r) const; // ... // Er zijn vele uitbreidingen mogelijk. private: int size; int* data; }; © Harry Broeders

OGOPRG 3 april 2017 ADT Array Array::Array(int s): size(s), data(new int[s]) { } Array::~Array() { delete[] data; 4 size 1 2 3 data ? ? ? ? Aangemaakt met new © Harry Broeders

Dit is niet goed! We moeten zelf een copy constructor definiëren. OGOPRG 3 april 2017 Copy constructor Array a(4); for (int j = 0; j < a.length(); ++j) { a[j] = j * j; // vul a met kwadraten } Array b(a); Default copy constructor: kopieert alle data members Array::Array(int s): size(s), data(new int[s]) { } a size data 4 ? 1 2 3 1 4 9 ? ? ? ? b Dit is niet goed! We moeten zelf een copy constructor definiëren. 4 ? size ? data © Harry Broeders

Copy constructor a b Gewenst resultaat: 4 size data 1 9 4 size data 1 OGOPRG 3 april 2017 Copy constructor Gewenst resultaat: 4 size data 1 9 2 3 a 4 size data 1 9 2 3 b © Harry Broeders

OGOPRG 3 april 2017 Copy constructor Array::Array(const Array& r): size(r.size), data(new int[r.size]) { for (int i = 0; i < size; ++i) data[i] = r.data[i]; } Kun je ook een Array in plaats van een const Array& als parameter gebruiken? Nee! Want dan moet er een kopietje worden gemaakt en dan wordt de copy constructor aangeroepen, maar dan moet er een kopietje worden gemaakt en dan wordt de copy constructor aangeroepen, maar dan moet er een kopietje worden gemaakt en dan wordt de copy constructor aangeroepen maar, dan moet er een kopietje worden gemaakt en dan wordt de copy constructor aangeroepen maar, dan moet er een kopietje worden gemaakt en dan ... © Harry Broeders

Dit is niet goed! We moeten zelf een operator= definiëren. OGOPRG 3 april 2017 operator= Array a(4); Array b(a.length()); for (int j = 0; j < a.length(); ++j) { a[j] = j * j; // vul a met kwadraten b[j] = j * a[j]; // vul b met derde machten } b = a; Dit is niet goed! We moeten zelf een operator= definiëren. Default assignment operator: assigned alle data members 4 size data 1 9 2 3 a b.size = a.size; b.data = a.data; b 4 size 1 2 3 data 1 8 27 © Harry Broeders

operator= a b Gewenst resultaat: 4 size data 1 9 4 size data 1 9 2 3 2 OGOPRG 3 april 2017 operator= Gewenst resultaat: 4 size data 1 9 2 3 a 4 size data 1 9 2 3 b © Harry Broeders

OGOPRG 3 april 2017 operator= Array& Array::operator=(const Array& r) { Array t(r); std::swap(data, t.data); std::swap(size, t.size); return *this; } Array& Array::operator=(Array r) { std::swap(data, r.data); std::swap(size, r.size); return *this; } Kun je ook een Array in plaats van een const Array& als parameter gebruiken? Ja! Er wordt dan een overbodig kopietje gemaakt. Ja!!! Het maken van het kopietje t is dan overbodig! Wat is nut van Array& return type en return *this? a = b = c; © Harry Broeders

Wanneer zelf definiëren? OGOPRG 3 april 2017 Wanneer zelf definiëren? Een class moet een zelf gedefinieerde copy constructor, operator= en destructor bevatten als: die class een pointer bevat en als bij het kopiëren van een object van de class niet de pointer, maar de data waar de pointer naar wijst moet worden gekopieerd en als bij een toekenning aan een object van de class niet de pointer, maar de data waar de pointer naar wijst moet worden toegekend en als bij het opruimen van een object van de class niet alleen de pointer, maar ook de data waar de pointer naar wijst moet worden opgeruimd. © Harry Broeders

ADT Array versus C array OGOPRG 3 april 2017 ADT Array versus C array Voordelen ADT Array: Bij aanmaken mag de grootte een variabele zijn. Bij gebruik [] wordt de index gecontroleerd. Nadelen ADT Array: Je kunt er alleen integers in opslaan! Oplossing? © Harry Broeders

Template class Array template<typename T> class Array { public: OGOPRG 3 april 2017 Template class Array template<typename T> class Array { public: explicit Array(int s); Array(const Array<T>& v); Array<T>& operator=(const Array<T>& r); ~Array(); T& operator[](int index); const T& operator[](int index) const; int length() const; bool operator==(const Array<T>& r) const; bool operator!=(const Array<T>& r) const; // ... // Er zijn vele uitbreidingen mogelijk. private: int size; T* data; }; template<typename T> Array<T>::Array(int s): size(s), data(new T[s]) { } © Harry Broeders

Template class Array // ... int i; OGOPRG 3 april 2017 Template class Array // ... int i; cout << "Hoe groot wil je de Array's "; cin >> i; Array<double> a(i); for (int j = 0; j < v.length(); ++j) a[j] = sqrt(j); // Vul a met wortels cout << "a[12] = " << a[12] << endl; Array<int> b(i); for (int j = 0; j < b.length(); ++j) b[j] = j * j; // Vul b met kwadraten cout << "b[12] = " << b[12] << endl; © Harry Broeders

ADT Array versus std::Array OGOPRG 3 april 2017 ADT Array versus std::Array Voordelen ADT Array: Bij aanmaken mag de grootte een variabele zijn. Bij gebruik [] wordt de index gecontroleerd. Voordelen std::Array: Grootte is een template parameter en hoeft dus niet opgeslagen te worden. Je kunt range-based for gebruiken om door de std::Array te lopen. Je kunt een std::Array initializeren met { … } Oplossing? © Harry Broeders

ADT Array uitbreidingen C++11 OGOPRG 3 april 2017 ADT Array uitbreidingen C++11 #include <initializer_list> template <typename T> class Array { public: // ... // Support for initializer list Array(initializer_list<T> list); // Support for range-based for T* begin(); const T* begin() const; T* end(); const T* end() const; private: int size; T* data; }; © Harry Broeders

ADT Array uitbreidingen C++11 OGOPRG 3 april 2017 ADT Array uitbreidingen C++11 template <typename T> Array<T>::Array(initializer_list<T> l): size(list.size()), data(new T[size]) { auto listIter = list.begin(); for (int i = 0; i < size; ++i) { data[i] = *listIter++; } template <typename T> T* Array<T>::begin() { return data; template <typename T> const T* Array<T>::begin() const { template <typename T> T* Array<T>::end() { return data + size; template <typename T> const T* Array<T>::end() const { © Harry Broeders

ADT Array uitbreidingen C++11 OGOPRG 3 april 2017 ADT Array uitbreidingen C++11 // ... Array<int> v = {1, 2, 3, 4}; for (auto e: v) { cout << e << " "; } cout << endl; © Harry Broeders

Objectgeoriënteerd Programmeren in C++ Terugblik practicum

Inhoud Herbruikbaarheid Aanpasbaarheid Uitbreidbaarheid OGOPRG 3 april 2017 Inhoud Objectgeoriënteerd Programmeren in C++. responsibility driven design (ontwerpen uitgaande van verantwoordelijkheden). information hiding (het afschermen van informatie door middel van het scheiden van interface en implementatie). abstraction (het afschermen van complexiteit door middel van het scheiden van interface en implementatie). inheritance (het mogelijk maken van een nieuwe vorm van hergebruik, ... is een ... in plaats van ... heeft een ...). polymorphism (veelvormigheid mogelijk gemaakt door dynamic binding). Objectgeoriënteerd Ontwerpen met UML. klasse- en objectdiagrammen. use-case-diagram. sequence- en collaborationdiagrammen. toestands- en activiteitendiagrammen. Herbruikbaarheid Aanpasbaarheid Uitbreidbaarheid © Harry Broeders

Herbruikbaarheid Practicumopdracht 1 Practicumopdracht 2a Hier heb je gezien dat de class std::string een eenvoudig te (her)gebruiken component is. Een object van het type std::string: Slaat een character string op (private data members). Heeft interface (public memberfuncties) waarmee: Informatie over de opgeslagen string kan worden opgevraagd (find). De opgeslagen string kan worden gewijzigd (erase). Practicumopdracht 2a Hier heb je zelf een ADT (Abstract DataType = herbruikbare component) Tijdsduur gemaakt. Practicumopdracht 2b Hier heb je door operator overloading toe te passen de herbruikbaarheid vergroot.

Aanpasbaarheid Practicumopdracht 2c Hier heb je de implementie van de classs Tijdsduur gewijzigd (slaat alleen nog minuten op) zonder de interface aan te passen. Alle code die gebruik maakt van de component Tijdsduur merkt hier niets van en hoeft niet aangepast te worden! Beide implementaties hebben hun sterkte: Implementatie van opdracht 2b kan sneller printen. Implementatie van opdracht 2c kan sneller rekenen en gebruikt minder geheugen. Doordat beide implementaties dezelfde interface hebben kan een gebruiker van de component (een programmeur) altijd nog wisselen van implementatie.

Herbruikbaarheid Practicumopdracht 2d Hier heb je de code van de component Tijdsduur opgenomen in twee aparte files Tijdsduur.h en Tijdsduur.cpp De herbruikbaarheid is hierdoor vergroot (component kan gebruikt worden door Tijdsduur.h te includen en Tijdsduur.cpp mee te linken). De aanpasbaarheid is hierdoor vergroot (wisselen van implementatie kan nu door wisselen van files). Je kan de component nu verspreiden zonder de source code vrij te geven. Door alleen Tijdsduur.h en een gecompileerde versie van Tijdsduur.cpp te verspreiden.

Uitbreidbaarheid Practicumopdracht 3b en 3c Hier heb je gezien dat door het gebruik van overerving het in opdracht 3a gemaakte programma eenvoudig is uit te breiden met een nieuwe soorten werknemers: Stukwerker en Manager. De polymorphic functie printMaandSalaris(const Werknemer& w) hoeft niet aangepast te worden. Je hoeft alleen de “verschillen” te programmeren. Het “gemeenschappelijke” erf je over vanuit de basisklasse Werknemer. Als het goed is heb je de basisklasse Werknemer abstract gemaakt om slicing te voorkomen.