- •Введение в перегрузку операций
- •Операции, как функции
- •Использование перегруженных операций
- •Ограничения в перегрузке операций
- •Перегрузка операций через дружественные функции
- •Перегрузка операций через дружественные функции
- •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 () {
Int m_dollars;
public:
Dollars (int dollars) {m_dollars = dollars;}
Int getDollars () const {return m_dollars;}
};
// Примечание: Эта функция перегрузки не является ни методом //класса, ни дружественной классу Dollars!
Dollars operator+(const Dollars &d1, const Dollars &d2)
{ // Используем конструктор Dollars и operator+ (int, int). Здесь нам //не нужен прямой доступ к закрытым членам класса Dollars
return Dollars (d1.getDollars () + d2.getDollars ());
}
Int main () {
Dollars dollars1(7);
Dollars dollars2(9);
Dollars dollarsSum = dollars1 + dollars2;
std::cout << "I have " << dollarsSum.getDollars() << " dollars." << std::endl;
return 0;
}
Поскольку принцип перегрузки операций через обычные и дружественные функции почти идентичен (они просто имеют разные уровни/условия доступа к закрытым членам класса), то единственное отличие заключается в том, что в случае с дружественной функцией, её нужно обязательно объявить в классе, а определить вне тела класса (или в классе), в то время как обычную функцию достаточно просто определить вне тела класса, без указания прототипа функции.
Dollars.h:
class Dollars {
private:
Int m_dollars;
public:
Dollars (int dollars) {m_dollars = dollars;}
Int getDollars () const {return m_dollars;}
};
// Указываем прототип внешней функции operator+ (), чтобы иметь //возможность использовать перегруженную оператор + в других //файлах
Dollars operator+(const Dollars &d1, const Dollars&d2);
Dollars.cpp:
#include "Dollars.h"
// Примечание: Эта функция внешняя, не является ни методом
// класса, ни дружественной классу Dollars!
Dollars operator+(const Dollars &d1, const Dollars &d2)
{ // Используем конструктор Dollars и operator+ (int, int).
// Здесь нам не нужен прямой доступ к закрытым членам класса //Dollars
return Dollars(d1.getDollars() + d2.getDollars());
}
main.cpp:
#include <iostream>
#include "Dollars.h"
Int main () {
Dollars dollars1(7);
Dollars dollars2(9);
Dollars dollarsSum = dollars1 + dollars2; // без явного указания //прототипа operator+ () в Dollars.h эта строка не скомпилировалась //бы
std::cout << "I have " << dollarsSum.getDollars() << " dollars." << std::endl;
return 0; }
Для перегрузки операций рекомендуется использовать обычные функции, нежели дружественные, если в классе, конечно, присутствуют геттеры (чем меньше функций касается внутренних элементов вашего класса, тем лучше).
Однако не добавляйте дополнительный геттер только для того, чтобы перегрузить операцию через обычную функцию вместо дружественной!
Если геттера нет по умолчанию или он не используется вообще (в нем нет необходимости), то тогда используйте перегрузку через дружественные функции.
Правило: Используйте перегрузку операций через обычные функции, вместо дружественных, если для этого не требуется добавление дополнительных функций в класс.
Перегрузка операций ввода и вывода
Рассмотрим перегрузку операций ввода и вывода в языке C++.
Перегрузка операции вывода <<
Для классов с множеством переменных-членов, выводить в консоль каждую переменную по отдельности может быть несколько утомительно. Например, рассмотрим следующий класс:
class Point {
private:
double m_x, m_y, 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) { }
double getX() { return m_x; }
double getY() { return m_y; }
double getZ() { return m_z; }
};
Если вы захотите вывести объект этого класса на экран, то вам нужно будет сделать что-то вроде следующего:
Point point (3.0, 4.0, 5.0);
std::cout << "Point(" << point.getX() << ", " <<
point.getY() << ", " <<
point.getZ() << ")";
Конечно, было бы проще написать отдельную функцию для вывода, которую можно было бы повторно использовать. Например, функцию print ():
class Point {
private:
double m_x, m_y, 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) { }
double getX() { return m_x; }
double getY() { return m_y; }
double getZ() { return m_z; }
