Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Leer Operatoroverbelasting | Overzicht van Polymorfisme
C++ OOP
course content

Cursusinhoud

C++ OOP

C++ OOP

1. Fundamenten van OOP in C++
2. Constructors en Destructors
3. Overzicht van Encapsulatie
4. Overzicht van Overerving
5. Overzicht van Polymorfisme

book
Operatoroverbelasting

Operator-overloading is een krachtige functie in objectgeoriënteerde programmeertalen waarmee je het gedrag van operatoren voor zelfgedefinieerde classes kunt herdefiniëren. Door operatoren te overladen, kun je aangepaste implementaties bieden voor bewerkingen met objecten van jouw class, wat zorgt voor meer intuïtieve en expressieve code.

De syntaxis van operator-overloading

Overladen wordt bereikt door speciale lidfuncties of vriendfuncties te definiëren die het gewenste gedrag voor de operator implementeren. De syntaxis voor het overladen van operatoren varieert afhankelijk van de operator die je wilt overladen. De algemene vorm ziet er als volgt uit:

overloading.h

overloading.h

copy
1
return_type operator operator_symbol(parameters);

De syntaxis, of meer specifiek, het aantal parameters en het retourtype, hangt ook af van de vraag of je operatoren overlaadt als lidfuncties of als vriendfuncties.

Member.h

Member.h

Friend.h

Friend.h

copy
123456
class Example { public: Example operator+ (const Example& other) { // Define behavior for operator+ } };

De tabel van operatoren die kunnen worden overbelast

Hier is een tabel met alle operatoren die kunnen worden overbelast. Het is echter belangrijk op te merken dat, hoewel het mogelijk is om deze operatoren te overbelasten, het zeker niet noodzakelijk is om ze allemaal voor je classes te overbelasten.

Overloaden van stream-invoegoperatoren

Om de operatoren << en >> voor een class te overloaden, definieer je doorgaans een friend-functie of een lidfunctie die een outputstream (std::ostream&) of inputstream (std::istream&) als linker operand neemt en een object van jouw class als rechter operand. Deze functie formatteert vervolgens de gegevens van het object en streamt deze naar of van de stream.

Point.h

Point.h

copy
123456789101112131415
class Point { public: friend std::ostream& operator<<(std::ostream& out, const Point& point); friend std::istream& operator>>(std::istream& in, Point& point); private: int x, y; }; std::ostream& operator<<(std::ostream& out, const Point& point) { return out << "x: " << point.x << ", y: " << point.y << std::endl; } std::istream& operator>>(std::istream& in, Point& point) { return in >> point.x >> point.y; }

Het overloaden van stream-invoegoperatoren, zoals <<, stelt je in staat om aangepast uitvoergedrag te definiëren voor objecten van jouw classes wanneer deze naar een outputstream zoals std::cout worden gestreamd. Deze functionaliteit is vooral nuttig voor het verbeteren van de leesbaarheid en bruikbaarheid van je code bij het werken met aangepaste datatypes.

Note
Opmerking

Het overladen van de <<-operator voor uitvoerstroom komt vaker voor dan het overladen van de >>-operator voor invoerstroom, omdat invoerbewerkingen met >> vaker foutgevoelig zijn.

Overladen van rekenkundige operatoren

Andere rekenkundige operatoren (-, *, /, %) kunnen op vergelijkbare wijze worden overladen om aangepaste bewerkingen met uw zelfgedefinieerde typen uit te voeren.

main.cpp

main.cpp

copy
12345678910111213141516171819202122
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} Point operator+(const Point& other) { return Point(x + other.x, y + other.y); } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p = Point(2, 4) + Point(2, 6); std::cout << p.getX() << ' ' << p.getY() << std::endl; }

De operator wordt overbelast als een lidfunctie van de Point-class. Deze neemt een ander Point-object als parameter en retourneert een nieuw Point-object dat de som van de twee punten voorstelt. De +-operator kan worden vervangen door -, *, / of %, met overeenkomstige aanpassingen in de implementatielogica.

Increment en Decrement

Zowel de prefix als postfix increment- en decrementoperators (++ en --) kunnen worden overbelast voor aangepaste classes. We beginnen met de prefixversie:

main.cpp

main.cpp

