- •Введение в перегрузку операций
- •Операции, как функции
- •Использование перегруженных операций
- •Ограничения в перегрузке операций
- •Перегрузка операций через дружественные функции
- •Перегрузка операций через дружественные функции
- •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 main (){
IntArray array;
array[4] = 5; // хорошо: вызывается неконстантная версия //operator[]()
std::cout << array[4];
const IntArray carray;
carray[4] = 5; // ошибка компиляции: вызывается константная //версия operator[](), которая возвращает константную ссылку. //Выполнять операцию присваивания нельзя
std::cout << carray[4];
return 0;
}
Строку carray[4] = 5; нужно закомментировать и программа скомпилируется (это проверка на изменение данных константных объектов — изменять данные нельзя, можно только выводить).
Проверка ошибок
Еще одним преимуществом перегрузки операции индексации является то, что мы можем выполнять проверку передаваемых значений индекса.
При прямом доступе к элементам массива (через геттеры и сеттеры), оператор индекса не проверяет, является ли индекс корректным. Например, компилятор не будет жаловаться на следующий код:
int array[7];
array[9] = 4; // индекс 9 является некорректным (вне допустимого //диапазона)!
Однако, если мы знаем длину нашего массива, мы можем выполнять проверку передаваемого индекса на корректность в функции перегрузки операции []:
#include <cassert> // для assert ()
class IntArray {
private:
Int m_array[10];
public:
Int& operator [] (const int index);
};
Int& IntArray::operator[] (const int index) {
assert(index >= 0 && index < 10);
return m_array[index];
}
В примере, приведенном выше, мы использовали вызов функции assert (которая определена в заголовочном файле cassert) для проверки диапазона index.
Если выражение внутри assert принимает значение false (т.е. пользователь ввел некорректный индекс), то программа немедленно завершится с выводом сообщения об ошибке, что лучше, нежели альтернативный вариант — повреждение памяти.
Это самый распространенный способ проверки ошибок с использованием функций перегрузки.
Указатели на объекты и перегруженный оператор []
Если вы попытаетесь вызвать operator [] () для указателя на объект, то C++ предположит, что вы пытаетесь индексировать массив.
Рассмотрим следующий пример:
#include <cassert> // для assert ()
class IntArray {
private:
int m_array [10];
public:
int& operator [] (const int index);
};
int& IntArray::operator [] (const int index) {
assert (index >= 0 && index < 10);
return m_array[index];
}
int main () {
IntArray *array = new IntArray;
array [4] = 5; // ошибка
delete array;
return 0;
}
Дело в том, что указатель указывает на адрес памяти, а не на значение. Поэтому сначала указатель нужно разыменовать, а затем уже использовать оператор []:
int main () {
IntArray *array = new IntArray;
(*array) [4] = 5; // сначала разыменовываем указатель для //получения объекта array, а затем вызываем operator []
delete array;
return 0;
}
Здесь очень легко наделать ошибок. Не используйте указатели на объекты, если это не является обязательным.
Передаваемый аргумент не обязательно должен быть целым числом
Как упоминалось выше, C++ передает в функцию перегрузки то, что пользователь указал в квадратных скобках в качестве аргумента (в большинстве случаев, это целочисленное значение).
Однако это не является обязательным требованием и, на самом деле, вы можете определить функцию перегрузки так, чтобы ваш перегруженный оператор [] принимал значения любого типа, которого вы только пожелаете (double, string и т.д.).
Например:
#include <iostream>
#include <string>
class Something {
private:
public:
