C ++ или С

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

  1. AlexU

    AlexU Гуру

    В статье пишут:
    2 байта на каждую вирт.функцию + 2 байта на деструктор (даже если он не виртуальный) + 2 байта на "не помню что". Хотя признаю с 2 кило погорячился -- при 15 классах с 5-ю - 10-ю вирт.функциями получается около 350 байт. Эти 350 байт не экономного разбазаривания оперативки.
    Смиритесь... Без RTTI это не решаемо...
     
  2. railmisaka

    railmisaka Нерд

    UPD, про механизм не прав, про вызовы все верно
    Я больше не буду вас переубеждать, но вы просто остановитесь на минутку и попытайтесь ответить на вопрос - зачем вообще нужны виртуальные функции? зачем вообще наследоваться?
    А на счет того, что без RTTI это не решаемо - легко, просто храним таблицы для объектов, а не для классов. UPD храним указатель на таблицу


    не.. если бы все было так, как вы говорите, то это были бы бесполезные траты.
     
    Последнее редактирование: 14 июл 2017
  3. Arkad_snz

    Arkad_snz Гик

    Нонче выпускники, получившие положительную оценку по Информатике в аттестате или в дипломе, и слыхом не слыхивали что такое регистр, а Фон Нейман в их представлении модный рэпер, или композитор рингтонов для мобил., а в компьютерах - все мнят себя наполеонами!
     
  4. AlexU

    AlexU Гуру

    Компиляторы создают таблицы для классов, а не для объектов.
    А что касается примера, то я допустил ошибку. Функция будет вызвана правильная, т.к. адрес таблицы вирт.функций будет вычислен из указателя на объект. Это я перепутал с вызовом виртуальной функции из конструктора -- там вызывалась функция из предка, если вызов был в конструкторе предка, вместо вызова нужной переопределённой...
     
  5. AlexU

    AlexU Гуру

    Правда есть вопрос, что за функция вызовется в следующем случае:
    Код (C++):
    void myFunc(A arg)
    {
      arg.f();
    }
    если в качестве аргумента передать объект класса В?
     
  6. railmisaka

    railmisaka Нерд

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

    каким это образом? ведь у нас рантайм информации о типах?

    это я как раз писал выше, но вы ошибаетесь когда используете слово "нужный". невозможно вызвать дочернюю функцию, потому что дочернего класса еще не существует.
     
  7. railmisaka

    railmisaka Нерд

    Это принципиально другой случай т.к. функция будет иметь не указатель, а сам объект.
    Наследование работает таким образом, что по ссылке и указателю на родительский класс может в действительности находиться дочерний. В данном случае будет вызван метод класса A.
    Но поменять поведение очень легко
    Код (C++):
    void myFunc(A &arg)
     
  8. AlexU

    AlexU Гуру

    В памяти, выделенной конкретному экземпляру объекта, есть специальных два байта, которые указывают на адрес таблицы вирт.функций. А указатель на объект как раз и указывает на эту память, где среди прочих данных объекта можно найти эти два байта -- указатель на таблицу. Тут всё просто. Но это единственное, что можно узнать о классе объекта. Полноценным RTTI это не назовёшь.
    Вообще перед вызовом конструктора объекту выделяется необходимая память и можно считать, что объект уже создан. Конструктор сам по себе ни каких объектов не создаёт -- конструктор можно рассматривать как хук (обработчик события создания объекта), который используется для инициализации данных объекта.
    Да и при вызове функции будет создана копия объекта, переданного в качестве аргумента, и вот мне пока не понятно, на основе какого класса будет создана копия и чьи конструкторы копирования (если они есть) будут вызваны.
    Да, только есть одно "но", в моём примере объект защищён от вмешательства в него функции (т.к. в функцию будет передана копия объекта), а в Вашем нет (т.к. будет передан сам объект). Поэтому результат работы функции может быть разным.
     
  9. mcureenab

    mcureenab Гуру

    Для защиты есть модификатор const.
    А передача по значению порождает новый объект, который, к стати может быть мостом к третьему общему объекту.
     
  10. railmisaka

    railmisaka Нерд

    За это точно не скажу. В этом вопросе я мог быть не прав.
    В целом такой подход лучше по памяти, чем хранить таблицу в объекте. А в процессе конструирования можно менять этот адрес. А лучше вообще "зашить" его в код(конструктора и деструктора). Тогда этот адрес можно считать неизменным и оптимизация, о которой вы говорили, возможна.

    Нет, т.к. поля дочернего объекта не инициализованы.

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

    Неправда. В общем случае он защищен только если реализовано глубокое копирование.
    А вот тут защищен
    Код (C++):
    void myFunc(const A &arg)
    Ваш код порождает копирование, что долго, жрет память, может привести к изменению исходного объекта. Как раз для этого и есть константные ссылки.
     
  11. mcureenab

    mcureenab Гуру

    Вот уж расписали))) если нужна локальная копия объекта, то передавать его аргументом по значению - самое то.
     
  12. mcureenab

    mcureenab Гуру

    А что не нормально?
    Да, теряется полиморфизм. Но может быть оно так и надо.
    Затрудняюсь представить для чего может понадобится применительно к классам с потомками.
     
  13. railmisaka

    railmisaka Нерд

    Я бы сказал, что все сильно зависит от ситуации.
    Но мне никогда не приходило в голову приводить объект к типа базового класса.

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

    ИгорьК Победитель модулей

    Ну хоть бы маленький пример реального проекта на ардуино...
     
  15. railmisaka

    railmisaka Нерд

    ненормально, потому что много деталей.

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

    глубокое копирование (предназначен ли класс для копирования?)

    думаю, еще можно придумать
     
  16. mcureenab

    mcureenab Гуру

    Короче, это для простых объектов, которые реализуют типы, не поддерживают наследование.
     
  17. railmisaka

    railmisaka Нерд

    если вы имеет ввиду передачу по значению, то обычно именно так и рекомендуют.