Для чего нужно возвращаемое значение в перегрузки операторов?

Рейтинг: 0Ответов: 2Опубликовано: 17.03.2023

Всем привет! Не могу никак разобраться с перегрузкой операторов в 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 понятнее. Вы не запутаетесь, что именно она возвращает.

Примерно так... Если что непонятно и теперь — спрашивайте.

▲ 0

В общем покопавшись немного в интернете, я смог наконец ответить на свой вопрос.

Объект res, созданный внутри перегруженного оператора +, возвращается функцией




return res;




Далее, объект res, созданный в функции main(), принимает все свойства возвращаемого объекта, включая значение поля var (происходит копирование объекта).

Теперь, когда объект res в функции main() содержит все свойства объекта res из перегруженного оператора +, можно обратиться к полю var этого объекта, чтобы получить результат сложения




cout << res.var; 



В данной теме меня волновал момент в коде, где происходил сам факт передачи объекта из класса в блок main().

Для меня, как для человека окунувшимся в ООП, было не понятно, каким образом целый объект присваивается другому объекту. Но теперь узнав, что все свойства одного объекта, могут заменять свойства другого (в данном случае по средством копирования объекта в другой объект), данная тема для меня закрыта =)