А это смотря что делать. Может, мне полиморфизм нужен будет (а, собственно, привязку к разным дисплеям так очень удобно делать). А тут уже vtable появляется.
Размер результирующего файла не изменился, но теперь подключая этот модуль к другим я могу обратиться к u8g и rtc. Идеологически это правильно я так понимаю? Завтра проверю в железе. Спасибо за помощь.
ключевое слово extern, для чего оно нужно и как применяется. Ну правда, это же основы, их надо знать обязательно.
Да не требуется там extern перестает компилироваться тогда. По ощущениям эти классы уже объявлены как extern сами по себе...
Вот именно что основы я понимаю, знаю и понимаю ООП. Но основная среда разработки у меня другая. Все мои примеры основаны на опыте работы с Delphi, а там мои примеры которые выше, но адаптированные под С++, считаются логичными и не вызывают никаких проблем и накладных расходов... Для меня вся проблема только в неожиданных"сюрпризах", "хитрых" директивах и структуре проекта...
Да не требуется там extern перестает компилироваться тогда. По ощущениям эти классы уже объявлены как extern сами по себе...
extern там можно. Работать будет. Можно даже extern функций делать. Вы просто ещё не освоились с концепцией заголовок-реализация. Поэтому ставите extern не туда и подключаете не то (и создали, наверняка, объект в заголовочном файле). Но это плохой стиль. Приводит он к тому, что у вас состояние модуля (речь не о вашем классе дисплея - тут это действительно пофигу, он у вас один, но вот в будущем не привыкайте к такому стилю) меняется с разных точек. А если вы измените поведение? А если оно начнёт меняться непредсказуемо? Вот поэтому глобальные переменные вредны. Их стоит использовать разве что при ну очень жесткой экономии ресурсов.
Вот поэтому глобальные переменные вредны. Их стоит использовать разве что при ну очень жесткой экономии ресурсов.
Тут не просто переменные, а объект неизвестного размера. Где же его ещё создавать, не в стеке или куче же. Да ещё чтобы доступен из других единиц трансляции был.
A!!! Все ясно. Нет ничего лучше, как своевременный пример по делу. Все сразу стало на свои места. С правильным подходом удалось сэкономить еще и сотню байт. Спасибо.
Тут не просто переменные, а объект неизвестного размера. Где же его ещё создавать, не в стеке или куче же. Да ещё чтобы доступен из других единиц трансляции был.
Так я несколько не об этом. Я имел в виду, что эту переменную нужно запирать в модуле, чтобы её не было видно глобально во всей программе.
Так я несколько не об этом. Я имел в виду, что эту переменную нужно запирать в модуле, чтобы её не было видно глобально во всей программе.
Зачем? Это глобальный ОБЪЕКТ - экран. Работа с ним осуществляется через его методы. Что там ещё прятать? Всё и так внутри объекта. То что автор решил его тягать как обычную переменную по функциям... Ну это он ССЗБ.
В arduino ide компилятор gcc, который С++ только в путь. Сам по себе C++ не даёт накладных расходов, если с головой подходить, а не так как matrex.
Не просто в путь. Весь Arduino Core (те самые библиотеки, на которых все строится в ардуино) основан на плюсах с ооп. Тот же Serial - объект. И многие другие вещи классами описаны.
А кстати, в плюсах если объект передавать как указатель в аргументах функции, накладных расходов же будет?
В этом случае передаётся не "объект как указатель", а указатель. Накладные будут при доступе по этому указателю. Насколько большие зависит от архитектуры. При развитых типах адресации может и не быть накладных.
Ну раз пошел у нас такой задушевный диалог, разрешите еще вопрос. Как правильно инициализировать структуру (по сути массив) нулями. В идеале одной командой сразу всю.
Код:
// данные с датчиков struct rSENSORS { float aPRESSURE[SENSOR_COUNT_DATA]; // Давление float aTMP_IN[SENSOR_COUNT_DATA]; // Температура внутри помещения float aTMP_OUT[SENSOR_COUNT_DATA]; // Температура на улице uint8_t aHOUR[SENSOR_COUNT_DATA]; // Час снятия показания uint8_t aMINUTE[SENSOR_COUNT_DATA]; // Минута снятия показания };
Делаю "в лоб" (работает, но не изящно, знаю что можно лучше):
В итоге - никак не инициализирую массив (все работает, экономит десяток байт) - вроде как из спецификации CPP там должны находиться нули по умолчанию, но меня терзают сомнения, а предыдущий опыт говорит о том, что переменные лучше инициализировать явно во избежании лишних проблем.
typedef struct { float aPRESSURE[SENSOR_COUNT_DATA]; // Давление float aTMP_IN[SENSOR_COUNT_DATA]; // Температура внутри помещения float aTMP_OUT[SENSOR_COUNT_DATA]; // Температура на улице uint8_t aHOUR[SENSOR_COUNT_DATA]; // Час снятия показания uint8_t aMINUTE[SENSOR_COUNT_DATA]; // Минута снятия показания } rSENSORS;
rSENSORS dt;
memset(&dt, 0, sizeof(rSENSORS));
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
На ARM нужно 10 раз подумать прежде чем так делать, чтобы исключить невыровненный доступ там где его нет и в HardFault не улететь. Можно, но с головой!
А зачем вы создали структуру из массивов? У вас же размерность одинаковая. Сделайте массив структур.
Код:
struct rSENSORS { float aPRESSURE; // Давление float aTMP_IN; // Температура внутри помещения float aTMP_OUT; // Температура на улице uint8_t aHOUR; // Час снятия показания uint8_t aMINUTE; // Минута снятия показания } dt[SENSOR_COUNT_DATA];
Если уже отличное от нулей, то тогда можно делать так:
На ARM нужно 10 раз подумать прежде чем так делать, чтобы исключить невыровненный доступ там где его нет и в HardFault не улететь.
было бы конструктивно объяснить, как следует поступать, чтобы не нарваться. причем без привзяки к ARM, а вообще по правильному для С++, раз уж тема об этом языке.
NStorm писал(а):
Или сделать уже memset(dt, 0, sizeof dt);
это чем-то отличается от предложенного мной?
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения