Ce face operator
Supraîncărcarea operatorilor (operator overloading) îți permite să scrii a + b pentru două obiecte Bani, std::cout << produs sau matrice[2]. Pentru compilator, a + b devine un apel de funcție operator+(a, b), pe care tu îl definești.
Un operator poate fi metodă a clasei (primul operand este obiectul: a.operator+(b)) sau funcție liberă. Operatorii care primesc alt tip în stânga, ca std::ostream& operator<<(std::ostream&, const T&), trebuie să fie funcții libere.
Din C++20, operator== și operator<=> (comparația în trei sensuri, „nava spațială”) pot fi cerute cu = default: compilatorul generează toate cele șase comparații, membru cu membru. operator() face un obiect apelabil ca o funcție (un „functor”).
Exemple
Exemplul 1: Adunare și afișare pentru o clasă Bani
#include <iostream>
struct Bani {
long bani; // suma în bani (1 leu = 100 bani)
Bani operator+(const Bani& alt) const { return {bani + alt.bani}; }
Bani& operator+=(const Bani& alt) {
bani += alt.bani;
return *this;
}
};
std::ostream& operator<<(std::ostream& out, const Bani& b) {
return out << b.bani / 100 << "," << (b.bani % 100 < 10 ? "0" : "") << b.bani % 100 << " lei";
}
int main() {
Bani paine{450};
Bani lapte{719};
Bani total = paine + lapte;
std::cout << "Total: " << total << '\n';
total += Bani{1205};
std::cout << "Cu cafea: " << total << '\n';
}
Rezultat
Total: 11,69 lei
Cu cafea: 23,74 lei
Exemplul 2: Comparații generate cu = default (C++20)
Membrii sunt comparați în ordinea declarării: întâi major, apoi minor. O singură linie generează <, >, <=, >=, == și !=.
#include <compare>
#include <print>
struct Versiune {
int major;
int minor;
auto operator<=>(const Versiune&) const = default;
};
int main() {
Versiune a{2, 5}, b{2, 10}, c{2, 5};
std::println("2.5 < 2.10: {}", a < b);
std::println("2.5 == 2.5: {}", a == c);
std::println("2.10 >= 2.5: {}", b >= a);
}
Rezultat
2.5 < 2.10: true
2.5 == 2.5: true
2.10 >= 2.5: true
Exemplul 3: operator[] și operator()
#include <print>
#include <string>
class Saptamana {
public:
const std::string& operator[](int zi) const { return zile_[zi - 1]; }
private:
std::string zile_[7] = {"luni", "marți", "miercuri", "joi", "vineri", "sâmbătă", "duminică"};
};
struct Reducere {
double procent;
double operator()(double pret) const { return pret * (1 - procent / 100); }
};
int main() {
Saptamana s;
std::println("Ziua 3: {}", s[3]);
Reducere black_friday{40};
std::println("1000 lei cu reducere: {} lei", black_friday(1000));
}
Rezultat
Ziua 3: miercuri
1000 lei cu reducere: 600 lei
Greșeli frecvente
- Dai unui operator un sens surprinzător (de exemplu
+care scade). Operatorii trebuie să facă ce se așteaptă oricine de la ei. - Returnezi prin valoare din
operator+=sauoperator<<. Convenția este să returnezi o referință (*this, respectiv fluxul), ca operațiile să se poată înlănțui. - Definești
operator==dar nu șioperator!=în cod mai vechi de C++20. Înainte de C++20, fiecare operator trebuia scris separat; din C++20,!=este dedus din==.
Comenzi înrudite
friend: Dă unei funcții sau altei clase acces la membrii privați și protejați ai clasei.class: Definește un tip nou care grupează date (membri) și funcțiile care lucrează cu ele (metode); baza programării orientate pe obiecte.lambda ([](){}): O funcție fără nume, scrisă direct acolo unde e folosită; poate „captura” variabile din jur.explicit: Interzice folosirea unui constructor sau a unui operator de conversie pentru conversii automate, ascunse.