Как передать объект в тело функции?
- Войдите на сайт для отправки комментариев
Втр, 17/03/2020 - 16:52
Исходный код у меня такой...
#include <ModbusRtu.h>
#include <OneWire.h>
#define DS18B20_1_Pin A2 // DS18B20 к пину
OneWire ds(DS18B20_1_Pin); // создаем объект OneWire(номер порта)
//*********************************************************
// Функция начальной конфигурации датчика
//*********************************************************
void setConfig() {
ds.reset(); // команда "сброс"
ds.skip(); // команда "пропустить ROM"
ds.write(0x4E); // команда "заисать в память"
ds.write(0x55); // записываем TH
ds.write(0x05); // записываем TL
ds.write(0x1F); // записываем "разрядность 9 бит"
ds.reset(); // команда "сброс"
}
Вопрос: Как передать в функцию setConfig() созданный мной объект ds, либо другой объект, что бы использовать одну и ту же функцию для разных объектов.
setConfig(OneWire & ds)
Чаще всего объекты следует передавать ссылкой (&)
А внутри самой функции как использовать?
например для
ds.reset(); // команда "сброс"
так же
setConfig(OneWire & ds)
Чаще всего объекты следует передавать ссылкой (&)
а указателем чем хуже?
setConfig(OneWire* ds)
Ссылка не может быть пустой, не подвержена арифметике и другим манипуляциям, тут не нужным. Тем самым не дает скомпилироваться большему количеству неверного кода.
paramen - вместо того что выкладывать сюда самочевидный код, лучше бы правила форума почитали
Для Вас это - "самочевидный код". Для меня это серьезный шаг в программировании. Мы с Вами наверно на "разных берегах", берите пример с rkit.
Дополню: правила хорошего тона требуют квалификатор const, когда переданный объект внутри функции - не изменяется:
Также - лучше не использовать имён object и т.п. - вполне возможно, в будущем вылезет боком: захочет комитет по С++ ввести такое ключевое слово - и амба. Да и во многих ЯП object - ключевое слово, поэтому - лучше ниннада, переносимость алгоритмов только повысится.
Правила хорошего тона говорят, что нужно понимать, о чем пишешь, а не выдумывать, что объект не изменяется, когда он явно изменяется.
Просто интересно - в каком месте данного кода "object" изменяется?
Правила хорошего тона говорят, что нужно понимать, о чем пишешь, а не выдумывать, что объект не изменяется, когда он явно изменяется.
Очередной высер от недоучки. Покажи, где изменяется объект? Пёрнул в лужу, как обычно.
Буквально в каждой строчке. Посмотри в исходники методов. Да даже не надо ничего знать о классе и исходниках, достаточно посмотреть на то, что есть методы, которые ничего не возвращают и не принимают. Они методом исключения что-то изменяют.
Вообще, с const-экземпляром могут работать только const-методы, и в библиотеке их просто нет.
И прежде чем баба завопит еще, добавлю, что среда arduino компилирует с -fpermissive, делая этот квалификатор бесполезным.
Да я посмотрел ещё до вопроса - reset(), skip(), write() не изменяют приватных/публичных переменных класса, используя локальные переменные функций и делая bit-banging ногой шины. Поэтому и поинтересовался - что в конкретном примере препятствует использованию const.
rkit, ты спицально уйню несешь?
Ни одна из них не объявлена как const.
Вобщем, тут каким-то холиваром запахло.
rkit, ты спицально уйню несешь?
Возьми нормальный компилятор (не arduino), и ты увидишь, что код с const вообще не компилируется. На этом разговор считаю закрытым.
Согласен. Я х-ню несу. Константный модификатор игнорируется при изменении объекта по ссылке.
передал String по ссылке (const String &s)
Приношу извинения за напраслину, безграмотный здесь я. :)
Ни одна из них не объявлена как const.
Потому что писали такие же недоучки, как ты. На деле же, объект в примере - нигде не изменяется. Но тебе же лень исходники глянуть, главное - погромче пёрнуть, пообзывать всех бабами, дырочка ты наша.
Ещё раз повторюсь: пёрнул - хоть руками помаши.
Согласен. Я х-ню несу. Константный модификатор игнорируется при изменении объекта по ссылке.
передал String по ссылке (const String &s)
Приношу извинения за напраслину, безграмотный здесь я. :)
Деда, тут нет ничего необычного. Просто ты видишь warning, и это - правильно. Когда тебе предоставляют метод, принимающий некий объект по ссылке, с квалификатором const - ты уже на этом уровне будешь уверен, что состояние объекта останется неизменным после отработки тела функции. Ну а далее - уже правильная реализацию const-методов класса, например. В твоём случае - настройки компилятора позволяют делать то, что ты сделал, но выдают warning. Уберёшь const - не будет warning. Уберёшь -fpermissive - не скомпилируется.
Но введение const, вне зависимости от настроек компилятора - это достаточно простой шаг для автодокументирования кода (скажем так, безграмотно). Конечно, это не отменяет юнит-тестов, например, но - помогает.
Многие, очень многие классы в Arduino написаны не очень. Поэтому авторы IDE тупо включили -fpermissive, чтобы оно всё хоть как-то компилировалось.
Но ещё раз повторюсь: если объект, переданный по ссылке, не изменяется в методе, то хорошим тоном является использование квалификатора const, явным образом сообщающим об этом. "Является хорошим тоном" != "обязательно использовать", конечно. Всё остальное, включая const-методы объекта - это уже архитектурный слой.
rkit, ты спицально уйню несешь?
Возьми нормальный компилятор (не arduino), и ты увидишь, что код с const вообще не компилируется. На этом разговор считаю закрытым.
А с каких это пор GCC перестал быть нормальным компилятором? Просто потому, что Arduino IDE вызывает его с некими настройками?
rkit, ты жутко напоминаешь Великого - как сказанёшь мощно - аж внушаить...
есть методы, которые ничего не возвращают и не принимают. Они методом исключения что-то изменяют.
Надо распечатать, и повесить на стеночку, рядом с портретом Ванги. Считаю - это очень мощное заявление, прямо таки пророческое, невиданной доселе величины.
Ключевое тут, считаю - "что-то". Конкретно вот - что-то таки изменяют, и пошли вы все нахер, руки прочь от Великого (ну он это, он).
Обьект с модификатором const можно передавать, только если используются его функции с явным модификатором const. Иначе, моветон и костыли, неизвестно как проявящиеся в будущем.
Поэтому, в данном конкретном случае, я признаю свою безграмотность перед rkit. У меня все в данной теме.
У меня все в данной теме.
У меня - тоже. В первоначальном примере - объект не изменяется, в твоём - изменяется. Используемые методы объекта в первом примере - нужно определить как const, для полного феншуя, т.к. они ничего не изменяют в состоянии объекта.
Использовать квалификатор const - естественно, надо с умом, именно поэтому я и написал "хорошим тоном" (что влечёт за собой кучу условностей, по определению, включая архитектурный слой).
Девочка же в ответ на это - сильно возбудилась, и начала пукать зачем-то и дальше. Вон, GCC уже обвинила в том, что некошерный это компилятор, видите ли.
Он не компилятор обвинял, а IDE, по умолчанию скрывающую warning-и
P.S. Мне не нравится его апломб и манеры общения, но если он прав, я это признаЮ.
я признаю свою безграмотность
Во-первых, не прибедняйся ;) Во-вторых, смотри, для чего вся эта чухня с квалификатором const. Допустим, у класса OneWire есть метод setPin(uint8_t pin) - который меняет линию, с которой работает объект. Создал ты такой объект OneWire, передал ему в конструктор пин номер 2. Затем - передал этот объект по ссылке в метод, написанный сторонним разработчиком. Передача по ссылке - без квалификатора const.
И такой внезапно по выходе из метода обнаруживаешь, что показания датчиков (например, DS18B20) пропали. А всё потому, что внутри функции сторонний разработчик позвал setPin с пином номер 3, вот так ему захотелось, по каким-то моральным соображениям. А если у тебя нет доступа к исходному коду Васи (например, это вызов Васей какого-нибудь API, которое ты ему предоставляешь)? Твоя задача в этом случае - обезопасить себя (на Васю - похер, он сам себе rkit), и быть уверенным, что состояние объекта останется неизменным после того, как он будет передан в функцию. Чисто прикладное применение, не более того.
Если же всё спроектировано правильно, то введением квалификатора const ты добьёшься того, что при попытке вызвать метод setPin для объекта, переданного в функцию, абстрактный сторонний Вася - получит по рукам от компилятора. Повторюсь: под "спроектировано правильно" имеется в виду полный набор, включая как архитектуру, так и настройки компилятора, и пр. средства.
Кстати про архитектурные косяки - в OneWire есть метод begin, который никто не помешает позвать унутре функции (если const не применять). Как раз случай, когда надо чуть-чуть постараться, и сделать так, чтобы были нормальные прототипы методов, с const, где это необходимо.
Он не компилятор обвинял, а IDE, по умолчанию скрывающую warning-и
P.S. Мне не нравится его апломб и манеры общения, но если он прав, я это признаЮ.
А вот это - хер собачий? Цитата: "Возьми нормальный компилятор (не arduino)". Где там что-то про IDE? Вижу там - про ненормальный компилятор, который используется - GCC. Собственно, Q.E.D.
Вот лог компиляции среды "из коробки". Где указан этот параметр? Покажите.
Можете пояснить каким именно образом использование "-fpermissive", даже если бы он и использовался, делает бесполезным квалификатор const?
6-я строка первого листинга :-) и далее по тексту, там много
Этот permissive отменяет модификатор const у обьекта, переданного по ссылке, если внутри функции используются методы этого обьекта без спецификатора const. Независимо от того, изменяются ли на самом деле поля обьекта.
6-я строка первого листинга :-) и далее по тексту, там много
Ой, и правда, а чё эт я поиском-то не нашел? Старею :-(
Этот permissive отменяет модификатор const у обьекта, переданного по ссылке, если внутри функции используются методы этого обьекта без спецификатора const. Независимо от того, изменяются ли на самом деле поля обьекта.
А вот хренушки! Это-то я как раз знаю, что он делает. Он, на самом деле
Т.е. ничего он не отменяет, просто в некоторых местах заменяет error на warning.
А const как был const'ом, так и остаётся.
#19. Не остается.
Нада напица. Всем пока.
Т.е. ничего он не отменяет, просто в некоторых местах заменяет error на warning.
Всё для удобства пользования. Ещё и warning все по умолчанию скрыты ;) Норм, чо.
#19. Не остается.
Деда, остаётся. В коде. Но при -fpermissive - игнорируется, давая возможность коду - скомпилироваться. Как по мне - жуткий костыль.
Вот смотри (мы же сейчас за чистоту рядов, т.е. кода говорим, да?) - в твоём примере ты передаёшь объект класса String по ссылке, с квалификатором const. Внутри функции - изменяешь состояние объекта, хотя тебе явно сказали - так делать нельзя. Но оно - скомпилировалось, потому что -fpermissive. Хорошо хоть, что warning дала, но и это - по умолчанию скрыто.
Искренне считаю, что отсутствие квалификаторов const там, где оно должно быть просто по определению - источник трудновыловимых ошибок в дальнейшем, даже при условии разработки в одно лицо (память - она неидеальна). Поэтому лучше свои классы проектировать так, чтобы оно компилировалось без warning, будучи переданы по ссылке с квалификатором const. И тогда будет уверенность, что и до, и после вызова функции - состояние объекта останется неизменным, если так хочется вызывающей стороне. А это, как показывал на примере выше - иногда ооочень полезно, уверенность - лишней не бывает.
Так что не в -fpermissive дело, по гамбургскому счёту ;)
З.Ы. Я сам при проектировании - не идеален, иногда всплывают жуткие недоработки, в процессе жизни какого-нибудь проекта. Но const по ссылке, если объект должен остаться неизменным - у меня уже на автомате пишется. Как я и говорил (безграмотно, конечно, говорил) - своего рода самодокументирование кода.
#19. Не остается.
Остаётся. Просто говорит, что игнорирует в том плане, что "если не смогу, то плюну", но все сопутствующем оптимизации пока может - выполняет.
Всё для удобства пользования. Ещё и warning все по умолчанию скрыты ;) Норм, чо.
Это да. За скрытые предупреждения (чтобы блондинкам голову не нагружало) иногда хочется руки поотрывать.
Дополню наглядным примером (не будем про -fpermissive и архитектуру конкретного класса). Есть прототип функции:
Глядючи на неё, я уже по умолчанию жду, что первые два параметра - останутся в неизменном состоянии после вызова функции, а в третий - будет помещён результат. И это - правильное объявление, т.к. с параметром pattern, например, захочется работать и дальше (например, применяем его в цикле к разным input, вызывая функцию parse).
Итог: код уже частично документировал сам себя, уже на этапе определения - от кода ждётся определённое поведение. И если какой-то ... включил -fpermissive, а конкретный Вася - решил этим воспользоваться и поменять, например, параметр pattern внутри parse - то по рукам получит именно Вася, т.к. после его изменений, во-первых, появится warning, и, во-вторых - не пройдёт юнит-тест (если они используются, конечно).
Всё для удобства пользования. Ещё и warning все по умолчанию скрыты ;) Норм, чо.
Это да. За скрытые предупреждения (чтобы блондинкам голову не нагружало) иногда хочется руки поотрывать.
Маркетинг, эффективные - реалии жизни. Если бы не прятали, и убрали -fpermissive - то не было бы сообщества Arduino, всё рухнуло бы в один миг, ибо - "оно же сложно, аааа, красная строчка, ааа, не компилируется!".
Не очень опытный пользователь спросил "Как передать объект в тело функции".
Решение было найдено быстро, и весь сыр бор разгорелся из-за
Дополню: правила хорошего тона требуют квалификатор const, когда переданный объект внутри функции - не изменяется:
Я тоже не очень опытный пользователь. Оценить с одного взгляда меняется объект или не меняется не могу. Лезть в библиотеку и смотреть как объявлены методы и что они делают??? Наверное это "правило хорошего тона" не для новичков.
Не очень опытный пользователь спросил "Как передать объект в тело функции".
Решение было найдено быстро, и весь сыр бор разгорелся из-за
Дополню: правила хорошего тона требуют квалификатор const, когда переданный объект внутри функции - не изменяется:
Просто форум - не справочная и каждый из нас не истина в последней инстанции.
Нашёлся спорный момент и те, кому это действительно интересно, пытаются докопаться до сути вещей. Нормальная