|
Заблокирован
|
||||||
Неочевидные грабли полиморфизма с++23.11.2011, 01:05. Показов 16456. Ответов 101
Метки нет (Все метки)
Наткнулся в интернете на любопытный код.
Спешу поделиться с сообществом. Просто, что бы кто если не в курсе - узнал, и не попал на эти грабли:
Но в любом случае, нужно быть предельно осторожным. А по сути, полиморфизм + множественное наследование = мина замедленного действия. Поэтому, при проектировании полиморфных классов, лучше до последнего избегать множественного наследования.
1
|
||||||
| 23.11.2011, 01:05 | |
|
Ответы с готовыми решениями:
101
Грабли с кодировкой |
|
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
|
||
| 23.11.2011, 10:49 | ||
|
Все указатели на уровне реализации - абсолютно одинаковы. Поэтому явное преобразование типа указателя - это просто для порядку на уровне С++. На самом деле никаких преобразований не производится. Как и было в С. А вот при наличии в классе виртуальных функциях нужно знать тип ВО ВРЕМЯ ВЫПОЛНЕНИЯ. Чтобы вызвать нужную функцию. Это довольно сложная операция. Это и есть механизм RTTI.
0
|
||
|
Делаю внезапно и красиво
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
|
||
| 23.11.2011, 10:50 | ||
Сообщение было отмечено как решение
РешениеИтак MSVC: В начале каждого объекта, содержащего виртуальные функции, записывается адрес используемой им таблицы виртуальных функций. Адрес объекта совпадает с указателем на эту таблицу. Виртуальные функции добавляются в эту таблицу в том же порядке, в котором они объявлены в классе. Вызов происходит не напрямую по адресу, а через индекс этой функции. Т.е. вместо непосредственного использования адреса функции, происходит индексированный доступ к таблице и вызов функции по соответствующему адресу. При множественном наследовании всё усложняется. Для первого базового класса указатель по прежнему записан в самом начале, затем идут данные-члены этого класса и только потом указатель на таблицу второго базового класса. Когда ты выполняешь приведение типа с помощью dynamic_cast, адрес объекта изменяется, т.к. он переносится на "начало" объекта второго базового класса. Ты можешь это легко проверить, выводя адрес объекта после кастования. Используя reinterpret_cast (круглые скобки это он и есть в данном случае), ты интерпретируешь указатель на один объект, как указатель на другой. Программа бы могла упасть, но прототипы функций одинаковые, поэтому порчи стека не происходит. Данные объекта тоже не используются. Но происходит индексированый доступ функции. Что ты и видишь в консоли. Можешь добавить в классы поля и попробывать их выводить в консоль (но не изменять) и зразу увидишь, что там не то, что ты ожидаешь. И это не грабли полиморфизма, это некорректная программа. Не зря ведь говорят ЗАБУДЬТЕ ПРО ПРИВЕДЕНИЕ ТИПОВ В СТИЛЕ Си.
4
|
||
|
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
|
||
| 23.11.2011, 10:50 | ||
|
Потому и не приводит. Обратная же совместимость!
0
|
||
|
Заблокирован
|
||||||
| 23.11.2011, 10:51 [ТС] | ||||||
|
Спустимся:
Корректно. Вы по прежнему щитаете, что между ними нет связи?
0
|
||||||
|
Делаю внезапно и красиво
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
|
||
| 23.11.2011, 10:53 | ||
|
1
|
||
|
|
|
| 23.11.2011, 10:54 | |
|
В общем-то насколько мне известно, множественный полиморфизм может быть реализован с использованием нескольких таблиц виртуальных методов (в данном случае двух). Собственно, как выше и говорилось, для этого и нужен dynamic_cast. Если использовать преобразование в стиле Си, то указатель vtable получается фактически случайным из двух.
0
|
|
|
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
|
||
| 23.11.2011, 10:55 | ||
|
Откуда компилятор мог знать, что Берс возьмет эти два класса и множественно унаследует. А потом явные имена при вызове будет писать и требовать "продолжения банкета" с виртуальными функциями.
0
|
||
|
Делаю внезапно и красиво
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
|
||
| 23.11.2011, 10:55 | ||
|
Но! Если А* и В* на самом деле указывают на объект типа С, то связь есть. Но только в случае использования dynamic_cast. При желании, можно вручную рассчитать необходимое смещение, сдвинуть указатель и поменять его тип. Но такому желанию лучше не возникать.)
0
|
||
|
Заблокирован
|
|
| 23.11.2011, 11:02 [ТС] | |
|
ну так вот, возвращаясь к моему тезису:
1. Избегайте множественного наследования + полиморфизм. 2. Избегайте динамического кастования, если дорога производительность. В противном случае не удивляйтесь ничайному выстрелу себе в ногу.
0
|
|
|
Делаю внезапно и красиво
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
|
||
| 23.11.2011, 11:10 | ||
|
2 - Это миф. 3 - Учитесь программировать и не придётся искать достаточно длинную верёвку, чтобы выстрелить себе в ногу.
2
|
||
|
Заблокирован
|
|
| 23.11.2011, 11:11 [ТС] | |
|
сказал Deviaphan, ничерта не пролив свет на происходящее
0
|
|
|
Делаю внезапно и красиво
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
|
||
| 23.11.2011, 11:18 | ||
|
Добавлено через 32 секунды От тута Неочевидные грабли полиморфизма с++
0
|
||
|
В астрале
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
|
|
| 23.11.2011, 11:41 | |
|
Deviaphan, На счет динамик каста я бы поспорил. Много динамик кастов убивают производительность. В одной проге профайлер показывает, что динамик каст занимает 14% общего времени, правда используется он там действительно немало где
0
|
|
|
Делаю внезапно и красиво
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
|
|||||||
| 23.11.2011, 11:51 | |||||||
|
И маленький примерчик, для "закрепления материала" ![]()
Можно закомментировать слова virtual, чтобы совсем уж точно материал усвоить.)
2
|
|||||||
|
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
|
||
| 23.11.2011, 11:54 | ||
|
0
|
||
| 23.11.2011, 11:56 | |
|
Не по теме: Deviaphan, http://www.jezuk.co.uk/cgi-bin... howtobuild при желании можешь посмотреть сорцы. Мб это и ошибка в проектировании
0
|
|
|
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
|
|||||||
| 23.11.2011, 12:01 | |||||||
0
|
|||||||
| 23.11.2011, 12:04 | ||
|
Не по теме:
Копаться в исходниках XML парсера особого желания не возникает.:)
1
|
||
|
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
|
||||||||||||||||||||
| 23.11.2011, 12:46 | ||||||||||||||||||||
Добавлено через 7 минут Добавлено через 1 минуту Добавлено через 1 минуту Добавлено через 9 минут
1. Это указатель. 2. Ему разрешено указывать только на данные определённого типа, или только на на данные определённого класса - того типа/класса, который поминается в словосочетании. Чтоб не сбивать тебя с толку следовало бы говорить "указатель на данное типа", "указатель на объект класса", но ни кто так длинно не говорит, все сокращают и все понимают, что на саму абстракцию указатель не указывает. Добавлено через 3 минуты Добавлено через 3 минуты Добавлено через 2 минуты Добавлено через 6 минут
0
|
||||||||||||||||||||
|
Делаю внезапно и красиво
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
|
|||
| 23.11.2011, 12:51 | |||
|
Надо же было твой пост разбить на два.
1
|
|||
| 23.11.2011, 12:51 | |
|
Xmega грабли Грабли с USART_FLAG_RXNE Наступлю на те же грабли?
Грабли malloc/free Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F
Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU.
Опрашиваются регистры. . .
|
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка:
Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
|
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо
Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
|
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман.
Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
|
|
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
|
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
|
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ
Основная суть и тезисы по измерениям:
0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема.
Объект не может перемещаться в 0D.
1D (Первое измерение):. . .
|
[EasyBuilder Pro] Памятка по разработке для панелей Weintek
ФедосеевПавел 26.08.2026
Памятка по разработке для панелей Weintek
ВВЕДЕНИЕ
Ранее, при реализации проектов основное внимание уделял разработке управляющей программы для контроллера, а панели оператора доставалось время. . .
|