Kursusindhold
C++ OOP
C++ OOP
Operatoroverbelastning
Operatoroverload er en kraftfuld funktion i objektorienterede programmeringssprog, der gør det muligt at omdefinere operatorers adfærd for brugerdefinerede classes
. Ved at overloade operatorer kan du levere brugerdefinerede implementeringer for operationer, der involverer objekter af din class
, hvilket muliggør mere intuitiv og udtryksfuld kode.
Syntaksen for operatoroverload
Overload opnås ved at definere specielle medlemsfunktioner eller vennefunktioner, der implementerer den ønskede adfærd for operatoren. Syntaksen for at overloade operatorer varierer afhængigt af, hvilken operator du ønsker at overloade. Den generelle syntaks ser således ud:
overloading.h
return_type operator operator_symbol(parameters);
Syntaksen, eller mere specifikt antallet af parametre og returtypen, afhænger også af, om du overbelaster operatorer som medlemsfunktioner eller vennefunktioner.
Member.h
Friend.h
class Example { public: Example operator+ (const Example& other) { // Define behavior for operator+ } };
Tabellen over operatorer, der kan overbelastes
Her er en tabel, der viser alle de operatorer, der kan overbelastes. Det er dog vigtigt at bemærke, at selvom det er muligt at overbelaste disse operatorer, er det på ingen måde nødvendigt at overbelaste dem alle for dine classes
.
Overbelastning af stream-indføringsoperatorer
For at overbelaste operatorerne <<
og >>
for en class
, defineres typisk en friend-funktion eller en medlemsfunktion, der tager en output stream (std::ostream&
) eller input stream (std::istream&
) som venstre operand og et objekt af din class
som højre operand. Denne funktion formaterer derefter objektets data og streamer det til eller fra streamen.
Point.h
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; }
Overbelastning af stream-indføringsoperatorer, såsom <<
, gør det muligt at definere brugerdefineret outputadfærd for objekter af dine classes
, når de sendes til en output stream som std::cout
. Denne funktion er især nyttig for at øge læsbarheden og anvendeligheden af din kode, når du arbejder med brugerdefinerede datatyper.
Overload af <<
-operatoren for output stream er mere almindelig end overload af >>
-operatoren for input stream, da inputoperationer med >>
kan være mere fejlbehæftede.
Overbelastning af aritmetiske operatorer
Andre aritmetiske operatorer (-
, *
, /
, %
) kan overbelastes på lignende måde for at udføre brugerdefinerede operationer med dine brugerdefinerede typer.
main.cpp
#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; }
Operatoren overbelastes som en medlemsfunktion i Point
-class
. Den tager et andet Point
-objekt som parameter og returnerer et nyt Point
-objekt, der repræsenterer summen af de to punkter. +
-operatoren kan erstattes med -
, *
, /
eller %
, med tilsvarende justeringer i implementeringslogikken.
Inkrementering og dekrementering
Både præfiks og postfiks inkrementerings- og dekrementeringsoperatorerne (++
og --
) kan overbelastes for brugerdefinerede classes
. Lad os begynde med præfiks-versionen:
main.cpp
#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; }
Decrement-operatoren overbelastes på samme måde som inkrement-operatoren, ved brug af --
-operatoren og subtraktionsoperationen.
Som du kan se, er det ligetil at overbelaste præfiks inkrement- og decrement-operatorerne. Det bliver dog mere kompliceret med postfiks versionerne. Husk, der er forskel på rækkefølgen af udførelse mellem præfiks og postfiks operationer.
Når man overbelaster postfiks inkrement og decrement, skal man også implementere rækkefølgen af udførelsesfunktionen. Det vil se nogenlunde sådan ud:
main.cpp
#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; }
Det heltalsparameteren overføres uden navn udelukkende for at signalere til compileren, at det er postfix-inkrementoperatoren, der overbelastes. Dette er nødvendigt, fordi deklarationerne for prefix- og postfix-operatorer ellers er identiske.
I implementeringen af postfix-inkrementoperatoren gemmes den oprindelige værdi af objektet i en midlertidig variabel (temp
). Det aktuelle objekt bliver derefter inkrementeret, men operatoren returnerer værdien, der er gemt i temp
. Dette betyder, at variablen bliver inkrementeret, men ændringen træder først i kraft i det næste udtryk, da operatoren returnerer den oprindelige værdi.
Tak for dine kommentarer!