Как создать экземпляр класса на ардуиновых сях?

Тема в разделе "Arduino & Shields", создана пользователем Mabanza, 1 июл 2016.

  1. Mabanza

    Mabanza Нуб

    Привет.
    У меня есть класс:

    Код (C++):
    class TimeLine
    {
      public:
        bool IsExecuted;
        DateTime Timestamp;
        int Command;
        int Argument;
    };
    Правильно ли создавать его экземпляр следующим образом:

    Код (C++):
    TimeLine item;
    item = new TimeLine();
    Во всяком случае, транслятор не ругается. И уже почти 20 лет я это делаю на C#. Однако его использование в дальнейшем, например так

    Код (C++):
    timeLines.push(item);
    вызывает следующее сообщение об ошибке:
    no match for 'operator=' (operand types are 'TimeLine' and 'TimeLine*')

    timeLines - ну это некая реализация Queue, не думаю, что в ней проблема.

    Как это фикснуть?
    Спасибо.
     
  2. DIYMan

    DIYMan Guest

    Если на стеке, то:
    Код (C++):
    TimeLine item;
    Если на куче, то:
    Код (C++):
    TimeLine* item = new TimeLine();
     
  3. Mabanza

    Mabanza Нуб

    Не работает.
    Код
    Код (C++):
     TimeLine* item = new TimeLine();
          timeLines.push(item);
    выдает ошибку

    no matching function for call to 'QueueList<TimeLine>::push(TimeLine*&)'

    Библиотека для работы с очередями взята отсюда

    http://playground.arduino.cc/Code/QueueList

    Что это за амперсанд оно требует?
     
  4. Mabanza

    Mabanza Нуб

    Да, и еще.
    Метод push в этой библиотеке объявлен так:

    Код (C++):
    // push an item to the queue.
        void push (const T i);
     
    Почему там константа? Константы хранятся в стеке. Может ли экземпляр класса быть константой?
    Если да, то как создать новый экземпляр в куче и объявить его константой?

    В общем, мне нужен лист экземпляров класса (не обязательно очередь). Лист, к которому можно добавлять новые экземпляры, созданные в куче. Ну и соответственно, удалять из листа. Есть ли какая-нибудь бесплатная реализация?
    Спасибо.
     
  5. geher

    geher Гуру

    Начну с "константы".
    const в данном контексте означает, что параметр не может быть изменен в пределах функции.

    По поводу ошибки
    Код (C++):
    no matching function for call to 'QueueList<TimeLine>::push(TimeLine*&)
    Ругается, что нет реализации функции, в которую передается указатель на TimeLine.
    Терзают смутные сомнения, что в функцию push надо передавать не указатель, а переменную типа TimeLine.
    Т.е надо примерно так:
    Код (C++):
    TimeLine item();
    timeLines.push(item);
    Указатель на класс передать вменяемым образом в объявленную подобным образом функцию push не получится.
     
    Mabanza нравится это.
  6. Mabanza

    Mabanza Нуб

    Хорошо.
    Если я задам как вы пишете, значит ли это, что в стеке будет зарезевировано слово под адрес на место в куче, где хранится сам экземпляр?
    (со стеком облом, как в Z80. Ничтожный размер).
    Я создаю 15-20 экземпляров. Это значит из стека будет забрано в 15-20 слов при таком объявлении?
    В принципе, ничего. Если я выйду из процедуры, весь ее стек со своими локальными перенными будет рециклирован и адреса остануться только в экземпляре timeLines. Если это так, то ничего. Пожалуйста поправьте, если не так.
     
  7. Mabanza

    Mabanza Нуб

    Ну,хорошо.
    Объявил класс как
    Код (C++):
    class TimeLine
    {
      public:
        TimeLine();
        bool IsExecuted;
        DateTime Timestamp;
        int Command;
        int Argument;
    };
    Вызов

    Код (C++):
    TimeLine item();
    timeLines.push(item);
    транслируется с ошибкой

    no matching function for call to 'QueueList<TimeLine> : : push(TimeLine (&)())'

    Что может быть не так?
     
  8. DIYMan

    DIYMan Guest

    Если там так объявлено - выкиньте в топку этот класс, там T передаётся по значению. Надо, чтобы было объявлено так:
    Код (C++):
    void push (const T& i)
    Подводных косяков с этой "библиотекой" будет - вагон и тележка, это я вам гарантирую.
     
  9. AlexU

    AlexU Гуру

    Шаблон QueueList и реализация его методов объявлены в одном файле (обычно заголовочном) или нет?
     
  10. AlexU

    AlexU Гуру

    А если по логике так нужно -- передавать по значению, что бы не менять исходный объект (потому и const применяется). Вы торопитесь с выводами.
     
  11. DIYMan

    DIYMan Guest

    По логике в таких случаях всё равно передают по ссылке и ставят модификатор const - компилятор по рукам настучит, если что.

    Так что это вы торопитесь с выводами ;). Передавать огромную структуру, например, по значению - это говнокод. Коего на playground.arduino.cc - тонны.

    Впрочем, никак не настаиваю, каждый ССЗБ. Просто, применяя шаблоны, надо уметь их правильно готовить. Просмотрев код "библиотеки" по ссылке, для себя сделал вывод - говно.

    З.Ы. И кстати сказать: передавая по значению, const можно выбросить в топку, т.к. всё равно на стеке создаётся копия объекта. И хоть обменяйтесь там внутри него - на исходный объект это никак не повлияет.

    З.З.Ы. Если что, то передача указателя - это не передача по значению. Також как передача по ссылке.
     
  12. AlexU

    AlexU Гуру

    Я не делал ни каких выводов, поэтому и торопиться не могу.
    Что касается const компилятор настучит только в пределах тела функции. А если предполагается, что в очереди должны храниться объекты, которые ни кем ни при каких условиях не должны меняться. В этом случае при передаче по ссылке ни какой const Вам не поможет, только передача по значению с копированием объектов и такой же возврат с копированием объектов "спасут отца русской демократии". Правда в условиях ограниченности памяти в AVR вполне вероятно, что нужно применять другие шаблоны проектирования.
    const указывает что копия объекта не может быть изменена. И по поводу const -- бытует мнение, что 'const' много не бывает, и его нужно применять везде, где только можно. Хотя я это мнение не разделяю полностью.
    Так что прежде, чем записывать код в категорию "говно", нужно понять для чего он создавался и в каких случаях должен использоваться и только потом делать выводы.
     
  13. DIYMan

    DIYMan Guest

    Вот и глянули бы код "библиотеки", и тогда бы поняли, что моё определение - безошибочно.

    Остальной ваш бред комментировать не буду, просто вывешу эту смешную простыню потомкам:
    Оставлю себе на память, чтобы веселиться при случае.

    З.Ы. Надеюсь, вы не хуже меня знаете, сколько говна собрано в поставке стандартных библиотек Arduino IDE - косяк на косяке, кучу warning и т.п. Зачем ещё множить фекал, скачивая его очередную порцию? Учиться надо на хорошем, а не на абы чём.
     
    Последнее редактирование модератором: 2 июл 2016
  14. geher

    geher Гуру

    Попробовал сам. Наблюдается интересный эффект.
    Если так:
    Код (C++):
    TimeLine item();
    timeLines.push(item);
    действительно, компилируется с ошибкой.
    А если так:
    Код (C++):
    TimeLine item;
    timeLines.push(item);
    то без ошибки.
     
  15. AlexU

    AlexU Гуру

    Код (C++):
    TimeLine item();
    Это объявление функции, которая возвращает объект типа TimeLine. (Интересно кто Вам так посоветовал объявлять объект класса?)
    И ошибка:
    Код (Text):
    no matching function for call to 'QueueList<TimeLine> : : push(TimeLine (&)())'
    сообщает о том, что нет реализации функции QueueList<TimeLine>:: push, которая в качестве параметра принимает указатель на функцию, т.к. такой функции действительно нет.
     
  16. geher

    geher Гуру

    Простая логика.
    Есть конструктор
    Код (C++):
    TimeLine()
    .
    Если бы конструктор имел параметры, то объявление экземпляра класса было бы таким
    Код (C++):
    TimeLine item(параметры);
    А для объявления функции логичнее такая конструкция:
    Код (C++):
    TimeLine item(void);
    И еще помнится, с каким-то компилятором С++ (уже не помню, каким) объявлял экземпляр класса с конструктором без параметров именно так:
    Код (C++):
    TimeLine item();
    , и он "не обижался".

    А на самом деле конструктор класса без параметров крайне редко приходится применять. Уже и не помню, когда последний раз так делал.
     
  17. AlexU

    AlexU Гуру

    Если не ошибаюсь для 'С' так делать обязательно, а для 'C++' нет. Поэтому возникает неоднозначность, которую разработчики компилятора решили в пользу объявления функции.

    Тогда уж и экземпляры класса логичней создавать следующим образом:
    Код (C++):
    TimeLine item = TimeLine();
    -- экземпляр 'item' является результатом работы конструктора 'TimeLine()'. Что собственно и является одним из способов объявления экземпляров класса, а запись вида:
    Код (C++):
    TimeLine item;
    // или
    TimeLine item(параметры);
    это его сокращенные формы.