-
Notifications
You must be signed in to change notification settings - Fork 0
CPP 11. Перегрузка унарных и бинарных операторов. Проблемы с перегрузкой операторов &&, ||, &. Перегрузка операторов PP, MM. Перегрузка операторов приведения типов. Тривалентный оператор spaceship.
Бинарные операторы можно перегружать как члены класса или как внешние функции-операторы. Это зависит от ситуации. Конечно, надо отдавать предпочтение члену класса. Если мы перегружаем бинарный оператор, как член класса, он принимает 1 параметр (второй параметр он принимает неявно - *this).
Унарные операторы перегружаем как члены класса.
Оператор && (логическое И) и оператор || (логическое ИЛИ) используются для вычисления логического значения выражений. При использовании этих операторов, если левый операнд вычисляется как истинный (true) или ложный (false), правый операнд может быть вычислен или не вычислен в зависимости от значения левого операнда. Это называется "ленивым вычислением" (short-circuit evaluation).
При перегрузке оператора &&, || важно учитывать, что левый операнд должен быть вычислен до того, как правый операнд будет вычислен. Если правый операнд не вычисляется, то его состояние не должно быть изменено. Это означает, что перегруженный оператор &&, || должен быть реализован как короткое замыкание (short-circuiting), чтобы учитывать правила ленивого вычисления.
Оператор & (побитовое И) используется для выполнения побитовой операции И между двумя значениями. При перегрузке оператора & важно учитывать, что он может быть использован как побитовая операция И, а также как операция взятия адреса. При перегрузке оператора & следует убедиться, что он ведет себя соответствующим образом в обоих контекстах.
Идея: отделить постфиксную от префиксной записи.
Решение: унарный - префиксный, бинарный - постфиксный операторы.
Замечание: если мы бинарный не перегружаем, то и для постфиксного, и для префиксного будет вызываться перегруженный унарный оператор. Иначе мы четко разделяем их.
class Index {
private:
int ind;
public:
Index(int i = 0) : ind(i) {}
Index& operator++() // ++obj
{
++ind;
return *this;
}
Index operator++(int) // obj++
{
Index it(*this);
++ind;
return it;
}
// оператор приведения типа, может неявно приводится к int
operator int() const { return ind; }
};
С минусом все аналогично.
Оператор spaceship (также известный как оператор трехкомпонентного сравнения) - это оператор, добавленный в C++20, который используется для сравнения двух объектов и возвращает одно из трех значений: отрицательное число, ноль или положительное число, в зависимости от того, какой объект меньше, равен или больше.
Синтаксис оператора spaceship выглядит следующим образом:
auto operator<=>(const T& lhs, const T& rhs);
где T - это тип объектов, которые будут сравниваться.
Оператор spaceship может быть использован вместо операторов сравнения (<, <=, ==, !=, >=, >), что позволяет упростить и улучшить читаемость кода. Он также может быть использован для сортировки объектов, например, в алгоритмах сортировки.
Пример использования оператора spaceship:
#include <compare>
struct Person {
std::string name;
int age;
auto operator<=>(const Person&) const = default;
};
int main() {
Person p1{"Alice", 25};
Person p2{"Bob", 30};
if (p1 <=> p2 < 0) {
std::cout << "Alice is younger than Bobn";
} else if (p1 <=> p2 > 0) {
std::cout << "Alice is older than Bobn";
} else {
std::cout << "Alice and Bob are the same agen";
}
}
В этом примере оператор spaceship используется для сравнения двух объектов типа Person по возрасту. Он возвращает одно из трех значений: отрицательное число, если p1 младше p2; ноль, если p1 и p2 одного возраста; и положительное число, если p1 старше p2.