C ++ не позволяет функции, которая складывает два целых числа и возвращает целое число, добавлять два числа с плавающей запятой и возвращать одно число с плавающей запятой. Представьте, что есть функция, складывающая два целых числа и возвращающая целое число. Было бы неплохо иметь еще одну функцию с тем же именем, которая добавляет только два или даже больше числа с плавающей запятой для возврата числа с плавающей запятой? Это называется перегрузкой первой функции.
Арифметические операторы обычно используются для арифметических операций. Разве не хорошо иметь +, соединять две строки? Включение этого называется перегрузкой оператора арифметического сложения для строк.
Оператор инкремента ++ добавляет 1 к int или float. При работе с указателями он не добавляет к указателю 1. Это заставляет указатель указывать на следующий последовательный объект в памяти. Итератор указывает на следующий объект в связанном списке, но объекты связанного списка находятся в разных местах памяти (а не в последовательных областях). Было бы неплохо перегрузить оператор инкремента для итератора, чтобы увеличивать, но указывать на следующий элемент в связанном списке?
В этой статье объясняется перегрузка в C ++. Он разделен на две части: перегрузка функции и перегрузка оператора. Для понимания остальной части статьи необходимо уже иметь базовые знания C ++.
Перегрузка функций
Следующая функция добавляет два целых числа и возвращает целое число:
int add(int no1, int no2)
{
int sum = no1 + no2;
return sum;
}The prototype of this function is:
int add(int no1, int no2);
The prototype of a function in the header of the function, ending with a semicolon. The following function with the same name, but with a different prototype, would add three floats and return a float:
float add(float no1, float no2, float no3)
{
float sum = no1 + no2 + no3;
return sum;
}
Как компилятор определяет, какую функцию вызывать, если две или более функций имеют одинаковое имя? Компилятор использует количество аргументов и типы аргументов, чтобы определить, какую функцию вызывать. Список параметров перегруженных функций должен различаться по их количеству и / или типам параметров. Итак, вызов функции,
int sm = add(2, 3);
вызовет целочисленную функцию, а вызов функции
float sme = add(2.3, 3.4, 2.0);
вызовет функцию с плавающей запятой. Примечание: бывают ситуации, когда компилятор отклоняет перегруженную функцию, когда количество аргументов одинаковое, но разных типов! — Причина: — см. Позже.
Следующая программа приводит в действие указанные выше сегменты кода:
#include <iostream>
using namespace std;int add(int no1, int no2)
{
int sum = no1 + no2;
return sum;
}float add(float no1, float no2, float no3)
{
float sum = no1 + no2 + no3;
return sum;
}int main()
{
int sm = add(2, 3);
cout<<sm<<‘\n‘;
float sme = add(2.3, 3.4, 2.0);
cout<<sme<<‘\n‘;return 0;
}
Результат:
5
7,7
Перегрузка оператора
Арифметические операторы используются для перегрузки операций в типах классов. Итератор — это тип класса. Операторы инкремента и декремента используются для перегрузки операций итератора.
Пример перегрузки оператора класса String
В этом разделе представлен пример, в котором + перегружен для просто разработанного строкового класса, называемого классом пружины. + объединяет литералы двух строковых объектов, возвращая новый объект с объединенными литералами. Объединение двух литералов означает присоединение второго литерала к концу первого литерала.
Теперь в C ++ есть специальная функция-член для всех классов, называемая оператором. Программист может использовать эту специальную функцию для перегрузки операторов, таких как +. Следующая программа показывает перегрузку оператора + для двух строк.
#include <iostream>
using namespace std;class spring
{
public:
//data members
char val[100];
int n;
char concat[100];
//member functions
spring (char arr[])
{
for (int i=0; i<100; ++i) {
val[i] = arr[i];
if (arr[i] == ‘\0‘)
break;
}
int i;
for (i=0; i<100; ++i) if (arr[i] == ‘\0‘) break;
n = i;
}
spring operator+(spring& st) {
int newLen = n + st.n;
char newStr[newLen+1];
for (int i=0; i<n; ++i) newStr[i] = val[i];
for (int i=n; i<newLen; ++i) newStr[i] = st.val[i—n];
newStr[newLen] = ‘\0‘;
spring obj(newStr);
return obj;
}
};int main()
{
char ch1[] = «I hate you! «; spring str1(ch1);
char ch2[] = «But she loves you!»; spring str2(ch2);
char ch3[] = «one»; spring str3(ch3);
str3 = str1 + str2;
cout<<str3.val<<‘\n‘;return 0;
}
Значение str1 — «Я тебя ненавижу!». Значение str2 — «Но она тебя любит!». А также, значение str3, то есть str1 + str2, является выходом:
«Я ненавижу тебя! Но она тебя любит!» который представляет собой конкатенацию двух строковых литералов. Сами строки представляют собой экземпляры объектов.
Определение операторной функции находится внутри описания (определения) строкового класса. Он начинается с возвращаемого типа «пружина» вместо «струна». Специальное имя «оператор, следуйте за этим». После этого идет символ оператора (подлежащего перегрузке). Затем идет список параметров, который на самом деле является списком операндов. + — это бинарный оператор: это означает, что он принимает левый и правый операнды. Однако, согласно спецификации C ++, в списке параметров здесь есть только правильный параметр. Затем идет тело операторной функции, которое имитирует поведение обычного оператора.
Согласно спецификации C ++, определение оператора + принимает только параметр правого операнда, потому что остальная часть описания класса является параметром левого операнда.
В приведенном выше коде только определение функции operator + () связано с перегрузкой +. Остальная часть кода класса — это обычная кодировка. Внутри этого определения два строковых литерала объединены в массив newStr []. После этого фактически создается новый строковый объект (экземпляр) с использованием аргумента newStr []. В конце определения функции operator + () возвращается вновь созданный объект, имеющий объединенную строку.
В функции main () добавление выполняется с помощью оператора:
str3 = str1 + str2;
Где str1, str2 и str3 — строковые объекты, которые уже были созданы в main (). Выражение «str1 + str2» с его + вызывает функцию-член operator + () в объекте str1. Функция-член operator + () в объекте str1 использует str2 в качестве аргумента и возвращает новый объект с (разработанной) объединенной строкой. Оператор присваивания (=) полного оператора заменяет содержимое (значения переменных) объекта str3 содержимым возвращенного объекта. В функции main () после добавления значение элемента данных str3.val больше не равно «единице»; это сложенная (сложенная) строка: «Я тебя ненавижу! Но она тебя любит!». Функция-член operator + () в объекте str1 использует строковый литерал своего собственного объекта и строковый литерал своего аргумента str2 для получения объединенного строкового литерала.
Перегрузка оператора итератора
При работе с итератором задействованы как минимум два объекта: связанный список и сам итератор. Фактически задействованы как минимум два класса: класс, из которого создается связанный список, и класс, из которого создается итератор.
Связанный список
Схема для объекта двусвязного списка:
Этот список состоит из трех элементов, но их может быть больше. Три элемента здесь являются элементами целых чисел. Первый имеет значение 14; следующий имеет значение 88; а последний имеет значение 47. Каждый элемент здесь состоит из трех последовательных местоположений.
Это не похоже на массив, где каждый элемент находится в одном месте, а все элементы массива находятся в последовательных местах. Здесь разные элементы находятся в разных местах в памяти, но каждый элемент состоит из трех последовательных ячеек.
Для каждого элемента среднее расположение содержит значение. В правильном месте находится указатель на следующий элемент. В левом месте находится указатель на предыдущий элемент. Для последнего элемента правильное расположение указывает на теоретический конец списка. Для первого элемента левая позиция указывает на теоретическое начало списка.
В массиве оператор инкремента (++) увеличивает указатель на физически следующее местоположение. В списке элементы не находятся в последовательных областях памяти. Итак, оператор инкремента может быть перегружен, переместив итератор (указатель) с одного элемента на логически следующий элемент. Такая же проекция применяется к оператору декремента (-).
Прямой итератор — это итератор, который при включении указывает на следующий элемент. Обратный итератор — это итератор, который при включении указывает на предыдущий элемент.
Перегрузка ++ ad —
Перегрузка этих операторов выполняется в описании (определении) класса итератора.
Синтаксис прототипа префикса перегрузки оператора приращения:
ReturnType operator++();
Синтаксис прототипа перегрузки оператора инкремента, postfix, следующий:
ReturnType operator++(int);
Синтаксис прототипа перегрузки оператора декремента, префикса, следующий:
ReturnType operator—();
Синтаксис прототипа перегрузки оператора инкремента, postfix, следующий:
ReturnType operator—(int);
Заключение
Перегрузка означает придание функции или оператора разного значения. Функции перегружены в той же области. Что отличает перегруженные функции, так это количество и / или типы параметров в их списках параметров. В некоторых случаях, когда количество параметров одинаковое, но с разными типами, компилятор отклоняет перегрузку — см. Ниже. Многие обычные операторы могут быть перегружены в классах, из которых создаются экземпляры объектов. Для этого специальной функции с именем operator в описании класса присваивается тип возвращаемого значения, список параметров и тело. и тело.