C ++ или С

Тема в разделе "Микроконтроллеры AVR", создана пользователем Romjke76, 2 авг 2016.

  1. mcureenab

    mcureenab Гуру

    По мере конструирования объекта указатели в таблице заменяются.
     
  2. AlexU

    AlexU Гуру

    Чой-то вдруг... На что они могут заменяться, если адреса функций известны на этапе компиляции и в дальнейшем функции не перемещаются.
     
  3. railmisaka

    railmisaka Нерд

    Я это написал не потому, что не в курсе о какой платформе речь, а потому, что я не привык экономить виртуальные функции. Думаю, в маленьких количествах они не зло.

    МК это же вообще про компромиссы. Да все программирование про это. Хочешь быстро разрабатывать/быстро исполнять/мало памяти итп - пишем программы по разному.

    Не совсем вас понял.
    Особенно, зачем паяльник.
    Если вы противопоставляете мою точку зрения своей, тогда я не понимаю также, зачем программисту С++ знать о регистрах.

    Конечно, вы можете считать, что начинать программировать под МК надо именно с С++, читая Страуструпа и Шилда. Я лишь изложил свою точку зрения.

    И я не против того, чтобы писать на смеси С++ и С. Но только если вы при этом в состоянии писать на самом С++.
     
  4. railmisaka

    railmisaka Нерд

    В конструкторе родительского класса они указывают на родительские объекты. И в деструкторе.
    Хотя точно про реализацию сказать не могу.
    UPD видимо, меняются не таблицы
     
    Последнее редактирование: 14 июл 2017
  5. mcureenab

    mcureenab Гуру

    В принципе, наверное можно иметь образ таблицы виртуальных функций для каждого этапа конструирования объекта.
     
  6. AlexU

    AlexU Гуру

    Таблицы виртуальных функций создаются на этапе компиляции и в дальнейшем не изменяются. Одна таблица на один класс, а сколько объектов будет создано на основе того или иного класса к таблице ни какого отношения не имеет.
     
  7. railmisaka

    railmisaka Нерд

    На днях (ну, я же новичок) я читал об где-то в сети. и там было написано, что эта проблема не решена, потому что те, кто могут это исправить не особо в этом заинтересованы. Исправить почти всегда и почти все можно. вопрос только в том, кто будет это делать.
    И если я ничего не путаю, там же говорилось, что есть то ли альтернативные компиляторы, то ли способы это это обойти как то еще.
     
  8. AlexU

    AlexU Гуру

  9. railmisaka

    railmisaka Нерд

    Положим, у вас есть
    Код (C++):
    class A {
      virtual void f();
    };
    и вы хотите
    Код (C++):
    class B: public A {
      void f() override;
    };
    Когда вы создаете класс B, то вы, само собой, должны вызвать его конструктор. Но перед конструктором B вызовется конструктор A. И, положим, конструктор A вызывает функцию f().
    Далее, конструктор A вообще не в курсе про класс B. Но это ничего. Хуже то, что класс B будет создан только после класса A. И конструктор класса A не может вызвать f из класса B, т.к. тот еще не создан.
    То же самое с деструктором. Деструктор A вызовет виртуальный метод A, т.к. B уже разрушен.

    Это про механизм.
     
    Последнее редактирование: 14 июл 2017
  10. Unixon

    Unixon Оракул

    Не несите чуши, это перепевка Java.
     
  11. AlexU

    AlexU Гуру

    И будет вызвана функция определённая в классе A. Именно поэтому не рекомендуется вызывать виртуальные функции в конструкторах (это касается С++, в Java и C# всё будет нормально).
    Даже более того скажу, что в методе:
    Код (C++):
    void myFunc(A * arg)
    {
      arg->f();
    }
    если в в качестве аргумента передадите указатель на объект типа В, будет вызвана функция 'f()' декларированная в классе A, не смотря на то что функция виртуальная и по идее должна быть вызвана функция из класса В. Потому что компилятор при компиляции скажет, что нужно использовать таблицу виртуальных функций для класса А, т.к. этот класс определяет тип аргумента.

    UPD: прошу прощения допустил ошибку
     
    Последнее редактирование: 13 июл 2017
  12. Unixon

    Unixon Оракул

    Смотря какой МК. Если памяти буквально несколько Кб, тогда конечно, все языковые выкрутасы идут нафиг, все максимально просто, в пределе отказ от плюсов и включение асм вставок где удается что-то сделать лучше компилятора. А если МК повышенной жирности, тогда можно и все плюшки использовать да еще и под RTOS какой-нибудь.
     
  13. railmisaka

    railmisaka Нерд

    опачки.. а это с чего бы вдруг?
    указатель на класс B будет приведен к указателю на класс A БЕЗ изменения самого класса.
    Поэтому у объекта arg таблица виртуальных функция объекта класса B
     
  14. railmisaka

    railmisaka Нерд

    вот только мне кажется что "жирность" надо не объемом памяти мерять, а соотносимостью с задачей. Если задача очень большая то даже на МК с большим количеством памяти могут быть проблемы.
     
  15. AlexU

    AlexU Гуру

    А с того, что бы знать какую функцию вызывать, нужна RTTI. А в компиляторе avr-g++ этого нет. И поэтому адрес функции (или таблицы функций, а из неё уже адрес функции) определяется на этапе компиляции. А на этапе компиляции компилятор видит только объект класса А и ни чего не знает о том, что в качестве аргумента может быть передан объект класса, являющегося наследником класса А. Вот и вся арифметика...
     
  16. railmisaka

    railmisaka Нерд

    Вы не правы хотя бы потому, что я делал это на ардуино. Кроме того, если бы все было так как вы говорите, то виртуальные функции были бы неюзабельны вообще. И получается, что C++ вообще не поддерживается, так как убита одна из ключевых особенностей.

    А про rtti, это значит, что у вас не выйдет dynamic_cast'ом определить тип.
    И таблица виртуальных функций хранится в объекте, а не в классе.

    UPD остальное верно
     
    Последнее редактирование: 14 июл 2017
  17. AlexU

    AlexU Гуру

    Я не могу говорить за все реализации компиляторов, а говорю за одну из самых распространённых для AVR -- avr-g++.
    "это значит, что у вас не выйдет dynamic_cast'ом определить тип" -- да, не выйдет, т.к. эту информацию компилятор просто не включает в прошивку.
    Таблица виртуальных функций одна на класс -- не верите, декомпилируйте прошивку и смотрите внимательно.
    На каком Arduino? Они есть не только на основе AVR.
    Виртуальные функции поддерживаются - но кривоватненько, очень даже кривоватненько.
    Именно поэтому в своём первом сообщении в этой теме и изложил мысль, что в контексте AVR использование языка C++ не множко не уместно.
     
  18. Unixon

    Unixon Оракул

    Конечно, объем памяти это далеко не единственный параметр, и "жирность" - понятие относительное. Скажем так, если располагаемые ресурсы достаточно превышают потребные, то можно не особо себя ограничивать при написании прошивки.
     
  19. railmisaka

    railmisaka Нерд

    Вы утверждаете, что не поддерживается, что по указателю на родительский объект вызовется метод родительского класса. Это не так. Это просто не может быть так. Это просто глупо.

    Arduino Uno. По указателю на родительский класс вызывается дочерний метод.

    Если бы таблица виртуальных функций была только одна, то никто бы не жаловался на память т.к. она одна для класса. Если у вас просто мало функций то получается маленький оверхэд.
    А проблема как раз в другом. Доп память на каждый объект.
    В упомянутой выше статье амперки на хабре как раз пишут об этом.

    UPD, понял, жалуются на таблицу в памяти и 2байта на объект..
     
    Последнее редактирование: 14 июл 2017
  20. railmisaka

    railmisaka Нерд

    С этим согласен. Именно так и поступаю.
    Больше того, я именно за такой подход.

    А то что я говорил относится больше к тем, кто собирается учиться. Если вы пишете на плюсах, вам мои советы не нужны.