friend const Balance operator+(double lhs, const Balance& rhs);
friend const Balance operator+(const Balance& lhs, double rhs);
public:
Balance() : val_(0.0) {}
Balance(double val) : val_(val) {}
~Balance() {}
// Унарные операторы
Balance& operator+=(const Balance& other) {
val_ += other.val_;
return(*this);
}
Balance& operator+=(double other) {
val_ += other;
return(*this);
}
double getVal() const {return(val_);}
private:
double val_;
};
// Бинарные операторы
const Balance operator+(const Balance& lhs, const Balance& rhs) {
Balance tmp(lhs.val_ + rhs.val_);
return(tmp);
}
const Balance operator+(double lhs, const Balance& rhs) {
Balance tmp(lhs + rhs.val_);
return(tmp);
}
const Balance operator+(const Balance& lhs, double rhs) {
Balance tmp(lhs.val_ + rhs);
return(tmp);
}
int main() {
Balance checking(500.00);
savings(23.91);
checking += 50;
Balance total = checking + savings;
cout << "Платежный баланс: " << checking.getVal() << '\n';
cout << "Общий баланс: " << total.getVal() << '\n';
}
Наиболее часто используют перегрузку для арифметических операторов и операторов присвоения. Существует огромное количество различных классов, для которых имеют смысл арифметические операторы (сложение, умножение, остаток от деления, сдвиг битов вправо/влево) и операторы присвоения — вне зависимости от того, используются ли они для вычислений или для чего-то другого. Пример 8.15 показывает основные методики перегрузки этих операторов.
Давайте начнем с того, что, вероятно, является наиболее часто перегружаемым оператором, — оператора присвоения. Оператор присвоения используется при присвоении одного объекта другому, как в следующем выражении.
Balance x(0), у(32);
x = y;
Вторая строка — это краткая запись вызова Balance::operator=(y)
Для класса Balance
Balance& operator=(const Balance& other) {
val_ = other.val_;
return(*this);
}
Первое, на что вы должны обратить внимание, если не знакомы с перегрузкой операторов, — это синтаксис operator=
operator[symbol]
, где symbol
— это перегружаемый оператор. Единственным различием между операторами и обычными функциями является синтаксис их вызова. На самом деле, если вы хотите ввести побольше кода и написать отвратительно выглядящий код, то операторы можно вызывать и с помощью такого синтаксиса.x.operator=(y); // То же самое, что и x = y, но уродливее
Работа моей реализации оператора присвоения проста. Он обновляет член val_
other
, а затем возвращает ссылку на текущий объект. Операторы присвоения возвращают текущий объект как ссылку, так что вызывающий код может использовать присвоение в выражениях:Balance x, y, z;
// ...
x = (y = z);
Таким образом, возвращаемое из (y = z)
y
, который затем передается в оператор присвоения объекта x
. Такая запись для присвоения используется не так часто, как для арифметических операторов, но чтобы придерживаться общего соглашения, всегда следует возвращать ссылку на текущий объект (то, как это связано с арифметическими операторами, я рассказываю дальше).