copy
123456789101112131415161718192021222324
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} // Prefix increment operator (++point) Point& operator++() { ++x; ++y; return *this; } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p(2, 2); ++p; std::cout << p.getX() << ' ' << p.getY() << std::endl; }
Note
Opmerking

De decrement-operator wordt op vergelijkbare wijze als de increment-operator overbelast, met gebruik van de ---operator en de aftrekbewerking.

Zoals je ziet is het overbelasten van de prefix increment- en decrement-operatoren eenvoudig. Het wordt echter lastiger bij de postfix varianten. Onthoud dat er een verschil is in de uitvoervolgorde tussen prefix- en postfix-bewerkingen.

Bij het overbelasten van postfix increment en decrement moet ook de uitvoervolgorde worden geïmplementeerd. Dit ziet er ongeveer zo uit:

main.cpp

main.cpp

copy
1234567891011121314151617181920212223242526
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} // Postfix increment operator (point++) Point operator++(int) { Point temp = *this; // Creating a temp variable ++(this->x); // Incrementing original Point's x ++(this->y); // Incrementing original Point's y return temp; // Returning created temp variable } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p(2, 2); p++; std::cout << p.getX() << ' ' << p.getY() << std::endl; }
Note
Opmerking

De gehele parameter wordt zonder naam doorgegeven alleen om aan de compiler aan te geven dat de postfix-incrementoperator wordt overbelast. Dit is noodzakelijk omdat de declaraties voor prefix- en postfix-operatoren anders identiek zijn.

In de implementatie van de postfix-incrementoperator wordt de oorspronkelijke waarde van het object opgeslagen in een tijdelijke variabele (temp). Het huidige object wordt vervolgens verhoogd, maar de operator retourneert de waarde die in temp is opgeslagen. Dit betekent dat de variabele wordt verhoogd, maar de wijziging pas in de volgende expressie effect heeft, omdat de operator de oorspronkelijke waarde retourneert.

question mark

Wat betekent operator overloading?

Select the correct answer

Was alles duidelijk?

Hoe kunnen we het verbeteren?

Bedankt voor je feedback!

Sectie 5. Hoofdstuk 4

Vraag AI

expand

Vraag AI

ChatGPT

Vraag wat u wilt of probeer een van de voorgestelde vragen om onze chat te starten.

course content

Cursusinhoud

C++ OOP

C++ OOP

1. Fundamenten van OOP in C++
2. Constructors en Destructors
3. Overzicht van Encapsulatie
4. Overzicht van Overerving
5. Overzicht van Polymorfisme

book
Operatoroverbelasting

Operator-overloading is een krachtige functie in objectgeoriënteerde programmeertalen waarmee je het gedrag van operatoren voor zelfgedefinieerde classes kunt herdefiniëren. Door operatoren te overladen, kun je aangepaste implementaties bieden voor bewerkingen met objecten van jouw class, wat zorgt voor meer intuïtieve en expressieve code.

De syntaxis van operator-overloading

Overladen wordt bereikt door speciale lidfuncties of vriendfuncties te definiëren die het gewenste gedrag voor de operator implementeren. De syntaxis voor het overladen van operatoren varieert afhankelijk van de operator die je wilt overladen. De algemene vorm ziet er als volgt uit:

overloading.h

overloading.h

copy
1
return_type operator operator_symbol(parameters);

De syntaxis, of meer specifiek, het aantal parameters en het retourtype, hangt ook af van de vraag of je operatoren overlaadt als lidfuncties of als vriendfuncties.

Member.h

Member.h

Friend.h

Friend.h

