Чой-то вдруг... На что они могут заменяться, если адреса функций известны на этапе компиляции и в дальнейшем функции не перемещаются.
Я это написал не потому, что не в курсе о какой платформе речь, а потому, что я не привык экономить виртуальные функции. Думаю, в маленьких количествах они не зло. МК это же вообще про компромиссы. Да все программирование про это. Хочешь быстро разрабатывать/быстро исполнять/мало памяти итп - пишем программы по разному. Не совсем вас понял. Особенно, зачем паяльник. Если вы противопоставляете мою точку зрения своей, тогда я не понимаю также, зачем программисту С++ знать о регистрах. Конечно, вы можете считать, что начинать программировать под МК надо именно с С++, читая Страуструпа и Шилда. Я лишь изложил свою точку зрения. И я не против того, чтобы писать на смеси С++ и С. Но только если вы при этом в состоянии писать на самом С++.
В конструкторе родительского класса они указывают на родительские объекты. И в деструкторе. Хотя точно про реализацию сказать не могу. UPD видимо, меняются не таблицы
В принципе, наверное можно иметь образ таблицы виртуальных функций для каждого этапа конструирования объекта.
Таблицы виртуальных функций создаются на этапе компиляции и в дальнейшем не изменяются. Одна таблица на один класс, а сколько объектов будет создано на основе того или иного класса к таблице ни какого отношения не имеет.
На днях (ну, я же новичок) я читал об где-то в сети. и там было написано, что эта проблема не решена, потому что те, кто могут это исправить не особо в этом заинтересованы. Исправить почти всегда и почти все можно. вопрос только в том, кто будет это делать. И если я ничего не путаю, там же говорилось, что есть то ли альтернативные компиляторы, то ли способы это это обойти как то еще.
Положим, у вас есть Код (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 уже разрушен. Это про механизм.
И будет вызвана функция определённая в классе A. Именно поэтому не рекомендуется вызывать виртуальные функции в конструкторах (это касается С++, в Java и C# всё будет нормально). Даже более того скажу, что в методе: Код (C++): void myFunc(A * arg) { arg->f(); } если в в качестве аргумента передадите указатель на объект типа В, будет вызвана функция 'f()' декларированная в классе A, не смотря на то что функция виртуальная и по идее должна быть вызвана функция из класса В. Потому что компилятор при компиляции скажет, что нужно использовать таблицу виртуальных функций для класса А, т.к. этот класс определяет тип аргумента. UPD: прошу прощения допустил ошибку
Смотря какой МК. Если памяти буквально несколько Кб, тогда конечно, все языковые выкрутасы идут нафиг, все максимально просто, в пределе отказ от плюсов и включение асм вставок где удается что-то сделать лучше компилятора. А если МК повышенной жирности, тогда можно и все плюшки использовать да еще и под RTOS какой-нибудь.
опачки.. а это с чего бы вдруг? указатель на класс B будет приведен к указателю на класс A БЕЗ изменения самого класса. Поэтому у объекта arg таблица виртуальных функция объекта класса B
вот только мне кажется что "жирность" надо не объемом памяти мерять, а соотносимостью с задачей. Если задача очень большая то даже на МК с большим количеством памяти могут быть проблемы.
А с того, что бы знать какую функцию вызывать, нужна RTTI. А в компиляторе avr-g++ этого нет. И поэтому адрес функции (или таблицы функций, а из неё уже адрес функции) определяется на этапе компиляции. А на этапе компиляции компилятор видит только объект класса А и ни чего не знает о том, что в качестве аргумента может быть передан объект класса, являющегося наследником класса А. Вот и вся арифметика...
Вы не правы хотя бы потому, что я делал это на ардуино. Кроме того, если бы все было так как вы говорите, то виртуальные функции были бы неюзабельны вообще. И получается, что C++ вообще не поддерживается, так как убита одна из ключевых особенностей. А про rtti, это значит, что у вас не выйдет dynamic_cast'ом определить тип. И таблица виртуальных функций хранится в объекте, а не в классе. UPD остальное верно
Я не могу говорить за все реализации компиляторов, а говорю за одну из самых распространённых для AVR -- avr-g++. "это значит, что у вас не выйдет dynamic_cast'ом определить тип" -- да, не выйдет, т.к. эту информацию компилятор просто не включает в прошивку. Таблица виртуальных функций одна на класс -- не верите, декомпилируйте прошивку и смотрите внимательно. На каком Arduino? Они есть не только на основе AVR. Виртуальные функции поддерживаются - но кривоватненько, очень даже кривоватненько. Именно поэтому в своём первом сообщении в этой теме и изложил мысль, что в контексте AVR использование языка C++ не множко не уместно.
Конечно, объем памяти это далеко не единственный параметр, и "жирность" - понятие относительное. Скажем так, если располагаемые ресурсы достаточно превышают потребные, то можно не особо себя ограничивать при написании прошивки.
Вы утверждаете, что не поддерживается, что по указателю на родительский объект вызовется метод родительского класса. Это не так. Это просто не может быть так. Это просто глупо. Arduino Uno. По указателю на родительский класс вызывается дочерний метод. Если бы таблица виртуальных функций была только одна, то никто бы не жаловался на память т.к. она одна для класса. Если у вас просто мало функций то получается маленький оверхэд. А проблема как раз в другом. Доп память на каждый объект. В упомянутой выше статье амперки на хабре как раз пишут об этом. UPD, понял, жалуются на таблицу в памяти и 2байта на объект..
С этим согласен. Именно так и поступаю. Больше того, я именно за такой подход. А то что я говорил относится больше к тем, кто собирается учиться. Если вы пишете на плюсах, вам мои советы не нужны.