Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
Здравствуйте C: Продолжаю изучать D&E BS и некоторые ранние статьи BS. Книга, как я и говорил ранее, великолепная, другой эпитет подобрать трудно. Объем нюансов возникающих при проектировании и разработке языка огромный, не буду их перечислять - те, для кого этот топик вероятно знакомы с ними, а даже если не знакомы, то лучше BS я все равно не напишу. У меня много вопросов, на мой личный взгляд это интересные, хорошие вопросы. И позже, я планировал сделать какую-то отдельную тему посвященную этой книге, но поскольку график слишком плотный, то я понимаю, что времени на это может просто не хватить, да и такие большие топики не всегда приветствуются, что возможно и правильно. Потому пока не время для "всех вопросов". BS отдает виртуальным функциям центральную роль при программировании на С++ и именно реализация такого рода концепции является одним из главных шагов для рождения С++ из C with Сlasses. Выше нужно сделать акцент на слове "реализация", я намеренно не использовал слово "появление". Данный раздел я решил посвятить виртуальным функциям, уже несколько дней они не дают мне спокойно думать о чем-то другом. Точнее не они, а история их реализации в С++. 1. Пусть у нас была бы возможность повлиять на реализацию языка. Представьте, что вы встретили листинг (D&E, BS) Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. Какой результат на ваш взгляд было бы логично ожидать в строчках 1, 2, и, самое главное, почему? (вопрос не о том, как сейчас будет происходить обработка данного кода). При этом, было бы интересно узнать о ваших мыслях не в контексте того, что сейчас есть в С++, а в контексте того, что у вас есть C with Сlasses и вы планируете интегрировать к данному языку механизм виртуальных функций. 2. Как часто вы используете виртуальные функции в своих программах и как лично вы относитесь к данному механизму? 3. Считаете ли вы ослабление правил замещения для типа возвращаемого значения и для аргументов правильным решением? Интересно, если бы комитет не принял предложения об этом, каким образом были бы решены возможные проблемы(пример из теории компиляторов, метод clone в базовом и производных классах). Лично мне кажется, что это привело бы к изменениям в системе типов языка, что в конечном счете могло положительно сказаться на ней. Было бы очень интересно узнать ваше мнение по данным вопросам:) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.02.2017, 22:40 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
SashaMercury, 1) Когда я вижу a.xxx или a->xxx то я ожидаю, что вызовется xxx именно у того класса, на экземпляр которого указывает a (или сам им является). В С++ это так и есть для полей и виртуальных функций. А для обычных функций класса - нет, даже если наследник переопределил функцию. 2) виртуальные функции - это в сочетании с наследованием в С++ необходимый и достаточный инструмент для реализации концепции интерфейсов. Так что что почти в любой программе в которой больше одного модуля они используются. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.02.2017, 23:00 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
SashaMercuryКакой результат на ваш взгляд было бы логично ожидать в строчках 1, 2, и, самое главное, почему? Лично я бы ожидал, что ошибка компиляции возникнет ещё раньше, когда идёт переопределение метода с другой сигнатурой. Но кое-кто при разработке языка пожадничал на явное указание overload/override и в результате мы имеем отличное логово для багов. PS: override таки появился в С++11 и лично я его использую повсеместно, где хочу именно перекрыть метод. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.02.2017, 23:10 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
SashaMercury, Параллельное наследование насколько мне известно не реализовано ещё ни в одном языке к сожалению. Всё ложится на плечи программиста на уровне "я знаю что класс А всё таки класс Б" ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2017, 08:41 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
" для рождения С++ из C with Сlasses" 20 лет назад я учился именно такому С++. Большинство фишек из 11,14, 17 версий уводят все дальше от этого базового уровня. Становясь более мощным, язык позволяет все более сложные концепции и приемы, это повышает требования к программистам, уменьшает их число, повышает порог вхождения, но от возможности выстрелить в ногу так и не избавляет полностью. Мне кажется, что современный С++ можно рассматривать как ветку от базового, направленную в сторону расширения возможностей языка. И что есть потребность в языке, который был бы другой веткой от базового С++, в котором меньше было бы всяких возможностей в духе Алексндреску, но который был бы надежнее, но без реализации через виртуальную машину (как Java), с сохранением и производительности и возможностью работы с иерархиями классов. Одной из основных возможностей повышения надежности мне кажется контроль работы экземпляров классов только в своей памяти, иное - только через специальные атрибуты. Чтобы в ран-тайме можно было бы включить такой режим контроля, доступна только своя память (и аргументы функций как пример средства реализации возможностей программы). Мне кажется что такой "более надежный но менее навороченный С++/С_с_классами" лучше подошел бы для всяких десктопных приложений, чем Java или C#, например те же десктопные игровые клиенты. Не уверен, может быть Objective C несет в себе что-то такое, давно не смотрел в ту сторону, да и на Windows с ним проблемы, а больше ничего похожего вообще в голову не приходит. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2017, 09:11 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
teo609, Держи ,,,,,,,,,,,, googlethis: dlang, golang, nimlang, rust ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2017, 10:59 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
Anatoly Moskovsky 2) виртуальные функции - это в сочетании с наследованием в С++ необходимый и достаточный инструмент для реализации концепции интерфейсов. Так что что почти в любой программе в которой больше одного модуля они используются. нет, это не так. можно программировать вообще без виртуальных функций, на шаблонном полиморфизме, на современном С++ еще на лямбдах, и чем новее версия языка, тем более он нас к этому стимулирует. Виртуальные функции нужны только когда у вас в программе есть иерархии классов. Кстати, я видел в сети предложение в стандарт для реализации в С++ множественной диспетчеризации в виртуальных методах, вот это была бы бомба! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2017, 11:22 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
SashaMercury Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. Какой результат на ваш взгляд было бы логично ожидать в строчках 1, 2, и, самое главное, почему? (вопрос не о том, как сейчас будет происходить обработка данного кода). При этом, было бы интересно узнать о ваших мыслях не в контексте того, что сейчас есть в С++, а в контексте того, что у вас есть C with Сlasses и вы планируете интегрировать к данному языку механизм виртуальных функций. По классике это должен был бы быть Код: plaintext 1. И как раз в тему о multiple dispatching Дело в том, что семантика присваивания полиморфна по отношению к двум видам объектов: что присваивается чему присваивается Возможны тут 4 случая Тип источникаТип приёмникаСемантика операцииBaseBaseНормальное присваивание объекта класса BaseBaseDerivedНедопустимая операция, так как часть членов класса Derived не будет присвоенаDerivedBaseУсечение Derived до Base, опасная, но допустимая в С++ операция, поскольку часть данных теряетсяDerivedDerivedНормальное присваивание объекта класса Derived Именно поэтому operator= как бы не наследуется и не переопределяется. Поэтому я бы рассматривал этот конкретный пример совершенно отдельно от обсуждения виртуальных функций, которые достаточно просты по своей семантике. автор2. Как часто вы используете виртуальные функции в своих программах и как лично вы относитесь к данному механизму? Ну, как часто, так часто, как надо. Это зависит от задачи. В общем, полиморфизм на типе объекта используется везде, где используются иерархии классов и операции над этими классами. С точки зрения семантики виртуальных функций в С++, она, безусловно, контринтуитивна, потому что естественным для программиста было бы, если бы все методы были автоматом виртуальными. Появление в С++ необходимости явно требовать оформления вызова виртуальной функции как косвенного вызова через таблицу виртуальных методов безусловно связана с необходимостью обеспечить управление быстродействием результирующей программы, получаемой из исходного кода. И хотя в общем стоимость виртуального вызова не так уж и сильно больше стоимости вызова обычного (оба на самом деле достаточно высоки, потому что надо формировать аргументы и переключать стек), во времена появления С++, наверное, разработчики боялись всего-всего, и я полагаю, что Страустрап просто остерёгся делать все поголовно функции виртуальными. В более современных языках, которые являются наследниками С++, -- Java и C# -- виртуальные вызовы делаются автоматически везде. Кстати, не многие помнят, что слово virtual в английском языке означает "действительный", и именно поэтому это слово используется в этом случае. автор3. Считаете ли вы ослабление правил замещения для типа возвращаемого значения и для аргументов правильным решением? Интересно, если бы комитет не принял предложения об этом, каким образом были бы решены возможные проблемы(пример из теории компиляторов, метод clone в базовом и производных классах). Лично мне кажется, что это привело бы к изменениям в системе типов языка, что в конечном счете могло положительно сказаться на ней. Я не очень понял, о чём ты тут ... Я бы думал, что кардинальное решение этой проблемы -- множественная диспетчеризация. Другой вариант решения, очень простой -- это использовать вместо Код: plaintext 1. функцию Код: plaintext 1. Тут семантика меняется, не смотря на то, что в принципе функция делает то же самое, и всё становится сильно легче, потому что полиморфизм идёт только по первому и единственному аргументу. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2017, 13:27 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
kealon(Ruslan)SashaMercury, Параллельное наследование насколько мне известно не реализовано ещё ни в одном языке к сожалению. Всё ложится на плечи программиста на уровне "я знаю что класс А всё таки класс Б" Скорее всего, ты и имеешь в виду множественную диспетчеризацию, а не "параллельное наследование". ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2017, 13:49 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
MasterZivkealon(Ruslan)SashaMercury, Параллельное наследование насколько мне известно не реализовано ещё ни в одном языке к сожалению. Всё ложится на плечи программиста на уровне "я знаю что класс А всё таки класс Б" Скорее всего, ты и имеешь в виду множественную диспетчеризацию, а не "параллельное наследование". нет, именно то, что SashaMercury заметил в С++ оно не особо критично, так как виртуальнных конструкторов всё равно нема архитектурно проблема появляется, например, так: есть контейнер определённых объектов (можно для усложения к этим объектам добавить ссылку на контейнер) у этого контейнера да и у объектов есть виртуальные методы в потомке этого контейнера нужно: расширить дочерние объекты новой функциональностью довольно часто нужно обращаться к новым методам контейнера из объекта и наоборот, а описания у нас имеют базовые типы - пришли к проблеме постоянно каста kealon(Ruslan)"я знаю что класс А всё таки класс Б" ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2017, 22:33 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
MasterZivнет, это не так. можно программировать вообще без виртуальных функций, на шаблонном полиморфизме, на современном С++ еще на лямбдах, и чем новее версия языка, тем более он нас к этому стимулирует. Ну и гвозди можно микроскопом забивать, но молотком удобнее. А интерфейсы реализовывать удобнее всего с помощью виртуальных функций. MasterZivВиртуальные функции нужны только когда у вас в программе есть иерархии классов. Иерархии (помимо реализации интерфейсов) в правильно спроектированной программе не нужны. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2017, 22:59 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyMasterZivнет, это не так. можно программировать вообще без виртуальных функций, на шаблонном полиморфизме, на современном С++ еще на лямбдах, и чем новее версия языка, тем более он нас к этому стимулирует. Ну и гвозди можно микроскопом забивать, но молотком удобнее. А интерфейсы реализовывать удобнее всего с помощью виртуальных функций. MasterZivВиртуальные функции нужны только когда у вас в программе есть иерархии классов. Иерархии (помимо реализации интерфейсов) в правильно спроектированной программе не нужны. Это заявление эквивалентно тому, что Duck Typing - необходимая и достаточная на все случаи жизни. Не согласен, инкапсуляция данных тоже важна. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2017, 23:46 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
kealon(Ruslan)MasterZivпропущено... Скорее всего, ты и имеешь в виду множественную диспетчеризацию, а не "параллельное наследование". нет, именно то, что SashaMercury заметил в С++ оно не особо критично, так как виртуальнных конструкторов всё равно нема архитектурно проблема появляется, например, так: есть контейнер определённых объектов (можно для усложения к этим объектам добавить ссылку на контейнер) у этого контейнера да и у объектов есть виртуальные методы в потомке этого контейнера нужно: расширить дочерние объекты новой функциональностью довольно часто нужно обращаться к новым методам контейнера из объекта и наоборот, а описания у нас имеют базовые типы - пришли к проблеме постоянно каста kealon(Ruslan)"я знаю что класс А всё таки класс Б" нафига тебе контейнер с полиморфными методами? ну да, иногда нужно что-то настраивать в алгоритмах, но виртуальные методы - не единственный способ это сделать. C++ - не Ява, тем он и хорош, что можно делать по-разному. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.02.2017, 01:21 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
MasterZivнафига тебе контейнер с полиморфными методами? ну да, иногда нужно что-то настраивать в алгоритмах, но виртуальные методы - не единственный способ это сделать. C++ - не Ява, тем он и хорош, что можно делать по-разному. да как бы обычные практические задачи, вполне конечно можно обходить с помощью генериков или метапрограммирования но в данном случае это явная недоработка, которая мешает компонентному использованию ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.02.2017, 07:48 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
kealon(Ruslan)MasterZivнафига тебе контейнер с полиморфными методами? ну да, иногда нужно что-то настраивать в алгоритмах, но виртуальные методы - не единственный способ это сделать. C++ - не Ява, тем он и хорош, что можно делать по-разному. да как бы обычные практические задачи, вполне конечно можно обходить с помощью генериков или метапрограммирования но в данном случае это явная недоработка, которая мешает компонентному использованию и часто ты наследуешься от контейнеров и что-то там переопределяешь? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.02.2017, 23:08 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
У меня возник еще один вопрос, и он должен был быть раньше того, что я спрашивал выше. 0. Модель размещения производного объекта в памяти на 1982 год (думаю, что и сейчас не сильно изменилась) заключалась в объединении его собственных членов и членов базового класса. Anatoly MoskovskySashaMercury, 1) Когда я вижу a.xxx или a->xxx то я ожидаю, что вызовется xxx именно у того класса, на экземпляр которого указывает a (или сам им является). В С++ это так и есть для полей и виртуальных функций. А для обычных функций класса - нет, даже если наследник переопределил функцию. Вы, судя по всему, говорите об этом Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. Но это скорее агрегация. И если поведение выше кажется логичным, то какое адекватное поведение в 1982 Bjarne мог ожидать от такого? Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. И это выглядит так, будто агрегация и наследование перемешаны. Потому, и не только потому, но и в целом, почему BS не сделал все методы виртуальными по умолчанию? Если метод будет переопределен в производном классе, то именно это определение фактически будет использовать для объектов данного класса. В том случае, когда не существует возможность представить реализацию конкретного метода в базовом классе, можно, например, использовать инструкцию аналогичную для чисто виртуальных функций. Если можно, приведите пожалуйста пример, где реализация виртуальных функций в таком формате была бы плохим решением. Наверняка тут есть подводные камни ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.02.2017, 15:43 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
И странно, что абстрактные классы не появились сразу, к выходу Cfront 1.0 в 1985. Ведь BS приводит такой пример в 1982, где очевидно, что они нужны (в качестве базового используется класс Shape, виртуальные методы draw(), rotate()) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.02.2017, 15:53 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
SashaMercuryпочему BS не сделал все методы виртуальными по умолчанию? Производительность. Вызов виртуального метода это как минимум два лишних обращения к случайному участку памяти. Кэши процессора не резиновые, а тогда их вообще не было. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.02.2017, 16:26 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
Dimitry SibiryakovSashaMercuryпочему BS не сделал все методы виртуальными по умолчанию? Производительность. Вызов виртуального метода это как минимум два лишних обращения к случайному участку памяти. Кэши процессора не резиновые, а тогда их вообще не было. Почему ДВА и почему к СЛУЧАЙНОМУ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.02.2017, 05:21 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
MasterZivПочему ДВА В случае вызова виртуальной функции: чтение указателя vtable (RAM) ->чтение адреса функции (RAM)->выполнение маш. команды call Вызов обычной функции: выполнение маш. команды call без чтения RAM (адрес функции - внутри команды) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.02.2017, 05:45 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
Anatoly Moskovsky, Указатель vtable лежит с данными объекта. Так что на кэш не повлияет, если объект нетривиальный, т.е. работает со своими мемберсами. Так что лишней можно считать одну операцию. Не стоит также забывать, что оптимизатор может производить невиртуальный вызов виртуальных ф-ций. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.02.2017, 09:27 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
SiemarglТак что лишней можно считать одну операцию. Считать можно что угодно, но операций там две ))) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.02.2017, 23:09 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyСчитать можно что угодно, но операций там две ))) "лишняя" - одна ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.02.2017, 23:24 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
Изопропил"лишняя" - одна Anatoly MoskovskyВ случае вызова виртуальной функции: чтение указателя vtable (RAM) ->чтение адреса функции (RAM)->выполнение маш. команды call Вызов обычной функции: выполнение маш. команды call без чтения RAM (адрес функции - внутри команды) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.02.2017, 23:55 |
|
||
|
К виртуальным функциям
|
|||
|---|---|---|---|
|
#18+
Dimitry SibiryakovЛично я бы ожидал, что ошибка компиляции возникнет ещё раньше, когда идёт переопределение метода с другой сигнатурой.по идее, explicit решает эту проблему MasterZivКстати, я видел в сети предложение в стандарт для реализации в С++ множественной диспетчеризации в виртуальных методах, вот это была бы бомба!А можно подробнее описать, что это? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.02.2017, 05:40 |
|
||
|
|

start [/forum/topic.php?fid=57&tid=2018245]: |
0ms |
get settings: |
9ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
44ms |
get topic data: |
11ms |
get forum data: |
3ms |
get page messages: |
53ms |
get tp. blocked users: |
2ms |
| others: | 15ms |
| total: | 158ms |

| 0 / 0 |
