|
Заблокирован
|
||||||
Неочевидные грабли полиморфизма с++23.11.2011, 01:05. Показов 17161. Ответов 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 / 1799 / 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 / 1799 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
|
|||||||
| 23.11.2011, 12:01 | |||||||
0
|
|||||||
| 23.11.2011, 12:04 | ||
|
Не по теме:
Копаться в исходниках XML парсера особого желания не возникает.:)
1
|
||
|
4226 / 1799 / 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 Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Книги по геймдизайну, игровым механикам и проектированию игрового опыта
8Observer8 08.11.2026
Содержание блога | English Version
1. 2003 - 06 - Designing Virtual Worlds (1st Edition)
Автор: Richard A. Bartle | Объем: 768 стр.
Ссылки: Amazon
. . .
|
Родители токсичные абьюзеры по отношению к своим детям ругают их оскорбляют не любят
zorxor 08.11.2026
Жить в атмосфере постоянных оскорблений, критики и холодности со стороны родителей — это тяжелое и болезненное испытание, которое оставляет глубокие эмоциональные раны. Токсичное и абьюзивное. . .
|
Как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Ответ от Джемени ИИ.
zorxor 08.11.2026
Джемени, как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы.
Многие люди, возвращаясь домой, сразу переодеваются в максимально свободную одежду или вовсе предпочитают. . .
|
Паттерн очереди действий/команд (Action / Command Queue). Система очереди действий и кат-сцен с SDL3 Callbacks, cglm и OpenGL
8Observer8 07.11.2026
Содержание блога | English Version
Руководство для начинающих по реализации паттерна очереди действий/ команд (Action / Command Queue) на C++ (C++20) с использованием официального SDL3 Callbacks. . .
|
|
Проверка полного ФИО в типовом справочнике
Maks 07.11.2026
Решение реализовано в конфигурации КА2, на примере справочника "КонтактныеЛицаПартнеров".
Задача:
Запрет инициалов.
Не допускаеть использование сокращений вида "И. И. ", "И. И. ", "И И" и. . .
|
Про "Windows must die!"
kumehtar 04.11.2026
Знаете, чет накатило. . . .
Когда-то это было почти боевым кличем: мол, нормальный человек сидит на DOS, OS/ 2 или Linux, а вот это вот - Must Die. А теперь человек произносит «мастдай» с усмешкой - и. . .
|
Красочные поля с номером страницы svg+background-image
russiannick 04.11.2026
Красочные поля с номером страницы не менее важны чем в эпоху бумажных книг.
Посему спешу представить почтеннейшей публике этот важный инструмент который эти поля и формирует.
В процессе разработки. . .
|
Вступаем в новую фазу генерации favicons, векторную.
russiannick 02.11.2026
Теперь нет нужды скрывать что используется простой svg. Исходный код изображения помещаем в поле и жмем кнопку. Исходник преобразуется в вид корректный для помещения в favicon или в url(). Нажатие. . .
|