Przeciążanie operatorów jednoargumentowych
W przeciwieństwie do operatorów, które widziałeś do tej pory, operatory dodatni (+), ujemny (-) i nie logiczne (!) są operatorami jednoargumentowymi, co oznacza, że działają tylko na jednym operandzie. Ponieważ działają tylko na obiekcie, do którego są zastosowane, zazwyczaj przeciążenia operatora jednoargumentowego są implementowane jako funkcje członkowskie. Wszystkie trzy operatory są implementowane w identyczny sposób.
Przyjrzyjmy się, jak zaimplementowalibyśmy operator – w klasie Cents, której używaliśmy w poprzednim przykładzie:
#include <iostream>
class Cents
{
private:
int m_cents {};
public:
Cents(int cents): m_cents{cents} {}
// Przeciążenie — Centy jako funkcja członkowska
Cents operator-() const;
int getCents() const { return m_cents; }
};
// uwaga: ta funkcja jest funkcją składową!
Cents Cents::operator-() const
{
return -m_cents; // ponieważ zwracany typ to Centy, powoduje to niejawną konwersję z int na Centy przy użyciu konstruktora Cents(int)
}
int main()
{
const Cents nickle{ 5 };
std::cout << "A nickle of debt is worth " << (-nickle).getCents() << " cents\n";
return 0;
}To powinno być proste. Nasz przeciążony operator ujemny (-) jest operatorem jednoargumentowym zaimplementowanym jako funkcja składowa, więc nie przyjmuje żadnych parametrów (działa na obiekcie *this). Zwraca obiekt Cents będący negacją oryginalnej wartości Cents. Ponieważ operator- nie modyfikuje obiektu Cents, możemy (i powinniśmy) uczynić z niego funkcję const (aby można było ją wywołać na obiektach const Cents).
Zauważ, że nie ma pomylenia pomiędzy operatorem ujemnym i operatorem minus, ponieważ mają one różną liczbę parametrów.
Oto kolejny przykład. ! operator jest operatorem logicznej negacji — jeśli wyrażenie ma wartość „prawda”, operator! zwróci false i odwrotnie. Często widzimy to w zastosowaniu do zmiennych boolowskich w celu sprawdzenia, czy są one prawdziwe, czy nie:
if (!isHappy)
std::cout << "I am not happy!\n";
else
std::cout << "I am so happy!\n";W przypadku liczb całkowitych 0 daje wartość fałszywą, a wszystko inne – prawdę, więc operator! w zastosowaniu do liczb całkowitych zwróci wartość true dla wartości całkowitej 0, w przeciwnym razie false.
Rozszerzając koncepcję, możemy powiedzieć, że operator! powinien mieć wartość true, jeśli stan obiektu to „false”, „zero” lub jakikolwiek inny domyślny stan inicjalizacji.
Poniższy przykład pokazuje przeciążenie zarówno operatora, jak i operatora! dla zdefiniowanej przez użytkownika klasy Point:
#include <iostream>
class Point
{
private:
double m_x {};
double m_y {};
double m_z {};
public:
Point(double x=0.0, double y=0.0, double z=0.0):
m_x{x}, m_y{y}, m_z{z}
{
}
// Przekształć punkt na jego ujemną odpowiednik
Point operator- () const;
// Zwraca wartość prawda, jeśli punkt jest ustawiony na początku
bool operator! () const;
double getX() const { return m_x; }
double getY() const { return m_y; }
double getZ() const { return m_z; }
};
// Przekształć punkt na jego ujemną odpowiednik
Point Point::operator- () const
{
return { -m_x, -m_y, -m_z };
}
// Zwraca wartość prawda, jeśli punkt jest ustawiony na początku, w przeciwnym razie fałsz
bool Point::operator! () const
{
return (m_x == 0.0 && m_y == 0.0 && m_z == 0.0);
}
int main()
{
Point point{}; // użyj domyślnego konstruktora, aby ustawić na (0.0, 0.0, 0.0)
if (!point)
std::cout << "point is set at the origin.\n";
else
std::cout << "point is not set at the origin.\n";
return 0;
}Przeciążony operator! dla tej klasy zwraca wartość logiczną „true”, jeśli Point ma ustawioną wartość domyślną na współrzędnej (0,0, 0,0, 0,0). Zatem powyższy kod generuje wynik:
point is set at the origin.
Czas quizu
- Implementacja przeciążona jednoargumentowa
operator+dla klasy Point. Jednoargumentowyoperator+po prostu zwraca swój operand (nie powoduje to, że wartości ujemne stają się dodatnie).

