Для чего нужно возвращаемое значение в перегрузки операторов?
Всем привет! Не могу никак разобраться с перегрузкой операторов в C++.
Есть некоторый код, который я хочу привести в пример, его я добыл на одном из ресурсов, где объяснялась тема перегрузки операторов:
#include <iostream>
using namespace std;
class MyClass {
public:
int var;
MyClass() { }
MyClass(int a)
: var(a) { }
MyClass operator+(MyClass &obj) {
MyClass res;
res.var= this->var+obj.var;
return res;
}
};
int main() {
MyClass obj1(12), obj2(55);
MyClass res = obj1+obj2;
cout << res.var;
}
В данном коде, по моей точке зрения, происходит следующее:
Строка MyClass obj1(12), obj(55); инициализирует объекты obj1 и obj2, а так же по порядку передаёт значения 12 и 55 в член класса var(a), тем самым присваивая члену var эти значения для каждого отдельного объекта.
Далее, Строка MyClass res = obj1+obj2; выполняет сразу несколько операций, первой выполняется часть obj1+obj2;, которая передаётся в данную часть кода:
MyClass operator+(MyClass &obj) {
MyClass res;
res.var= this->var+obj.var;
return res;
}
};
И вот именно в этой части кода я начинаю задаваться вопросом, а зачем нам возвращаемое значение return res;? По моей логике, мы здесь перегружаем оператор + и записываем результат в член класса var, с помощью записи res.var. Если это не так, то поправьте меня. Дальше у меня начинают появляться ещё вопросы. Зачем мы возвращаем return res;? Что находится в res, результат выполнения операции сложения? Просто, если он передаёт результат операции сложения, то разве не логичнее сделать возвращаемое значение таким return res.var? Я пробовал такую запись и результат был таким же. Однако, на этом я не остановился и решил вовсе убрать возвращаемое значение из данного блока кода. Когда я его убрал, результат на мое удивление тоже не поменялся! Почему результат все равно вывелся таким же? А когда я решил написать return 0;, то вывелся 0. Хотя 0 это же совершенно другой тип данных? Во первых, как он вообще передался, ведь там тип данных MyClass должен быть, а во вторых, почему вывелся 0, если при удалении return, результат вывода не менялся?
Ответы (2 шт):
Сама идея перегрузки операторов в том, чтобы можно было писать то же a+b не только для чисел, но и для объектов пользовательских классов.
Поскольку идея выполнять для a+b что-то типа "записать a в файл b" или что еще, никак не напоминающее умножение, хотя и вполне реализуема, но ужасна сама по себе, операторы в идеале должны иметь ту же семантику, что и встроенные.
В вашем классе есть одно поле — число var, так что логично применять оператор для сложения этих var. Можно, конечно, и для умножения или деления, но это будет уже неверная семантика. Так что будем складывать.
Но для чего? Вы же не пишете в программах 2+15 и все? Результат сложения чему-то присваивается. Поэтому он должен быть. Иначе в таком присваивании никакого смысла!
Можно, конечно, возвращать, например, строку... но это опять же нарушение семантики :)
Давайте просто возвращать такой же объект. Потому что можно вернуть и число, но как-то странно смотрится
MyClass a, b;
int с = a + b;
Нет?
Итак, возвращаем такой же объект. У которого член var является суммой членов.
Очевидно, что слагаемые не изменяются, правда ведь? Так что объявить оператор мы должны как
MyClass operator+(const MyClass &obj) const
или как свободный оператор
MyClass operator+(const MyClass &obj1, const MyClass &obj2)
Собственно, дальше только написать суммирование. Я бы, кстати, написал как
MyClass operator+(const MyClass &obj) const
{
return MyClass(var + obj.var);
}
Вот вкратце и все.
Когда вы возвращаете число, тот же 0, у вас просто из этого нуля создается объект возвращаемого типа MyClass. Конечно, вполне можно и так. Просто подробная запись через MyClass понятнее. Вы не запутаетесь, что именно она возвращает.
Примерно так... Если что непонятно и теперь — спрашивайте.
В общем покопавшись немного в интернете, я смог наконец ответить на свой вопрос.
Объект res, созданный внутри перегруженного оператора +, возвращается функцией
return res;
Далее, объект res, созданный в функции main(), принимает все свойства возвращаемого объекта, включая значение поля var (происходит копирование объекта).
Теперь, когда объект res в функции main() содержит все свойства объекта res из перегруженного оператора +, можно обратиться к полю var этого объекта, чтобы получить результат сложения
cout << res.var;
В данной теме меня волновал момент в коде, где происходил сам факт передачи объекта из класса в блок main().
Для меня, как для человека окунувшимся в ООП, было не понятно, каким образом целый объект присваивается другому объекту. Но теперь узнав, что все свойства одного объекта, могут заменять свойства другого (в данном случае по средством копирования объекта в другой объект), данная тема для меня закрыта =)