между методом и функцией. Дружественной или нет. Свободной и члена-класса.
Как я понимаю, вот мои заблуждения, в которых мне предстоит разобраться:
1. Метод — это функция, описанная в теле или вне класса, для работы через экземпляры этого класса. Из этого следует мой неверный вывод: метод — это просто другое название для функции "внутри объекта класса" к которой можно обратиться через оператор доступа "точка". Из этого следовало, что в классе ничего не называется функцией (как оказалось, ошибка). Ключевое отличие метода — оператор доступа?
2. Значит, у класса есть не только методы, но и функции. Нужно понять, как различать эти сущности.
3. Нужно понять, что такое функция-член, свободная функция, чем они различаются.
4. Перегрузки операторов — отдельная сущность. Оказывается, это по сути тоже функция. Но не метод, потому что нельзя обратиться через оператор доступа.
5. Конструкторы и деструкторы — отдельные сущности или все таки тоже функции?
6. То, как я перегрузил оператор + бессмысленно, раз я в своём классе реализовал сеттеры и геттеры. Надо переделать под два параметра, тогда по непонятным пока что мне причинам доступ к полям класса пропадёт? Кажется, это как-то зависело от количества параметров, а от количества параметров как-то зависело, функция-член класса или свободная функция. Это как-то всё связано, но нужно выстроить цельную картину.
Пойду потихоньку гуглить, но буду рад любой помощи. Ещё раз спасибо!
class foo { public: // спецификатор доступа // функция-член доступна через объект этого класса, по сути она содержит неявный параметр this void boo() {} // оператор foo operator +(const foo&other) { return *this; } // статическая функция-член static void static_func() {} }; ... foo a; foo b; foo c = a + b; // вызов оператора foo d = a.operator+(b); // можно и так вызвать оператор a.boo(); // вызов функции-члена foo::static_func(); // вызов статической функции-члена, она работает вне контекста текущего объекта ну и никаких методов в С++ нет, это просто по инерции мы используем этот термин из терминологии ООП для обозначения функций-членов
Исходя из примера я понял, что: Функция-член — это такая функция, которая доступна через объект этого класса. Метод — термин из терминологии ООП. Вот и путаница. В каком-то смысле — синонимичные термины. Перегрузка оператора — это действие над оператором. Мы прописываем, что оператор должен сделать с объектами класса. Но от этого оператор не перестаёт быть оператором. Т.е. такие сущности нужно называть операторами? Но в общем смысле получается, что оператор — это в каком-то смысле функция? А в контексте перегрузки оператора для класса — функция-член? Я всё ещё не могу понять, почему перегрузка с одним параметром была названа функцией-членом, а с двумя — свободной функцией. Получается, если я буду перегружать оператор через два параметра, я пропишу, что не хочу, чтобы этот оператор был функцией-членом, т.е. не хочу, чтобы у него был неявный указатель this. Поэтому пишу два параметра. Поэтому у меня нет доступа к приватным полям класса? Правильно ли я понял разницу? foo d = a.operator+(b); Не знал про это. Это помогает лучше прочувствовать взаимосвязь всего со всем. Вроде бы оператор, а вроде бы тоже могу его вызвать. А значит тоже своего рода функция. А термины созданы для того, чтобы различать, классифицировать функции, различать сущности. Понял разницу между static и regular функциями-членами на наглядном примере. Большое спасибо за ответ!
почему вы называете это "перегрузками"?
В интернете начитался. Например пишут: «Перегрузка операторов позволяет определить действия, которые будет выполнять оператор. Перегрузка подразумевает создание функции, название которой содержит слово operator и символ перегружаемого оператора.» Или вот ещё: https://docs.microsoft.com/ru-ru/cpp/cpp/operator-overloading?view=msvc-170 После того, как задался всеми этими вопросами, стало ясно, что оператор, вот это всё, это всё таки тоже функция. Путаница в терминах, моя невнимательность. А ещё мне казалось, что есть схожесть с перегрузкой функции, когда у функции одно название, но разные сочетания параметров (количество, типы). Но видимо я что-то напутал.
понятно. хотя термин немного некорректный. потому что перегрузка заменяет одно другим
перегрузку оператора можно оформить как член класса: struct foo { foo operator+(const foo& other); }; так и свободной функцией: struct foo { }; foo operator+(const foo& left, const foo& right) {...} достоинство у второго варианта в том, что можно перегружать оператор для произвольных типов: foo operator+(int left, const foo& right) {...} если они имеют смысл для вашего класса
есть такой термин. считается, что перегрузка оператора - это адаптация встроенных операторов под нужны этого прикладного класса. отсюда перегрузка
Технически оба варианта можно произвольно вносить/выносить из тела класса? Если да, получается, считается хорошим тоном, операторы, которые функции-члены, оставлять внутри тела класса (смысловая связь с наличием this), а те, которые свободные функции, выносить из тела класса (потому что у них нет this, нет доступа к полям)?
Это обязательная принципиальная разница. Вы не можете определить бинарный оператор методом с более чем одним параметром (пока что).
Т.е. в данном случае вынесение за тело класса — это не просто стиль кода?
Вы можете вынести определение, но оно должно оставаться консистентным с объявлением (которое, в случае выбора метода, будет иметь один параметр).
есть набор операторов, которые могут быть только функциями членами. operator=, operator[], operator-> и operator()
внешние операторы позволяют расширят интерфейс класса без изменения его кода. самый наглядный пример это классы std::ostream и std::istream. что бы задать функции сериализации какого-то своего типа, не надо добавлять новые операторы в ostream/istream, достаточно определить свободный операторы. дальше уже ADL сделает всю работу
К своему стыду, я ещё ни разу не встречался с термином «консистентность». Сейчас потихоньку в интернете ищу информацию.
Это и не термин. Edit: Ну или не языковой, по крайней мере... Edit: Я это имел в виду: struct Struct { auto operator + ( int ) -> Struct; }; auto Struct::operator + ( int ) -> Struct { /* ... */ }
Я пытаюсь понять, что именно вы хотели сказать. Что-то нашёл про согласованность данных. Т.е. про какой-то смысл, заложенный в структуру данных. В общем, я могу вынести определение функции-члена за тело класса, если это не нарушает смысла, заложенного в этот класс? P.S. к сожалению, я не понимаю кода, который вы приложили. Но всё равно спасибо за наводку, постараюсь разобраться
Спасибо за пример! По поводу свободной функции, почему её объявили вне класса, стало намного понятнее
Если интересна идейная составляющая вопроса https://youtu.be/WLDT1lDOsb4
Если это определение согласуется с объявлением (разница неформально). В моем примере выше в пределах определения Struct был объявлен метод operator+(), "перегружающий" сложение с int, после чего, уже за пределами определения Struct, было предложено определение этого метода. Из потенциально "новых" синтаксических особенностей: - auto можно писать на позиции типа возвращаемого значения, если этот тип можно контекстно вывести, либо если он указывается в рамках trailing-return-type (посмотрите здесь грамматику (2)), т.е. после -> как в примере. int sub ( ); и auto sub ( ) -> int; эквивалентны. - Имена параметров опциональны в объявлениях и определениях: int sub ( int ); и int sub ( int i ); эквивалентны.
Тебе надо было СЛАТЬ КОД, а не рассуждать. (т.е. слать код и + к этому рассуждать)
Всё не так...
Вывод - идти читать учебник и/или cppreference.com
Обсуждают сегодня