- •Введение в перегрузку операций
- •Операции, как функции
- •Использование перегруженных операций
- •Ограничения в перегрузке операций
- •Перегрузка операций через дружественные функции
- •Перегрузка операций через дружественные функции
- •Int main () {
- •I have 16 dollars.
- •Int m_dollars;
- •Int getDollars () const {return m_dollars;}
- •Int main () {
- •Дружественные функции могут быть определены внутри класса
- •Int m_dollars;
- •Int getDollars () const {return m_dollars;}
- •Int main () {
- •Перегрузка операций с операндами разных типов
- •Int m_dollars;
- •Int getDollars () {return m_dollars;}
- •Int main () {
- •Values (int min, int max) {
- •Int getMin () {return m_min;}
- •Int getMax () {return m_max;}
- •Int main () {
- •Int main () {
- •Int main () {
- •Перегрузка операций через обычные функции
- •Int m_dollars;
- •Int getDollars () const {return m_dollars;}
- •Int main () {
- •Int m_dollars;
- •Int getDollars () const {return m_dollars;}
- •Int main () {
- •Int m_dollars;
- •Int getDollars () const {return m_dollars;}
- •Int main () {
- •Перегрузка операций ввода и вывода
- •Void print () {
- •Int main () {
- •Int main () {
- •Int main () {
- •Int main () {
- •Int main () {
- •Int m_numerator;
- •Int m_denominator;
- •Void reduce () {
- •Void print () {
- •Перегрузка операций через методы классов
- •Int m_dollars;
- •Int getDollars () { return m_dollars; }
- •Int main () {
- •Int m_dollars;
- •Int getDollars () {return m_dollars;}
- •Int main (){
- •Не всё может быть перегружено через дружественные функции
- •Не всё может быть перегружено через методы класса
- •Int main (){
- •Какой способ перегрузки и когда следует использовать?
- •Int m_dollars;
- •Int getDollars () const {return m_dollars;}
- •Int main () {
- •If (!isHappy)
- •Int main () {
- •If (!something)
- •Перегрузка операций сравнения
- •Int main () {
- •Int m_dollars;
- •Int main () {
- •Перегрузка операторов инкремента и декремента
- •Int m_number;
- •Int main () {
- •Перегрузка операций инкремента и декремента версии постфикс
- •Int m_number;
- •Int main () {
- •Перегрузка операции индексации []
- •Почему оператор индексации [] использует возврат по ссылке?
- •Использование оператора индексации с константными объектами класса
- •Int& operator[] (const int index);
- •Int main (){
- •IntArray array;
- •Проверка ошибок
- •Int m_array[10];
- •Int& operator [] (const int index);
- •Int& IntArray::operator[] (const int index) {
- •Указатели на объекты и перегруженный оператор []
- •Передаваемый аргумент не обязательно должен быть целым числом
- •Void operator [] (std::string index);
- •Void Something::operator [] (std::string index){
- •Int main () {
- •Перегрузка операции ()
- •Int main () {
- •Void operator() ();
- •Void Matrix::operator()() {
- •Int main() {
- •Перегрузка операций преобразования типов данных
- •Int m_dollars;
- •Int getDollars () { return m_dollars; }
- •Int main () {
Void reduce () {
int nod = Fraction::nod(m_numerator, m_denominator);
m_numerator /= nod;
m_denominator /= nod;
}
friend Fraction operator*(const Fraction &f1, const Fraction &f2);
friend Fraction operator*(const Fraction &f1, int value);
friend Fraction operator*(int value, const Fraction &f1);
Void print () {
std::cout << m_numerator << "/" << m_denominator << "\n";
}
};
Fraction operator*(const Fraction &f1, const Fraction &f2) {
return Fraction (f1.m_numerator * f2.m_numerator, f1.m_denominator * f2.m_denominator);
}
Fraction operator*(const Fraction &f1, int value) {
return Fraction (f1.m_numerator * value, f1.m_denominator);
}
Fraction operator*(int value, const Fraction &f1) {
return Fraction (f1.m_numerator * value, f1.m_denominator);
}
Перегрузка операций через методы класса
Перегрузка операций через методы класса очень похожа на перегрузку операций через дружественные функции. Но при перегрузке операции через метод класса левым операндом становится неявный объект, на который указывает скрытый указатель this.
Перегрузка операций через методы классов
Вспомним, как выглядит перегрузка операции через дружественную функцию:
#include <iostream>
class Dollars {
private:
Int m_dollars;
public:
Dollars (int dollars) { m_dollars = dollars; }
// Выполняем Dollars + int
friend Dollars operator+(const Dollars &dollars, int value);
Int getDollars () { return m_dollars; }
};
Dollars operator+(const Dollars &dollars, int value) {
return Dollars (dollars.m_dollars + value);
}
Int main () {
Dollars dollars1(7);
Dollars dollars2 = dollars1 + 3;
std::cout << "I have " << dollars2.getDollars() << " dollars.\n";
return 0;
}
Конвертация перегрузки через дружественную функцию в перегрузку через метод класса довольно-таки проста:
Перегрузка операции определяется как метод класса, вместо дружественной функции (Dollars::operator+ вместо friend operator+).
Левый параметр из функции перегрузки выбрасывается, вместо него будет неявный текущий объект, на который указывает указатель this.
Внутри тела функции перегрузки все ссылки на левый параметр могут быть удалены (например, dollars.m_dollars становится m_dollars
, который неявно ссылается на текущий объект с помощью указателя this).
Теперь та же перегрузка операции +, но уже через метод класса:
#include <iostream>
class Dollars{
private:
Int m_dollars;
public:
Dollars (int dollars) { m_dollars = dollars; }
// Выполняем Dollars + int
Dollars operator+(int value);
Int getDollars () {return m_dollars;}
};
// Примечание: Эта функция является методом класса!
// Вместо параметра dollars в перегрузке через дружественную //функцию здесь неявный параметр, на который указывает указатель //this, явный параметр отсутствует
Dollars Dollars::operator+ (int value) {
return Dollars (m_dollars + value);
}
Int main (){
Dollars dollars1(7);
Dollars dollars2 = dollars1 + 3;
std::cout << "I have " << dollars2.getDollars() << " dollars.\n";
return 0;
}
Обратите внимание, использование в main операции + не изменяется (в обоих случаях dollars1 + 3), но реализация отличается.
Наша дружественная функция с двумя параметрами становится методом класса с одним параметром, причем левый параметр в перегрузке через дружественную функцию (Dollars&dollars), в перегрузке через метод класса становится неявным объектом, на который указывает указатель this.
Рассмотрим детально для понимания, как обрабатывается выражение
dollars1 + 3.
В перегрузке через дружественную функцию выражение dollars1 + 3 приводит к вызову функции operator+(dollars1, 3). Здесь есть два параметра.
В перегрузке через метод класса выражение dollars1 + 3 приводит к вызову dollars1.operator+(3).
Обратите внимание, здесь уже один явный параметр, а dollars1 используется как префикс к operator+. Этот префикс компилятор неявно конвертирует в скрытый левый параметр, на который указывает указатель this.
Таким образом, dollars1.operator+(3), что по сути очень похоже на вызов operator+(dollars1, 3), что почти идентично перегрузке через дружественную функцию.
Итак, если мы можем перегрузить операцию через дружественную функцию или через метод класса, то что тогда выбрать? Прежде чем мы дадим ответ на этот вопрос, вам нужно узнать еще несколько деталей.
