| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > Как получить тип через указатель на базовый класс? |
| Автор: georain 20.12.2007, 01:43 |
| Подскажите, что то я запутался. Есть дерево полиморфных классов, есть указатель на базовый класс. Как я могу (и могу ли вообще) получить указатель на класс, на который указывает указатель на базовый класс. |
| Автор: Daevaorn 20.12.2007, 01:55 |
| "Указателей на класс" в С++ не существует. |
| Автор: georain 20.12.2007, 02:09 | ||
| Извините, неправильно (сокращённо) выразился. Указатель с типом производного класса?
Нужно получить d_ptrA, d_ptrB или d_ptrС каким-либо образом из b_ptr. |
| Автор: dizzy1984 20.12.2007, 07:25 | ||||
Если b_ptr указывает на DerivedA, то можно так
или с помощью c-cast
|
| Автор: georain 20.12.2007, 07:45 |
| Так это понятно А если мы заранее не знаем что он указывает на DerivedA? Мы может определить это через специальную виртуальную функцию. Но как это автоматизировать? Хочется что-то типа b_ptr = dynamic_cast <(b_ptr->get_my_type)>(b_ptr) только без RTTI, ну и чтоб работало) Я думаю что похоже придётся для каждого класса специализированный шаблон заводить... |
| Автор: dizzy1984 20.12.2007, 09:50 |
| А можно привести ситуацию в которой такое преобразование необходимо? |
| Автор: Alek86 20.12.2007, 11:01 |
| georain, а можно поинтересоваться, зачем это тебе нужно? по-моему, ты пренебрегаешь такой хорошей штукой, как полиморфизм скорее всего, твоя проблема решается с помощью виртуальных функций. |
| Автор: MAKCim 20.12.2007, 11:58 |
| Alek86, dizzy1984, я вот не понимаю, зачем задавать подобные вопросы это самый что ни на есть прямой уход от поставленной задачи что не есть хорошо человек определенно спросил, можно ли, дескать, сделать так-то и так-то а вы начинаете демогогию типа "а зачем тебе это нужно" не знаете - не отвечайте извините за резкость...накипело |
| Автор: baldina 20.12.2007, 12:00 | ||||||||||
без RTTI вообще никак (ну только если ты сам не хранишь поле типа). RTTI нужен для dynamic_cast.
полностью согласен.
сам то понял что сказал? у тебя уже есть b_ptr. А если ты хочешь и можешь использовать его полиморфно, приведение типа не нужно.
Это в smalltalk такой подход. Мы не знаем, чем на самом деле является класс и запрашиваем возможность использования его в качестве одного из подтипов. Если получается - используем. Для этого как раз может подойти dynamic_cast. Например, у тебя в массиве хранятся указатели на объекты типа Base, но реально имеющие производный тип. И ты хочешь над всеми, кто указывает на DerivedA, выполнить специфичную для DerivedA (не полиморфную) операцию. Будет так:
|
| Автор: MAKCim 20.12.2007, 12:07 | ||
я отлично понял, что имел в виду georain и объяснил, что в С++ такое невозможно |
| Автор: Alek86 20.12.2007, 12:24 | ||||
оффтоп
я "отвечал" не на первый вопрос темы (на него уже ответили) а на этот:
пытался, так сказать, как Христос, не накормить рыбой а научить ловить |
| Автор: baldina 20.12.2007, 12:31 | ||
MAKCim, это автору предназначалось. |
| Автор: MAKCim 20.12.2007, 12:40 |
я думаю, если другие поняли, то и автор должен понимать |
| Автор: georain 20.12.2007, 13:52 | ||
| Ладно, объясняю зачем мне это нужно. Всё опять же нужно для оптимизации по скорости. Возможно есть какой-то другой способ решения, если знаете подскажите пожалуйста. Есть довольно большое дерево полиморфных классов, в каждом классе есть тоже довольно много виртуальных функций. Специфика программы в том, что часто в одном месте (всмысле последовательно) из одного из классов вызывается много функций подряд в разных последовательностях. Так вот хочется уменьшить накладные расходы на вызовы виртуальных функций, и сократить их до одной, а потом вызывать остальные статически, ведь по идее с помощь виртуальной функции можно получить информацию о типе, а имея информацию о типе можно вызывать функции непосредственно (статически). Т.е. что-то типа
MAKCim, спасибо за понимание. Я пока писал понял что действительно в с++ так нельзя... если без шаблонов...)) baldina, с dynamic_cast пришлось бы делать перебор для всех классов, а он сам по себе очень не дешёвый - в итоге смысла нет. Конечно есть вариант в самих классах определять дополнительные виртуальные функции с необходимой последовательностью, но их там и так много, перебор получается, к тому-же это сильно увеличит размер виртуальных таблиц. |
| Автор: Alek86 20.12.2007, 14:01 |
| то есть, если я правильно понял, ты хочешь вызывать функции не виртуально (через таблицу виртуальных функций) а напрямую? вообще избавиться от виртуальности функций? |
| Автор: MAKCim 20.12.2007, 14:04 | ||
| georain, а если так сделать
|
| Автор: Alek86 20.12.2007, 14:08 | ||
| исправьте меня, если ошибусь, но, вроде, единственные издержки в вызове виртуальных функций - это то, что они вызываются через указатели, и ускорить их вызов можно, лишь сделав их невиртуальными... Добавлено через 29 секунд
|
| Автор: MAKCim 20.12.2007, 14:23 | ||
Alek86,
|
| Автор: Alek86 20.12.2007, 14:30 |
| тогда по вопросу осталась мелочь - побыстрее определить, что текущий указатель указывает именно на A, а не на B и вызвать определенную статическую функцию с кастанутым текущим указателем... может, typeof поможет |
| Автор: HappyLife 20.12.2007, 14:37 |
| Кхм.... интересно а насколько дорого стоит вызов виртуальной функции? |
| Автор: Lazin 20.12.2007, 14:37 |
| Не знаю насколько я попал в тему... избавиться от дополнительных виртуальных ф-й и вызывать правильные не виртуальные методы в производных классах позволяет шаблон проектирования Curiously recurring template |
| Автор: MAKCim 20.12.2007, 15:19 | ||||||
вместо
|
| Автор: Alek86 20.12.2007, 15:35 |
| ну, и еще ее нельзя инлайнить, в общем случае |
| Автор: Earnest 25.12.2007, 18:12 | ||
Строго говоря, вовсе необязательно CRT - любой шаблон обеспечивает статический полиморфизм. Только не всегда можно заменить динамический полиморфизм статическим - для этого нужно знать типы на этапе компиляции. Автору: большое дерево классов + много виртуальных функций - уже надо что-то в консерватории поправить. Если достаточно определить в одном месте тип, а потом можно вызвать конкретную функцию, так и сделай именно эту функцию виртуальной (а остальные - невиртуальными). Замена на callback, как вроде кто-то предлагал - хрень редьки не слаще, тот же косвенный вызов с теми же издержками. Кстати, они действительно небольшие. Ты уверен, что стОит париться, т.е. узкое место с производительностью именно здесь? Профилятор это показал? Или ты просто так думаешь, заранее? |
| Автор: baldina 25.12.2007, 18:18 | ||
но CRT там не поможет. если идет борьба за пару инструкций, это не выход - косвенный вызов остается. |
| Автор: georain 25.12.2007, 19:01 |
| В общем я сделал все виртуальные функции обычными, и запихал все свои комбинации в новые виртуальные функции, в итоге добился того что и хотел: вызов только одно виртуальной функции для комбинации. В итоге выиграл 4% производительности. Я считаю что это прилично, и труд был потрачен не зря. На счет моего вопроса: для решения таких проблем нужно очень хорошо представлять, что уже известно на этапе компиляции, а что нет. Задавая вопрос "Как я могу (и могу ли вообще) получить указатель на класс, на который указывает указатель на базовый класс?", я допустил логическую ошибку. MAKCim уже сказал, что не могу, потому что (как сказал Earnest) узнать на какой класс указывает базовый указатель мы может только на этапе выполнения, а связывание по типу происходит на этапе компиляции (например вызов нужной функции, в зависимости от типа указателя). Спасибо всем за огромную помощь, как говорится, дурная голова никому покоя не дает. |