Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Общие вопросы > virtual function |
Автор: sergioK1 12.7.2013, 19:55 |
Собвенно когда вышла жава все были довольны тем что все функции виртуальны , тем более что тормоза по этой причине за которые многие ругали OOP полный миф , Ну язык он есть такой , ну покему когда сам разрабатывешь не сделать virtual ? захотят перегрузить перегрузят , не захотят - ничего не случиться, P.S. в С# такая же фича , разрабатывать не возможно ![]() |
Автор: mes 12.7.2013, 20:45 |
sergioK1, а С++ тут при чем ? ![]() ![]() |
Автор: sergioK1 12.7.2013, 21:53 | ||
При том читать надо что пишут ![]() На С++ разрабатывать тяжело без возможности наследовать почему не облегчить жизнь, тупо ![]() Если второй раз не понял - меняй профессию ![]() ![]() |
Автор: sergioK1 12.7.2013, 23:57 | ||||||
Что отсечь? наооборот добавить для удобства, Ясно что getData может быть изменен так чего не поставить virtual ? Не та идеология в чем ? |
Автор: feodorv 13.7.2013, 07:57 | ||
Помню, в начале-середине 90-х был такой борландовский продукт - TurboVision. Мне понадобилось-то внести небольшие изменения в оболочку одной программы, основанной на этом самом TurboVision. Ха. Нужные методы не были объявлены virtual. Хорошо, что Борланд дал исходные коды TurboVision. Перекомпиляция всего TurboVision на новейшей скоростной 386 системе занимала 4 часа. Путём оптимизации заголовков удалось снизить это время до получаса. Потом ещё несколько раз я вставлял virtual в нужные мне места. И если бы изначально все методы были бы виртуальными, то вся эта дурацкая деятельность была бы не нужна. Поэтому считаю вопрос правомерным. С другой стороны, так изначально был построен C++. Ну вот именно так и никак иначе. Решение о том, будет какой-либо метод виртуальным, принимается разработчиком исходя из логики проектирования классов. Посмотрите на MFC - большинство методов виртуальные. Но не все! В java я тоже могу понатыкать final где не попадя, осложнив жизнь другим программистам. Шучу))) Поэтому вопрос "когда сам разрабатываешь, не сделать virtual" теряет свою правомерность и отправляется целиком к разработчику конкретного продукта...
Вот, кстати, не факт. |
Автор: sergioK1 13.7.2013, 08:48 | ||||
В MFC да , В яве ставят final когда осознанно хотят закрыть наследование осознанно, в С++ какие соображения? тот же буст хоть и студенты писали (хоть и Беркли) ну не могли же они не понимать необходимости в возможной перегрузке например stack reserve , |
Автор: mes 13.7.2013, 09:33 | ||||
1. если автоматом у каждого класса будет таблица виртуальных методов, то о метапрограммированнии можно будет забыть.. 2. в моей практиктике витуальная функция одна на сто или более невиртуальных... а в некоторых случаях меня не устраивает родная виртуальность, и я пишу свою.. тоже забыть ?? 3. в С++ структура и класс ничем по сути не отличаются... В блоки данных тоже помещать таблицу ? 4. Зачастую интерфейс про функцию намного более приемлим, чем интерфейс про класс.. И зачем тогда классовая виртуальность ? 5. ну про конструктор умолчим... и многое многое другое... сейчас лень напрягаться и вспоминать...
перегрузку(overload) с переопределением(override) не путатете ? что ж тогда на виртуальность то замахнулись ? нужна виртуальность во всем берите другие языки, в которых еще и рефлексия к тому же есть.. Нужен еще С++ - используйте связку.. Не надо все разнообразие задач сводить под студенческие требования... |
Автор: sergioK1 13.7.2013, 18:12 | ||||||
Ой только не надо лигвистики :-D перегрузка это когда есть функция а наследник имет свою реализацию , хотите пусть будет переопределение, Если честно Я ваших аргуметов ничего не понял , ни про метопрограмирования ни про class vs structure . в других языках это нормально, в С++ нет какая разница, ? По проще можно . |
Автор: mes 13.7.2013, 22:29 | ||
перегрузка это наличие двух (или более) функций, различаемых типом вызова.. а переопределение, это изменение поведения одной и той же.. другие языки не предоставляют того, что предоставляет С++.. именно за это многообразие, а также за наличия прямого доступа к внутренним представлениям и ругают многие С++.. мол много учить, или мол легко прострелить себе колено.. Все то оно конечно оно так, но зато какие возможности открывает за собой С++. Да многим этим возможности и не нужны, но с другой стороны для них уже дельфи с шарпом есть.. Да С++ не лишен недостатков, и много где он бессилен.. Но на то и разнообразие языков, чтоб для каждой задачи выбирать подходящий... |
Автор: volatile 13.7.2013, 22:40 |
Делайте. Вам что, кто-то здесь запрещает? sergioK1, Какова цель вашего выступления? Что вы предлагаете? |
Автор: mes 13.7.2013, 22:42 |
P.S. я не против внедрения механизмом, испробованных одним языком в другой.. я против привведения С++ в только-студенто-ориентированный язык... вначале посмотрите сколько людей, которые вообще не нужна виртуальность... и за что им будут связывать руки ?! мало того, что цена вызова дорогая, к тому же лишний размер.. но это мелочи, хоть за нич тоже надо платить.. но вот к примеру, как мне в случае маниакальной виртуальности, получить структуру совместимую с С ? заводить новый тип для обычных структур ? а зачем ? |
Автор: sergioK1 14.7.2013, 06:48 | ||
Я предлагаю строить грамотный дизайн даже если это на С++ ![]() И там где есть бизнес обьект он может быть перегружен наследником , И еще чтобы mes внятно и по русски разьяснил третьей попытки , что он имеет ввиду ![]() желательно простыми примерами, вызов виртуал функции дороже чем обычной - чушь ![]() Даже обсуждать лень, |
Автор: mes 14.7.2013, 10:37 | ||||||
скажите это микроконролерщикам.. которым даже обычный вызов бывает дорог..
так я двумя руками за граммотный.. только я против считать явскую корявость граммотным дизайном.. Пусть на ней студенты развлекаются... http://codepad.org/kGYnfiS8
теперь попробуйте повторить с #define V virtual.. |
Автор: volatile 14.7.2013, 10:56 | ||||
Этот вопрос (слава богу!) не нужно обсуждать. Достаточно просто измерить:
http://codepad.org/J9Vb0nl9 На домашней машине, при полной оптимизации, виртуальная функция в среднем в 5 раз медленее чем простая. |
Автор: sergioK1 14.7.2013, 21:21 | ||||||||
угу на вебе ![]() там интерпритатор , который имулирует компиляцию Я измерил открыл Code Block c gcc хотя надо бы в студии но ее счас нетy,
проделал раз 10 максимум что удалось получить это 192,0 vs 158.0 на 11раз получил Times for: virtual function = 172.0, plain function = 182.0 virtual function = 158.0, plain function = 147.0 virtual function = 160.0, plain function = 150.0 sum = 1863248640 Process returned 0 (0x0) execution time : 0.995 s Press any key to continue. потом проверил еще пару раз и вот Times for: virtual function = 177.0, plain function = 161.0 virtual function = 189.0, plain function = 205.0 virtual function = 170.0, plain function = 162.0 sum = 1863248640 Process returned 0 (0x0) execution time : 1.091 s Press any key to continue т,е мы видим что разницы нет , mes , сказал ответили что ставять inline ![]() вызов VF в сpp это сишный вызов поинтера на функцию , хотя там где critical necessary компайлеру лучше не доверяться а делать самому, классический пример "умная пуля" , Я говорил про бизнес обьекты, с "тупо везде" перегнул, у вас скорее конвертер который вообще должен быть static , IMHO, |
Автор: NoviceF 14.7.2013, 21:42 |
не знаю, где в креаторе наболтать оптимизацию, но по дефолту на нетбуке цифры такие Times for: virtual function = 300.0, plain function = 50.0 virtual function = 300.0, plain function = 50.0 virtual function = 300.0, plain function = 50.0 sergioK1, релиз запусти, а не дебаг. |
Автор: sergioK1 14.7.2013, 22:38 | ||
Да в дебаге без разницы в релизе в 4раза И не помогает оптимизация , Страустроп пишет что разница не значительная , он не знает С++ ??? |
Автор: bsa 14.7.2013, 22:46 |
sergioK1, что такое вызвать функцию? Это делает инструкция call <address>. Она есть практически в любом процессоре. Но в некоторых РИСКах ее может не быть, тогда это делается вручную: адрес возврата записывается в стек, указатель стека смещается на размер адреса возврата, происходит загрузка в указатель команд адреса процедуры. Когда имеется вызов виртуальной функции, то тут все сложнее: сохранить адрес возврата, сместить указатель вершины стека, загрузить адрес процедуры в указатель команд, загрузить адрес таблицы виртуальных функций, добавить смещение, загрузить адрес функции. А теперь вспомним, что на С++ пишут в основном не под микроконтроллеры, а под "большие" машины архитектуры x86 (или x86_64). Чем она отличается? А тем, что кроме всего вышеперечисленного есть кэш и многостадийный конвеер. Таким образом, если производится одновременная работа с большим количеством данных, то кэш начинает тормозить весь процесс - происходят постоянно промахи и приходится заменять одни данные другими. А вот конвеер спотыкается на переходах. И, есть у меня подозрение, что их предсказатель далеко не всегда успешно справляется при вызове виртуальных функций, так как в момент принятия решения адрес перехода может фактически отсутствовать в доступности процессора. А если предсказание перехода завершилось неудачей, то после выявления этого весь конвеер будет сброшен и процессор "потеряет" более десятка тактов... Когда разработчик проектирует класс, он предусматривает, что пользователь может переопределить, а что в принципе не должен. Причем, опыт показывает, что 90% методов классов в переопределении не нуждаются. Главная философия языка "не делать то, о чем не просили". Если ты хочешь переопределить у стека метод reserve (нахрена?), то сделай это путем агрегации (сделай свой стек, который содержит в себе стандартный). Все равно, все члены класса приватные и ты из потомка к ним доступа не получишь. Если ты хочешь изменить аллокатор, то может стоит именно это и сделать? Посмотри на второй параметр шаблона. И не забывай, что все стандартные контейнеры самодостаточны. Их не требуется как-то "дореализовывать". Кстати, то что какие-то части стандартной библиотеки писали "студенты" не означает, что это студенты проектировали. В комитете по стандартизации сидят довольно серьезные люди. |
Автор: sergioK1 14.7.2013, 23:46 |
volatile NoviceF Это обман трудящихся ![]() у меня даже 1% разницы нет , |
Автор: CosmoMan 29.7.2013, 11:14 |
Я одно время тестировал оверхед при использовании виртуальных функций в классе. Это очень актуально для геймдева, где может каждый фрейм перебираться миллион объектов в цикле и дергаться у них виртуальные методы. Особенно если объекты многокомпонентные (много стратегий поведения с общим интерфейсом). там это имеет значение и может существенно влиять на производительность. Я считаю, что делать все функции виртуальными - это лишнее. Но думаю не помешал бы блок вроде public virtual: |
Автор: volatile 29.7.2013, 13:08 | ||
sergioK1, тут уже говорилось что код нужно проверять на максимальной оптимизации на скорость. То что у вас скорость зависит от "разбиения на файлы", говорит лишь о том что у вас не включен элементаный link-time code generation. Да и потом изучайте мат-часть. То что вирт. функция будет медленней - даже спорить смешно. |
Автор: sergioK1 29.7.2013, 13:28 | ||
где его включать? вопрос неправильно ставите(это масчеи матчасти ![]() а static call vs dynamic call , т,е вопрос можно ли оптимизировать что-бы был статик? в чистом С это можно(судя по тестам), почему в С++ нет ? |
Автор: volatile 29.7.2013, 14:01 | ||
Нигде нельзя. Потому-что в компйл-тайме компилятор не знает, какую функцию ему вызвать. И это решается только в ран-тайме, путем дополнительного вычисления (извлечение нужной функции из талбицы). В случае не вирт. функции, никакого вычисления в ран-тайме НЕ нужно. Все известно на момент компиляции. И компилятор просто подставляет жесткий адрес функции. |
Автор: mes 29.7.2013, 15:38 |
если известен тип, с++ позволяет оптимизировать виртуальный вызов.. |
Автор: volatile 29.7.2013, 15:50 |
Если известен тип, тогда смысла в виртуальной функции нет. Добавлено через 2 минуты и 37 секунд Естествеено, если взять пример с одним типом, как код выше, ясно что там другого просто не будет. В реальных программах (сколько нибудь сложных) - так не бывает. |
Автор: mes 29.7.2013, 16:03 | ||
зато есть смысл в оптимизации такого вызова ![]()
зато бывает в тестах, что мешает некоторым (как например тс) адекватно оценить затраты на виртуальность.. Добавлено через 2 минуты и 23 секунды и все ж бывает.. |
Автор: volatile 29.7.2013, 16:29 | ||
Аналогично, можно еще очень сильно настаивать на том, что скорость умножения, вообще не имеет значения в программировании основываясь на том что высосанный из пальца тестовый код выполняется моментально:
Да здесь не будет умножения в ран-тайме, но это вовсе не означает что можно теперь плевать на скорость умножения. Да бывает что так пишут. Но это капля в море. и вообще не о том речь. Добавлено через 3 минуты и 54 секунды Так - же и с вашими оптимизациями вирт.функций. Там где их компилятор сможет оптимизировать, там вообще не нужно виртализация. И лучше рассмотеть использвание шаблонов! Там гораздо надежнее получите высокооптимизированный код |
Автор: mes 29.7.2013, 18:27 | ||
как по мне тут соленное с влажным сравнивается.. |
Автор: volatile 29.7.2013, 20:37 |
Вот здесь люди тоже сравнивают : http://stackoverflow.com/questions/9907004/dyamic-vs-static-polymorphism-in-c-which-is-preferable есть и еще с десяток тысяч линков, найдете без труда в гугле... |
Автор: mes 29.7.2013, 21:48 |
я не о сравнение динамического и статического полиморфизма, а о сравнение оптимизации виртуального вызова со статическим полиморфизмом... |
Автор: borisbn 29.7.2013, 22:15 | ||||||||||
Как говорит мОлодежь в интернетах - я бы вд..... дореализовывал... Вот смотрите: такая комбинация в пользовательском коде:
мягко говоря - не редкость. Так почему бы не реализовать
как в той же КуТе ? Или такой пользовательский код:
есть у 146% программистов. Так почему не ввести в контейнер функцию bool contains( T x ) const; ? Я уже молчу про убогийший http://en.cppreference.com/w/cpp/string/basic_string/replace... Ну, везде... Просто везде... есть функция замены подстроки в строке на другую строку. Типа
По существу вопроса: ИМХО, если ты достиг такого уровня в программировании, что ускорить твою программу может только (!!!) переход от виртуальных функций к обычным, то тебе нужно не задавать вопросы на форумах, а как минимум отвечать на них, а как максимум писать соответствующие статьи P.S. Надо бы для "Premature optimization is the root of all evil" придумать такую же известную и запоминающуюся аббревиатуру как IMHO. Пусть будет PORE ![]() |
Автор: volatile 29.7.2013, 22:47 | ||
Ну и что тут влажное, а что соленое ? Оптимизировать можно только те виртуальные вызовы, (да и то только теоретически) которые можно преобразовать к статическому полиморфизму. Остальные (а их подавляющее большинство), оптимизировать нельзя даже теоретически. Вообще, имхо, начинаете жонгллировать словами... borisbn, по-сути да. В большинстве случаев не нужно предельное быстродействие. И можно пренебречь скоростью. Просто здесь пытаются убедить что виртуалиация не медленее чем простой вызов. А это в принципе не верно. |
Автор: sergioK1 30.7.2013, 10:48 | ||
Ну покажите свой пример, который не мешает реальной оценке затрат, borisbn То что можно испортить стандартный код всем известно , Элементарный thead safety как ты сделаешь ? Eсть у тебя foo(Vector& v ) - т,е рапер не пройдет и std::set где равные элементы это те где е1-е2 < некой дельты , опять же не меняя интерфейса foo(std::set& s) . только других либ не предлагай ![]() Тот кто скажет что такого в реальной жизни не бывает , как volatile просто не пишет больших апликаций ![]() |
Автор: bsa 30.7.2013, 11:47 | ||||||
О да! Нужная вещь... Вот только есть одна маленькая проблема, несущественная для простых типов. В случае takeBack произойдет 100% копирование объекта (в Qt это решено тотальным использованием PIMPL и COW). И если у тебя та же строка, то займет это не мало времени (хотя, в C++11 это можно эффективно оптимизировать).
Я бы вообще все эти штуки делал бы через отдельные функции:
|
Автор: borisbn 30.7.2013, 11:54 |
Что называется - найдите одно отличие )) А по поводу свободных функций - я только за, но чтобы не у каждого они лежали где-нибудь в stl_utils.hpp, а поставлялись бы с компилятором (как это делается во многих языках) |
Автор: sergioK1 30.7.2013, 12:18 | ||
[/QUOTE] Когда возникают подобные ситуации то скоростью , размером приходиться жертвовать, Точнее примемять там где она не критична , ну так кто-нидь предложит решение , |
Автор: volatile 30.7.2013, 12:32 | ||
Во первых я это говорил совсем по другому поводу... Во вторых не нужно придираться к словам. Вы пытаетесь доказать что умножение не требует затрат, осовываясь на том что вычисляется моментально. А я говорю что такого в жизни не бывает. Правильнее конечно сказать, бывает, только это не играет никакого значения в реальной программе. И умножение будет занимать процессорное время. Замените слово "умножение", на "виртуализацию". Все. Добавлено через 7 минут и 35 секунд В вашем случае, имхо, достоточно ввести глобальную оптимизацию Потому-что хоть код и теоретически можно оптимизировать, но практически компиляторы пока даже этого не научились делать нормально. Так что введите линк-тайм генерейшен, и глобольную оптимизацию вы не сказали какой у вас компилятор, поэтому более конкретно подсказать не могу |
Автор: volatile 30.7.2013, 13:03 |
Вы, имхо, вообще измеряте не виртуализацию. ![]() А я не телепат.что там у вас... А вообще пишите как хотите. меня удивляет что вродебы не новичкам, нужно доказывать что белое это белое. а черное это черное. ![]() |
Автор: volatile 30.7.2013, 13:25 |
http://www.google.com/search?hl=ru&q=Virtual+functions+performance+C%2B%2B&lr=&aq=f&oq= |
Автор: sergioK1 30.7.2013, 15:44 | ||
Cтрауспу поверил на слово он пишет что разницы нет , или перевод sucks . основная причина в инлайне IMHO Так что белое и что черное ? |
Автор: volatile 30.7.2013, 17:45 |
Где он это пишет? ссыллку дайте. |
Автор: sergioK1 30.7.2013, 19:01 | ||
В книге страница 515-520 , |
Автор: volatile 30.7.2013, 20:49 | ||
У вас бред, вам это приснилось ...
http://www.stroustrup.com/bs_faq2.html |
Автор: Alexeis 30.7.2013, 21:57 |
Все эти оверхеды существенны для всякого рода железок. Для писшника 4 байта VMT ерунда, а вызов функции усложняется на одну инструкцию получения адреса функции по фиксированному смещению от начала VMT. Если для функции такая операция критична по времени, то следует подумать о том чтобы ее заинлайнить. Насколько я помню любая функция из секции импорта также требует дополнительной операции получения адреса, поскольку компилятор лишь знает где будет располагаться адрес функции после загрузки Dll . И никого не волнуют такие затраты. Мне кажется главная причина того что не все функции виртуальные это потеря прозрачности. Виртуальная функция сама по себе "сюрприз". Мы перекрываем виртуальную функцию, чтобы изменить поведение уже написанного кода, однако если код писал другой человек, то мы можем не знать заложенной логики и вместо правильно работающей чужой функции, в некотором месте может вызываться наша, которая уже может не знать замысла автора класса предка. Иногда нужно создать функцию с тем же именем что и виртуальная, но для своих целей, при этом мы хотим, чтобы замысел автора класса остался неизменным. Она будет заменять функцию предка, в новом классе при этом предок продолжить вызывать свою стабильную функцию. При глубокой иерархии мы можем и не знать имен всех функций и случайно назвать свою функцию также как одна из виртуальных функций предка. Иными словами, виртуальность это некоторый механизм, который нужен только там где он нужен, как например механизм констант. Константы в С++ это круто это гибко, это безопасно, но никому не придет в голову делать все данные константами. |
Автор: bsa 30.7.2013, 22:41 |
Alexeis, золотые слова |
Автор: xvr 6.8.2013, 12:33 | ||
Гы ![]() Был случай - одна программа на Java была ускоренна в несколько раз простым прописыванием final ко всем методам всех классов, которые реально не были виртуальными. |
Автор: sergioK1 6.8.2013, 13:29 | ||||
С потоками ? Какая java ? версия ? Желательно код сюда , А то мой телепат в отпуске ![]() Хотя final или static в жаве грузиться заранее это фактически аналог inline , |
Автор: xvr 6.8.2013, 13:37 |
Это отключение виртуальности. Все остальное - это уже последствия. |
Автор: Alexeis 6.8.2013, 14:42 |
Это отключение корявой реализации чего-то вместе с виртуальностью. Сами же виртуальный вызов в С++ почти ничего не стоит. Есть правда еще один минус виртуальности. Компилятор не может выкидывать функции, которые ни где не использовались, если они виртуальные. Зато может инлайнить, если на 100% уверен, что будет вызвана именно эта функция. |
Автор: bsa 6.8.2013, 14:50 |
смотря по сравнению с чем. Если сравнивать с простым вызовом подпрограммы, то цена огромна, если с библиотечным вызовом, то сопоставима, если с системным - то пренебрежимо мала. Касается современного "настольного" процессора с длинным конвейером и предсказателем переходов |
Автор: sergioK1 6.8.2013, 15:58 | ||
пример показывай где огромна, хватит уже теорий ![]() Alexeis , это установка флага const в поинтер на функцию , |
Автор: Alexeis 6.8.2013, 16:12 |
С этого момента по подробнее. Я где-то раньше читал, что вызов подпрограммы занимает 12 тактов процессора (x86), добавим сюда типичную операцию помещения в стек 1-2х параметров (хз сколько тактов), против дополнительных расходов по извлечению адреса расположенного по фиксированному смещению. По сути 2е операции с памятью. 1я получение адреса VMT, 2я получение адреса функции. Что же здесь такого накладного? Неужели промахи кеша процессора приводят к таким огромным потерям производительности? |
Автор: bsa 6.8.2013, 18:02 |
Alexeis, я же написал, смотря с чем сравнивать. Если ты выполняешь какие-то внутренние вычисления и при этом активно используешь виртуальные методы, то производительности ты потеряешь значительную долю. А вот если 90% времени программа "отдыхает" (что-то делает система), то скорее всего, виртуальность вреда существенного не наносит. |
Автор: mes 6.8.2013, 18:34 | ||
а значит все таки стоят ![]() ![]() ну а в общем согласен с Alexeis, в программированниие есть множество других аспектов, которые губится поголовной виртуалностью, в сравнении с которыми цена виртуального вызова не имеет значения.. |
Автор: xvr 6.8.2013, 22:45 | ||
Не так страшен вызов виртуальной функции сам по себе, как то, что напрочь отбивает все возможности компилятора по оптимизации через границу этого вызова. И это касается не только инлайна, но и pointer анализа и вынесения общих подвыражений. Пример -
|
Автор: sergioK1 6.8.2013, 23:38 | ||||
Все это так но, но при нормальном код ревью вы скорее всего оптимизируете алгоритм сами , по крайне мере постараетесь это сделать если пример будет более сложный, компилятор не всемогущ и гарантий 100% что он оптимизирует нет, или нааборот из-за каких то других причин будет нельзя пользоваться оптимизацией . Т,е , "проблемв тормозов" остаюеться в теории, по крайне мере в основном В java проверил final эффект нулевой |
Автор: xvr 6.8.2013, 23:51 | ||||||
Угу, но включенная по умолчанию виртуальность для всех методов будет этому сильно мешать.
Разумеется, но 100% от него никто и не требует. Иначе не было бы инженеров по performance анализу (а они есть, и немало). Однако, ускорение программы в разы при включении оптимизации вполне рядовая вещь.
Как раз наоборот. Если сделать все методы виртуальными, то на больших программах (где есть выигрыш в разы от включения оптимизаций), этот выигрыш может заметно упасть (причем очень заметно) Я не говорил, что это проявится на любой java программе. Я говорил, что такие программы существуют. К сожалению цифрами подтвердить влияние виртуальности сложно, т.к. для получения таких цифр придется вручную перепахать все исходники, а размер этих исходников должен быть очень большим, что бы эффект проявился. Не думаю, что бы кто нибудь за это взялся из чисто спортивного интереса ![]() |
Автор: sergioK1 7.8.2013, 10:16 | ||||||||
Да вобщем то про недостатки всех функций быть виртуальными ,по принципу а может пригодиться ,Я давно понял , надо было раньше об этом произнести в слух ![]() Про final Я слышал пару раз в реальности ни разу не видел. И еше у меня сложилось ощущение в Java не все функции виртуальны , т,е компайлер "умнее" чем в С++ , т,е там где наследника нет нету виртуального механизма , Но поскольку документации по теме мизер, то остаеться только догадаваться так это или нет , |
Автор: xvr 7.8.2013, 13:04 | ||
Возможно. Та история, которую я тут упоминал, произошла более 20 лет назад, с тех пор компиляторы сильно поумнели ![]() Хотя в Java есть 2 вещи, одна из которых сильно мешает а вторая помогает проводить такие оптимизации. В Java есть динамическая загрузка классов, так что не-виртуальный метод может в run-time привратится в виртуальный, что явно не способствует проведению оптимизации в compile-time ![]() С другой стороны в Java есть JIT компилятор, так что при таком 'внезапном' изменении статуса виртуальности функции ее можно будет и перекомпилировать. ![]() Что, увы, автоматически перености большую часть оптимизатора в run-time, что отнюдь не добавляет надежности и устойчивости всей Java системе в целом ![]() |
Автор: Amp 7.8.2013, 16:09 |
У самого Java компилятора маневров для оптимизации кода вызова виртуальных методов не так и много - инструкции invokevirtual и invokeinterface. Использование invokeinterface может сказаться на времени вызова метода не самым лучшим образом. Остальные оптимизации уже за JIT-ом. |
Автор: NoviceF 8.8.2013, 13:30 |
По поводу виртуальный функций есть ещё одно не совсем очевидное следствие, которое не определено стандартом, но зачастую компиляторы поступают именно так. Когда инстанцируется шаблонный класс, в котором есть виртаульная функция, она будет инстанцирована всегда, даже если в коде она не используется (актуально для старых версий gcc и MSVС компилятора, с новыми не проверял), в отличие от всех других функций шаблонного класса. Что может приводить к невозможности использовать шаблонный класс там, где ограничений для его применения на самом деле нет. Например, невозможно создать экземпляр MFC контейнера CArray с типом с закрытым конструктором по умолчанию из-за виртуальной функции Serialize. |
Автор: Alexeis 8.8.2013, 14:52 |
NoviceF, ну это скорее ограничения обычного класса чем шаблонного. Таблица VMT должна содержать записи всех виртуальных функций и все указатели должны указывать на реальные адреса. Представь, что я каким-нить неявным для компилятора образом образом, получу указатель на предка (к примеру COM интерфейс) и передам его за границу модуля в Dll, и оттуда вызову виртуальную функцию. Раз компилятор не может отследить, то обязан всегда все виртуальные функции помещать в исполняемый модуль и все записи помещать в VMT. В случае же простой функции компилятору достаточно убедиться, что ни где нет оператора взятия адреса функции и она ни где явно не вызывается, чтобы не компилировать ее и не включать в образ. Для виртуальной функции именно неявный вызов является причиной того, что она всегда будет включаться в образ и это не зависит от версии компилятора и не может быть иначе реализовано. |
Автор: Jeka178RUS 13.8.2013, 13:59 | ||||
Ну и жесть ![]() |
Автор: mes 16.8.2013, 09:41 |
нуттак ![]() |