![]() |
Модераторы: Daevaorn |
![]() ![]() ![]() |
|
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Есть у меня такая бяка.
Задача в том, чтобы сделать скажем 10-20 классов наследников от Base. И у всех этих классов будет единый код parse(), а вот метод custom() я хочу переопределить в каждом классе. Чтобы чуток убыстрить код я решил метод сделать inline. Вопрос заключается в том как поведет себя компилятор в этом случае. Ведь изначально код метода parse() - общий для всех экземляров, меняется только объект, но если идет inline подстановка кода внутрь метода каждого экземляра класса на базе Base, не получится ли так, что код блока for(){} будет продублирован 10-20 раз в исполнимом файле для каждого класса? Или компилятор просто проигнорирует ключевое слово inline |
|||
|
||||
Alexeis |
|
|||
![]() Амеба ![]() Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: 12 Всего: 459 |
Inline нестрогая директива, а virtual строгая. Поскольку они взаимоисключающие, то сработает тока virtual.
-------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Спасибо. Жалко, что у компилятора (gcc) по этому поводу варнингов не выводится.
Еще один вопрос. Как компилятор разрулит ситуацию, ведь указатель на метод custom() у каждого класса будет разным, не будет ли в этом случае весь код из parse() дублироваться в новые классы?
Это сообщение отредактировал(а) SABROG - 24.7.2009, 21:14 |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Они не взаимоисключающие, вызов виртуальной функции может быть встроен в некоторых случаях. Но ключевое слово inline для этого писать совершенно не обязательно, позволь компилятору самому решить. Функция определена в самом классе - этого достаточно. Нет, функция parse одна, с чего ей дублироваться? Это сообщение отредактировал(а) azesmcar - 24.7.2009, 21:28 |
|||
|
||||
kamre |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 330 Регистрация: 24.3.2006 Репутация: 1 Всего: 13 |
В этом случае может подойти static polymorphism и Curiously recurring template pattern. Компилятор может в принципе и заинлайнить все эти custom() функции. |
|||
|
||||
Alexeis |
|
|||
![]() Амеба ![]() Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: 12 Всего: 459 |
Каким образом? Ведь суть позднего связывания в том, что во время компиляции неизвестно какой реально метод будет вызван, поэтому и вставляется код который ищет адрес функции в VMT. Внутри метода этого класса 100% будет вызван виртуально. Инлайн возможен только если объект создан статически и тут же вызван его метод "через точку". Я таких вещей не проверял, но из курса по ООП я помню то что виртуальная функция всегда должна вызываться как виртуальная. -------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
|||
|
||||
azesmcar |
|
||||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Ну встроить он может только те вызовы, при которых ему заранее известен тип. В принципе все зависит от компилятора, но исключать возможность встраивания виртуальных функций не стоит. Я не о конкретно этом коде говорил, вообще, ну тут он может не встроится, а в другом месте встроится. Виртуальные функции ведь не всегда вызываются как виртуальные. Например в этом случае
этот вызов вполне может быть встроен
а тут разумеется встроить не сможет даже самый гениальный компилятор (тут нужен дар предвидения ![]()
ну да, я как раз об этом. Это сообщение отредактировал(а) azesmcar - 24.7.2009, 22:31 |
||||||
|
|||||||
mes |
|
||||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
![]()
![]() Добавлено через 1 минуту и 15 секунд
![]() |
||||||
|
|||||||
SABROG |
|
||||||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
А вообще возможно завести контейнер, который содержал бы указатели на базовый класс и получая указатель через этот контейнер использовать методы производного класса (upcast?), без RTTI?
Просто я не совсем понимаю как это работает на Java: Базовый класс
Производный класс:
Вызов переопределенного метода parse() через базовый класс, как такое возможно?
delegates - контейнер map. Это сообщение отредактировал(а) SABROG - 25.7.2009, 18:11 |
||||||
|
|||||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
нет.. но можно постораться сократить кол-во виртуальных вызовов. Добавлено через 2 минуты и 20 секунд так на Яве по умолчанию вроде ж все методы виртуальные ![]() Это сообщение отредактировал(а) mes - 25.7.2009, 18:12 |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Если я сделаю базовый класс полностью виртуальным мне это поможет? ![]() Тут я не уловил мысли. В принципе у меня один метод виртуальный, который переопределен в производном классе. Если я вызову не виртуальный метод parse() базового класса, в котором используется переопределенный виртуальный метод производного класса это будет работать? |
|||
|
||||
mes |
|
||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
вот тут многоразовый вызов виртуального метода custom. Хотя достаточно сделать виртуальным parse (), а чтоб не повторять код в теле функции применить шаблоны, возможно CRT Pattern. Вообщем мысль в том, чтоб правильно организовать архитектуру, избежав лишних виртуальных вызовов. |
||||
|
|||||
SABROG |
|
||||||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 4 Всего: 91 |
Я на это пойтить не могу, смысл всего в том, чтобы избежать дублирования кода. Если я сделаю parse() виртуальным, то мне придется в 20 классах дублировать цикл for(). Ладно, может быть тогда посоветуете какой-нибудь другой способ, чтобы избежать такого:
Пытаюсь написать класс, который было бы удобно использовать с StAX xml парсером, но если брать во внимание саму технологию, то отпарсить сложный xml файл с большой глубиной уровней задача не из легких. Ссылка для ознакомления: http://www.devx.com/Java/Article/30298/0/page/2 - статья про StAX в Java А это то, как выглядит парсинг xml'я простой структуры, всего 3 вложенных цикла while. У меня же этих циклов намного больше.
Это сообщение отредактировал(а) SABROG - 25.7.2009, 19:03 |
||||||
|
|||||||
mes |
|
||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
А если сделать две Parse ? одна для вызова виртуальная, другая шаблонная для имплементации ? Вот в упрощенном виде :
Это сообщение отредактировал(а) mes - 25.7.2009, 20:21 |
||||
|
|||||
Любитель |
|
|||
Программист-романтик ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3645 Регистрация: 21.5.2005 Где: Воронеж Репутация: 24 Всего: 92 |
Именно так обычно и делается. У Саттера вроде была фраза о том, чтобы делать виртуальными только прайват-методы. А паблик/проектед обёртки проверяют аргументы и выполняют некий общий, ненастраиваемый код (это правда специфика С++ - не во всех ОО-моделях прайват-методы вообще могут работать как виртуальные). |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
Это несколько другая задача (можно сказать обратная нашей)- паттерн невиртуальный интерфейс. у нас "проблема" - лишние виртуальные вызовы. Данный паттерн ничем в данном вопросе помочь не может ![]() |
|||
|
||||
Любитель |
|
|||
Программист-романтик ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3645 Регистрация: 21.5.2005 Где: Воронеж Репутация: 24 Всего: 92 |
Сорри, я невнимательно прочитал твой прошлый пост :(
Я думал речь о том, как обеспечить настраиваемость без дублирования кода, а не о минимизации виртуальных вызовов. Тогда речь о другом - а стоит ли это делать вообще? Ведь parse (пусть и маленький) всё равно придётся писать везде в этом случае. Как я понимаю, речь о прикладном приложении, причём на Qt - там найдётся куча гораздо более узких мест.. |
|||
|
||||
mes |
|
||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
не обязательно.. вот пример, заодно и тс. будет легче
как видите, никаких лишних повторений исходного кода ![]() Это сообщение отредактировал(а) mes - 29.7.2009, 03:57 |
||||
|
|||||
Любитель |
|
|||
Программист-романтик ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3645 Регистрация: 21.5.2005 Где: Воронеж Репутация: 24 Всего: 92 |
Да, красиво
![]() Единственное - всё-таки увлекаться таким не стоит. Пусть код писать не будем, но для каждого цикла ведь весь цикл будет дублироваться (придесятке классов это несущественно, конечно). Это сообщение отредактировал(а) Любитель - 28.7.2009, 17:06 |
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
ну это естественно, ради одного приходится жертвовать другим. Тут уж пусть тс. решает что ему важней: избежать лишних виртуальных вызовов или сэкономить на объеме машинного кода (излишки которого в общем случае для данной задачи минимальны) ![]() Это сообщение отредактировал(а) mes - 28.7.2009, 18:28 |
|||
|
||||
![]() ![]() ![]() |
Правила форума "С++:Общие вопросы" | |
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |