67 / 65 / 61
Регистрация: 11.11.2015
Сообщений: 392
|
||||||||||||||||
1 | ||||||||||||||||
Как правильно перегружать операторы?22.09.2016, 22:03. Показов 3383. Ответов 14
Метки нет Все метки)
(
Добрый день. Более-менее освоил Си, и вроде бы неплохо в нем разбираюсь. Решил взяться за плюсы.
Помогите разобраться с перегрузкой операторов. Я понял, что существуют разные виды перегрузки (как дружественная функция, как функция-член класса). Но когда и какой способ предпочтительно использовать? Вот есть у меня некий класс
Ну и чтобы можно было пользоваться оператором +=? Заранее спасибо.
0
|
22.09.2016, 22:03 | |
Ответы с готовыми решениями:
14
Как же все-таки лучше всего перегружать операторы? Как правильно перегружать оператор? Как правильно перегружать унарный минус? |
7803 / 6567 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
|
|
22.09.2016, 22:06 | 2 |
Как функцию-член класса реализуй. Дружественная только для ввода/вывода, с потоками.
2
|
495 / 209 / 70
Регистрация: 27.05.2016
Сообщений: 557
|
||||||
22.09.2016, 22:24 | 3 | |||||
![]() Решение
1
|
67 / 65 / 61
Регистрация: 11.11.2015
Сообщений: 392
|
|
22.09.2016, 22:39 [ТС] | 4 |
А почему для += нужно возвращать ссылку, а для + константу?
0
|
495 / 209 / 70
Регистрация: 27.05.2016
Сообщений: 557
|
||||||
22.09.2016, 22:55 | 6 | |||||
Такое поведение определено для встроенных типов в С++ и по логике наш оператор += (и все другие операторы присваивания) тоже должен это делать.
Защита от такого кода:
1
|
67 / 65 / 61
Регистрация: 11.11.2015
Сообщений: 392
|
||||||
22.09.2016, 22:58 [ТС] | 7 | |||||
В C++ в таком случае что происходит? (21 строка)
0
|
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
|
||||||
22.09.2016, 23:07 | 8 | |||||
Потому что для + ссылка будет на локальную переменную (на аргументы нельзя - плюс их не меняет) и сдохнет сразу по завершении оператора.
0
|
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
|
|
22.09.2016, 23:16 | 9 |
![]() Решение
Добрый вечер,
давайте разбираться - имеем 2 способа перегрузки операторов: 1) в классе 2) вне класса. Прежде чем говорить о выборе того или другого способа давайте обсудим операторы, которые можно перегрузить только в один способ: а) Перегрузить только как член класса можно: - operator = - operator () - operator[] - operator -> - operator new - operator delete Заметим, что операторы new и delete перегружаются только как статические методы класса - ведь без объекта можно вызвать только статические. А тут важная критерия "без объекта" особенно для оператора new - думаю вы понимаете. б) Перегружать только глобально: - сюда относится только 1 тип операторов, и вопрос я считаю сложным (лично я его и завалил на испыте и получил 11, а не 12 ![]() Кликните здесь для просмотра всего текста
Операторы левый оперант, которых фундаментальный тип или другой пользовательский тип
И так мы определились с правилами без которых ни куда. Далее есть рекомендация от создателя языке С++: "Если оператор подразумевает изменение объекта - его стоит перегрузить как член-класса, в противном случаи - через глобальную функцию" Поэтому если у вас встанет вопрос, какой же выбрать - вспомните эту рекомендацию. Теперь третий и последний вопрос: мы уже определились, что оператор будет перегружен как глобальная функция, но данный оператор является неотъемлемой частью класса в частности оператор вывода/ввода - так как левый оперант у нас "неправильный" и мы вынуждены перегрузить только глобально, то встаёт вопрос - сколько сеттеров/геттеров нужно будет вызвать в этих операторах - хотя эту функцию будет писать тот же программист, и объявлена она будет в том же файле, где и класс. Поэтому очень часто этой функции предоставляют карт-бланш делая её дружественной. Тем самым мы архитектурно говорим, что она наша - просто сложились такие обстоятельства, что она снаружи класса.
3
|
67 / 65 / 61
Регистрация: 11.11.2015
Сообщений: 392
|
|
22.09.2016, 23:30 [ТС] | 10 |
Спасибо, буду разбираться дальше.
0
|
Вездепух
![]() ![]() ![]() 12860 / 6725 / 1807
Регистрация: 18.10.2014
Сообщений: 17,025
|
|
22.09.2016, 23:48 | 11 |
Во-первых, немодифицирующие операторы с симметричными (по типу) операндами (типа бинарных арифметических), рекомендуется реализовывать отдельностоящей [friend] функцией, а не членом класса. Членом класса обычно реализуются только модифицирующие операторы (типа
+= или ++ )Во-вторых, чтобы два раза не делать одно и то же, устойчивой идиомой является реализация бинарного + через += .
0
|
67 / 65 / 61
Регистрация: 11.11.2015
Сообщений: 392
|
|
23.09.2016, 09:35 [ТС] | 12 |
Интересно. Мнения разделились. Выходит строгих правил нет.
0
|
![]() ![]() 3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
|
||||||
23.09.2016, 10:01 | 13 | |||||
Важно подчеркнуть, что, если инициализировать второй и третий параметры конструктора значениями по умолчанию, то складывать скаляр с вектором можно будет только если функция сложения определена не как член класса:
Добавлено через 1 минуту В чем же, по-вашему?
0
|
67 / 65 / 61
Регистрация: 11.11.2015
Сообщений: 392
|
|
23.09.2016, 10:03 [ТС] | 14 |
Ну выше была рекомендация использовать дружественные функции, только для работы с потоками. < >
0
|
![]() ![]() 3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
|
|
23.09.2016, 12:49 | 15 |
Не знаю, где вы это вычитали, здесь вроде бы все согласились, что
Саттер и Александреску в своей книге "Стандарты программирования на С++" рекомендуют предпочитать функции, которые не являются ни членами, ни друзьями (рекомендации 27 и 44). На самом деле это одно из применений основного принципа ООП - всемерной минимизации взаимозависимостей.
1
|
23.09.2016, 12:49 | ||||||
Помогаю со студенческими работами здесь
15
какие операторы нельзя перегружать? Как правильно перегружать потоковый оператор вывода в файл? Для енама нельзя перегружать операторы?
Как правильно перегрузить операторы для собственных классов? Искать еще темы с ответами Или воспользуйтесь поиском по форуму:
|
|
![]() |
Новые блоги и статьи
![]() |
||||
Контейнеризация ML моделей с помощью Docker и Kubernetes
Mr. Docker 14.03.2025
Перенос ML-моделей из лаборатории в продакшн сопровождается целым комплексом проблем. Нередко код, который отлично работает на локальной машине, отказывается функционировать в промышленной среде. . . .
|
Организация масштабируемого хранилища с Apache Cassandra
Codd 14.03.2025
Изначально разработанная в Facebook, а затем переданная Apache Software Foundation, Cassandra сочетает в себе принципы Amazon's Dynamo и Google's BigTable. Эта комбинация создает уникальную. . .
|
Kafka или Pulsar: Что лучше для потоковой обработки в Java
Javaican 14.03.2025
Среди множества решений для потоковой обработки данных Apache Kafka долгое время удерживала лидирующие позиции, став де-факто стандартом в индустрии. Однако в последние годы всё больше внимания. . .
|
Создание и использование компонентов в Vue 3
Reangularity 14.03.2025
Компонент в Vue - это автономный блок интерфейса, который содержит собственную разметку, логику и стили. Представьте себе кнопку, форму ввода или даже целую панель навигации - всё это можно оформить. . .
|
Vue 3: Создаем современное веб-приложение с Composition API
Reangularity 14.03.2025
В фронтенд-разработке Vue 3 выделяется своим прагматичным подходом. В отличие от React с его минималистичной философией "всё — JavaScript" или Angular с его всеобъемлющим корпоративным подходом, Vue. . .
|
Разработка контекстных меню в iOS
mobDevWorks 14.03.2025
С приходом iOS 13 Apple представила новый API для контекстных меню, который полностью заменил предыдущую технологию 3D Touch peek & pop. Хотя многие разработчики и пользователи испытывают ностальгию. . .
|
Лучшие практики оптимизации Docker Image
Mr. Docker 13.03.2025
Размер Docker-образа влияет на множество аспектов работы с контейнерами. Чем больше образ, тем дольше его загрузка в реестр и выгрузка из него. Для команд разработки, работающих с CI/ CD пайплайнами,. . .
|
Вопросы на собеседовании по Docker
Mr. Docker 13.03.2025
Ты сидишь напротив технического специалиста, и вдруг звучит вопрос про Docker Swarm или многоэтапные сборки. Пот на лбу? Не переживай, после этой статьи ты будешь готов ко всему! Эта статья будет. . .
|
Поиск текста в сносках : замена дефиса на тире или тире на дефис...
РоΜа 13.03.2025
Нужно было найти текст в сносках и заменить. Почему-то метод селекшн не сработал. . . пришлось гуглить. найденный на форумвба код пришлось править. Смысл - заменяет в сносках дефисы и тире на нужные. . . .
|
Real PATH definitions in bash scripts
jigi33 13.03.2025
Как поймать путь и путь к директории относительно запускаемого файла в BASH
1. поймать путь через вывод $(pwd)
2. более правильно - на основе realpath (см. скриншот)
|