![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| georain |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 193 Регистрация: 28.11.2006 Где: Санкт-Петербург Репутация: нет Всего: нет |
Подскажите, что то я запутался.
Есть дерево полиморфных классов, есть указатель на базовый класс. Как я могу (и могу ли вообще) получить указатель на класс, на который указывает указатель на базовый класс. |
|||
|
||||
| Daevaorn |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2155 Регистрация: 29.11.2004 Где: Москва Репутация: 51 Всего: 70 |
"Указателей на класс" в С++ не существует.
|
|||
|
||||
| georain |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 193 Регистрация: 28.11.2006 Где: Санкт-Петербург Репутация: нет Всего: нет |
Извините, неправильно (сокращённо) выразился.
Указатель с типом производного класса?
Нужно получить d_ptrA, d_ptrB или d_ptrС каким-либо образом из b_ptr. |
|||
|
||||
| dizzy1984 |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 675 Регистрация: 15.2.2007 Репутация: 3 Всего: 25 |
Если b_ptr указывает на DerivedA, то можно так
или с помощью c-cast
|
||||
|
|||||
| georain |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 193 Регистрация: 28.11.2006 Где: Санкт-Петербург Репутация: нет Всего: нет |
Так это понятно
А если мы заранее не знаем что он указывает на DerivedA? Мы может определить это через специальную виртуальную функцию. Но как это автоматизировать? Хочется что-то типа b_ptr = dynamic_cast <(b_ptr->get_my_type)>(b_ptr) только без RTTI, ну и чтоб работало) Я думаю что похоже придётся для каждого класса специализированный шаблон заводить... |
|||
|
||||
| dizzy1984 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 675 Регистрация: 15.2.2007 Репутация: 3 Всего: 25 |
А можно привести ситуацию в которой такое преобразование необходимо?
|
|||
|
||||
| MAKCim |
|
|||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 52 Всего: 207 |
нельзя в С++ статическая типизация -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
|||
|
||||
| Alek86 |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1299 Регистрация: 30.1.2007 Где: Киев Репутация: 21 Всего: 25 |
georain, а можно поинтересоваться, зачем это тебе нужно?
по-моему, ты пренебрегаешь такой хорошей штукой, как полиморфизм скорее всего, твоя проблема решается с помощью виртуальных функций. |
|||
|
||||
| MAKCim |
|
|||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 52 Всего: 207 |
Alek86, dizzy1984, я вот не понимаю, зачем задавать подобные вопросы это самый что ни на есть прямой уход от поставленной задачи что не есть хорошо человек определенно спросил, можно ли, дескать, сделать так-то и так-то а вы начинаете демогогию типа "а зачем тебе это нужно" не знаете - не отвечайте извините за резкость...накипело -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
|||
|
||||
| baldina |
|
||||||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
без RTTI вообще никак (ну только если ты сам не хранишь поле типа). RTTI нужен для dynamic_cast.
полностью согласен.
сам то понял что сказал? у тебя уже есть b_ptr. А если ты хочешь и можешь использовать его полиморфно, приведение типа не нужно.
Это в smalltalk такой подход. Мы не знаем, чем на самом деле является класс и запрашиваем возможность использования его в качестве одного из подтипов. Если получается - используем. Для этого как раз может подойти dynamic_cast. Например, у тебя в массиве хранятся указатели на объекты типа Base, но реально имеющие производный тип. И ты хочешь над всеми, кто указывает на DerivedA, выполнить специфичную для DerivedA (не полиморфную) операцию. Будет так:
|
||||||||||
|
|||||||||||
| MAKCim |
|
|||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 52 Всего: 207 |
я отлично понял, что имел в виду georain и объяснил, что в С++ такое невозможно -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
|||
|
||||
| Alek86 |
|
||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1299 Регистрация: 30.1.2007 Где: Киев Репутация: 21 Всего: 25 |
оффтоп
я "отвечал" не на первый вопрос темы (на него уже ответили) а на этот:
пытался, так сказать, как Христос, не накормить рыбой а научить ловить Это сообщение отредактировал(а) Alek86 - 20.12.2007, 12:24 |
||||
|
|||||
| baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
MAKCim, это автору предназначалось. |
|||
|
||||
| MAKCim |
|
|||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 52 Всего: 207 |
я думаю, если другие поняли, то и автор должен понимать -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
|||
|
||||
| georain |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 193 Регистрация: 28.11.2006 Где: Санкт-Петербург Репутация: нет Всего: нет |
Ладно, объясняю зачем мне это нужно. Всё опять же нужно для оптимизации по скорости. Возможно есть какой-то другой способ решения, если знаете подскажите пожалуйста.
Есть довольно большое дерево полиморфных классов, в каждом классе есть тоже довольно много виртуальных функций. Специфика программы в том, что часто в одном месте (всмысле последовательно) из одного из классов вызывается много функций подряд в разных последовательностях. Так вот хочется уменьшить накладные расходы на вызовы виртуальных функций, и сократить их до одной, а потом вызывать остальные статически, ведь по идее с помощь виртуальной функции можно получить информацию о типе, а имея информацию о типе можно вызывать функции непосредственно (статически). Т.е. что-то типа
MAKCim, спасибо за понимание. Я пока писал понял что действительно в с++ так нельзя... если без шаблонов...)) baldina, с dynamic_cast пришлось бы делать перебор для всех классов, а он сам по себе очень не дешёвый - в итоге смысла нет. Конечно есть вариант в самих классах определять дополнительные виртуальные функции с необходимой последовательностью, но их там и так много, перебор получается, к тому-же это сильно увеличит размер виртуальных таблиц. Это сообщение отредактировал(а) georain - 20.12.2007, 13:56 |
|||
|
||||
| Alek86 |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1299 Регистрация: 30.1.2007 Где: Киев Репутация: 21 Всего: 25 |
то есть, если я правильно понял, ты хочешь вызывать функции не виртуально (через таблицу виртуальных функций) а напрямую?
вообще избавиться от виртуальности функций? |
|||
|
||||
| MAKCim |
|
|||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 52 Всего: 207 |
georain,
а если так сделать
-------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
|||
|
||||
| Alek86 |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1299 Регистрация: 30.1.2007 Где: Киев Репутация: 21 Всего: 25 |
исправьте меня, если ошибусь, но, вроде, единственные издержки в вызове виртуальных функций - это то, что они вызываются через указатели, и ускорить их вызов можно, лишь сделав их невиртуальными...
Добавлено через 29 секунд |
|||
|
||||
| MAKCim |
|
|||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 52 Всего: 207 |
Alek86,
-------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
|||
|
||||
| Alek86 |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1299 Регистрация: 30.1.2007 Где: Киев Репутация: 21 Всего: 25 |
тогда по вопросу осталась мелочь - побыстрее определить, что текущий указатель указывает именно на A, а не на B и вызвать определенную статическую функцию с кастанутым текущим указателем...
может, typeof поможет Это сообщение отредактировал(а) Alek86 - 20.12.2007, 14:37 |
|||
|
||||
| HappyLife |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 642 Регистрация: 17.5.2006 Репутация: 3 Всего: 8 |
Кхм.... интересно а насколько дорого стоит вызов виртуальной функции?
|
|||
|
||||
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 41 Всего: 154 |
Не знаю насколько я попал в тему...
избавиться от дополнительных виртуальных ф-й и вызывать правильные не виртуальные методы в производных классах позволяет шаблон проектирования Curiously recurring template |
|||
|
||||
| MAKCim |
|
||||||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 52 Всего: 207 |
вместо
-------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
||||||
|
|||||||
| Alek86 |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1299 Регистрация: 30.1.2007 Где: Киев Репутация: 21 Всего: 25 |
ну, и еще ее нельзя инлайнить, в общем случае
|
|||
|
||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 53 Всего: 183 |
Строго говоря, вовсе необязательно CRT - любой шаблон обеспечивает статический полиморфизм. Только не всегда можно заменить динамический полиморфизм статическим - для этого нужно знать типы на этапе компиляции. Автору: большое дерево классов + много виртуальных функций - уже надо что-то в консерватории поправить. Если достаточно определить в одном месте тип, а потом можно вызвать конкретную функцию, так и сделай именно эту функцию виртуальной (а остальные - невиртуальными). Замена на callback, как вроде кто-то предлагал - хрень редьки не слаще, тот же косвенный вызов с теми же издержками. Кстати, они действительно небольшие. Ты уверен, что стОит париться, т.е. узкое место с производительностью именно здесь? Профилятор это показал? Или ты просто так думаешь, заранее? -------------------- ... |
|||
|
||||
| baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
но CRT там не поможет. если идет борьба за пару инструкций, это не выход - косвенный вызов остается. Это сообщение отредактировал(а) baldina - 25.12.2007, 18:19 |
|||
|
||||
| georain |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 193 Регистрация: 28.11.2006 Где: Санкт-Петербург Репутация: нет Всего: нет |
В общем я сделал все виртуальные функции обычными, и запихал все свои комбинации в новые виртуальные функции, в итоге добился того что и хотел: вызов только одно виртуальной функции для комбинации. В итоге выиграл 4% производительности. Я считаю что это прилично, и труд был потрачен не зря.
На счет моего вопроса: для решения таких проблем нужно очень хорошо представлять, что уже известно на этапе компиляции, а что нет. Задавая вопрос "Как я могу (и могу ли вообще) получить указатель на класс, на который указывает указатель на базовый класс?", я допустил логическую ошибку. MAKCim уже сказал, что не могу, потому что (как сказал Earnest) узнать на какой класс указывает базовый указатель мы может только на этапе выполнения, а связывание по типу происходит на этапе компиляции (например вызов нужной функции, в зависимости от типа указателя). Спасибо всем за огромную помощь, как говорится, дурная голова никому покоя не дает. |
|||
|
||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |