Kursinnehåll
C++ OOP
C++ OOP
Operatoröverladdning
Operatoröverladdning är en kraftfull funktion i objektorienterade programmeringsspråk som gör det möjligt att omdefiniera operatorers beteende för användardefinierade classes
. Genom att överladda operatorer kan du tillhandahålla anpassade implementationer för operationer som involverar objekt av din class
, vilket möjliggör mer intuitiv och uttrycksfull kod.
Syntaxen för operatoröverladdning
Överladdning uppnås genom att definiera speciella medlemsfunktioner eller vänfunktioner som implementerar det önskade beteendet för operatorn. Syntaxen för att överladda operatorer varierar beroende på vilken operator du vill överladda. Den generella formen ser ut så här:
overloading.h
return_type operator operator_symbol(parameters);
Syntaxen, eller mer specifikt antalet parametrar och returtyp, beror också på om du överlagrar operatorer som medlemsfunktioner eller vänfunktioner.
Member.h
Friend.h
class Example { public: Example operator+ (const Example& other) { // Define behavior for operator+ } };
Tabell över operatorer som kan överlagras
Här är en tabell som listar alla operatorer som kan överlagras. Det är dock viktigt att notera att även om det är möjligt att överlagra dessa operatorer, är det absolut inte nödvändigt att överlagra alla för dina classes
.
Överlagring av ströminsättningsoperatorer
För att överlasta operatorerna <<
och >>
för en class
definierar du vanligtvis en vänfunktion eller en medlemsfunktion som tar en utströmsreferens (std::ostream&
) eller inströmsreferens (std::istream&
) som vänster operand och ett objekt av din class
som höger operand. Denna funktion formaterar sedan objektets data och strömmar det till eller från strömmen.
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; }
Överlagring av ströminsättningsoperatorer, såsom <<
, gör det möjligt att definiera anpassat utmatningsbeteende för objekt av dina classes
när de strömmas till en utström som std::cout
. Denna funktion är särskilt användbar för att förbättra läsbarheten och användbarheten av din kod när du arbetar med egna datatyper.
Att överlagra operatorn <<
för utmatningsström är vanligare än att överlagra operatorn >>
för inmatningsström, eftersom inmatningsoperationer med >>
kan vara mer felbenägna.
Överlagring av aritmetiska operatorer
Du kan överlagra andra aritmetiska operatorer (-
, *
, /
, %
) på liknande sätt för att utföra anpassade operationer med dina användardefinierade 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; }
Operatorn överlagras som en medlemsfunktion i Point
-class
. Den tar ett annat Point
-objekt som parameter och returnerar ett nytt Point
-objekt som representerar summan av de två punkterna. +
-operatorn kan ersättas med -
, *
, /
eller %
, med motsvarande justeringar i implementeringslogiken.
Inkrementering och dekrementering
Både prefix- och postfix-inkrementerings- och dekrementeringsoperatorerna (++
och --
) kan överlagras för anpassade classes
. Vi börjar med prefixversionen:
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; }
Dekrementoperatorn överlagras på liknande sätt som inkrementoperatorn, med hjälp av --
-operatorn och subtraktionsoperationen.
Som du kan se är det enkelt att överlasta prefix inkrement- och dekrementoperatorer. Det blir dock mer komplicerat med postfix-versionerna. Kom ihåg att det finns en skillnad i exekveringsordning mellan prefix och postfix operationer.
Vid överlagring av postfix inkrement och dekrement måste vi även implementera exekveringsordningsfunktionen. Det kommer att se ut ungefär så här:
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; }
Heltalsparametern skickas utan namn endast för att signalera till kompilatorn att postfix-inkrementoperatorn överlagras. Detta är nödvändigt eftersom deklarationerna för prefix- och postfixoperatorer annars är identiska.
I implementeringen av postfix-inkrementoperatorn lagras det ursprungliga värdet av objektet i en tillfällig variabel (temp
). Det aktuella objektet ökas sedan, men operatorn returnerar värdet som lagras i temp
. Detta innebär att variabeln ökas, men ändringen träder i kraft först i nästa uttryck, eftersom operatorn returnerar det ursprungliga värdet.
Tack för dina kommentarer!