copy
123456
class Example { public: Example operator+ (const Example& other) { // Define behavior for operator+ } };

De tabel van operatoren die kunnen worden overbelast

Hier is een tabel met alle operatoren die kunnen worden overbelast. Het is echter belangrijk op te merken dat, hoewel het mogelijk is om deze operatoren te overbelasten, het zeker niet noodzakelijk is om ze allemaal voor je classes te overbelasten.

Overloaden van stream-invoegoperatoren

Om de operatoren << en >> voor een class te overloaden, definieer je doorgaans een friend-functie of een lidfunctie die een outputstream (std::ostream&) of inputstream (std::istream&) als linker operand neemt en een object van jouw class als rechter operand. Deze functie formatteert vervolgens de gegevens van het object en streamt deze naar of van de stream.

Point.h

Point.h

copy
123456789101112131415
class Point { public: friend std::ostream& operator<<(std::ostream& out, const Point& point); friend std::istream& operator>>(std::istream& in, Point& point); private: int x, y; }; std::ostream& operator<<(std::ostream& out, const Point& point) { return out << "x: " << point.x << ", y: " << point.y << std::endl; } std::istream& operator>>(std::istream& in, Point& point) { return in >> point.x >> point.y; }

Het overloaden van stream-invoegoperatoren, zoals <<, stelt je in staat om aangepast uitvoergedrag te definiëren voor objecten van jouw classes wanneer deze naar een outputstream zoals std::cout worden gestreamd. Deze functionaliteit is vooral nuttig voor het verbeteren van de leesbaarheid en bruikbaarheid van je code bij het werken met aangepaste datatypes.

Note
Opmerking

Het overladen van de <<-operator voor uitvoerstroom komt vaker voor dan het overladen van de >>-operator voor invoerstroom, omdat invoerbewerkingen met >> vaker foutgevoelig zijn.

Overladen van rekenkundige operatoren

Andere rekenkundige operatoren (-, *, /, %) kunnen op vergelijkbare wijze worden overladen om aangepaste bewerkingen met uw zelfgedefinieerde typen uit te voeren.

main.cpp

main.cpp

copy
12345678910111213141516171819202122
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} Point operator+(const Point& other) { return Point(x + other.x, y + other.y); } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p = Point(2, 4) + Point(2, 6); std::cout << p.getX() << ' ' << p.getY() << std::endl; }

De operator wordt overbelast als een lidfunctie van de Point-class. Deze neemt een ander Point-object als parameter en retourneert een nieuw Point-object dat de som van de twee punten voorstelt. De +-operator kan worden vervangen door -, *, / of %, met overeenkomstige aanpassingen in de implementatielogica.

Increment en Decrement

Zowel de prefix als postfix increment- en decrementoperators (++ en --) kunnen worden overbelast voor aangepaste classes. We beginnen met de prefixversie:

main.cpp

main.cpp

copy
123456789101112131415161718192021222324
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} // Prefix increment operator (++point) Point& operator++() { ++x; ++y; return *this; } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p(2, 2); ++p; std::cout << p.getX() << ' ' << p.getY() << std::endl; }
Note
Opmerking

De decrement-operator wordt op vergelijkbare wijze als de increment-operator overbelast, met gebruik van de ---operator en de aftrekbewerking.

Zoals je ziet is het overbelasten van de prefix increment- en decrement-operatoren eenvoudig. Het wordt echter lastiger bij de postfix varianten. Onthoud dat er een verschil is in de uitvoervolgorde tussen prefix- en postfix-bewerkingen.

Bij het overbelasten van postfix increment en decrement moet ook de uitvoervolgorde worden geïmplementeerd. Dit ziet er ongeveer zo uit:

main.cpp

main.cpp

copy
1234567891011121314151617181920212223242526
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} // Postfix increment operator (point++) Point operator++(int) { Point temp = *this; // Creating a temp variable ++(this->x); // Incrementing original Point's x ++(this->y); // Incrementing original Point's y return temp; // Returning created temp variable } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p(2, 2); p++; std::cout << p.getX() << ' ' << p.getY() << std::endl; }
Note
Opmerking

De gehele parameter wordt zonder naam doorgegeven alleen om aan de compiler aan te geven dat de postfix-incrementoperator wordt overbelast. Dit is noodzakelijk omdat de declaraties voor prefix- en postfix-operatoren anders identiek zijn.

In de implementatie van de postfix-incrementoperator wordt de oorspronkelijke waarde van het object opgeslagen in een tijdelijke variabele (temp). Het huidige object wordt vervolgens verhoogd, maar de operator retourneert de waarde die in temp is opgeslagen. Dit betekent dat de variabele wordt verhoogd, maar de wijziging pas in de volgende expressie effect heeft, omdat de operator de oorspronkelijke waarde retourneert.

question mark

Wat betekent operator overloading?

Select the correct answer

Was alles duidelijk?

Hoe kunnen we het verbeteren?

Bedankt voor je feedback!

Sectie 5. Hoofdstuk 4
some-alt