|
37 / 37 / 18
Регистрация: 15.05.2013
Сообщений: 236
|
||||||
Параметры по-умолчанию в виртуальных функциях15.11.2016, 20:37. Показов 3675. Ответов 42
Метки нет (Все метки)
Подскажите, это ведь UB ?
Я понимаю, что при пустом foo() сработал бы вариант из Derived, но вот с добавлением значений по умолчанию хз.
0
|
||||||
| 15.11.2016, 20:37 | |
|
Ответы с готовыми решениями:
42
О виртуальных функциях Значение по умолчанию в функциях Значения по умолчанию в функциях С++ |
|
Неэпический
|
||
| 15.11.2016, 20:45 | ||
Сообщение было отмечено Kant как решение
Решениекомпилятор проставит еще при компиляции, поэтому параметр, заданный по-умолчанию определяется исходя из типа указателя. Как следствие, будет вызван foo из Derived, но с параметром по-умолчанию, заданным в Base.
3
|
||
|
37 / 37 / 18
Регистрация: 15.05.2013
Сообщений: 236
|
|
| 15.11.2016, 20:54 [ТС] | |
|
Croessmah, спасибо, ты как всегда хорошо объяснил. Можешь немного подробнее почему
значение по умолчанию берется исходя из типа указателя. Как-то не ложится это у меня в голове.
0
|
|
|
Неэпический
|
||
| 15.11.2016, 21:15 | ||
Сообщение было отмечено Kant как решение
РешениеВ этом месте derived->foo(); компилятор должен проверить и построить легальный код для вызова. Он прекрасно видит, что есть один вариант foo, который можно использовать таким образом (вызов без указания параметра), и ему нужно здесь передать в функцию аргумент: derived->foo(параметр-заданный-по-умолчанию);Внимание, у нас этап компиляции, компилятору неизвестно какой там реально будет тип в памяти. Поэтому сначала кратенько напомню, что есть статический и динамический типы. Динамический тип - это тип того объекта, который непосредственно будет создан и лежать в памяти, т.е. в нашем случае это объект типа Derived. Статический тип - это тип выражения, который определяется в результате анализа программы без учета выполнения семантики. В нашем случае в выражении derived->foo(); derived - это указатель на объект типа Base. То, что в памяти при derived->foo(); окажется объект типа Derived будет известно только во время выполнения, Во время компиляции же компилятору здесь вообще не может быть известно, какой реально тип имеет объект, на который указывает derived, но код вызова он построить должен, так что у него нет другого выбора, кроме как взять параметр по-умолчанию исходя из статического типа, и впихнуть его сюда т.е. параметр будет взят из Base::foo, и будет построен код аналогичный derived->foo(42);.
9
|
||
|
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
|
||
| 15.11.2016, 21:38 | ||
|
0
|
||
|
Неэпический
|
|||
| 15.11.2016, 21:43 | |||
|
Не по теме:
если всё равно не верите прочитанному? - Я ему не верю, но всё равно буду читать бред, который он пишет.:D Добавлено через 3 минуты который в C++ реализуется с помощью виртуальных функций. И вот как раз если бы язык был динамически типизируемый, то параметры бы брались уже во время выполнения, но увы. Да и виртуальные функции тогда были бы не нужны.
1
|
|||
|
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
|
|
| 15.11.2016, 21:56 | |
|
Croessmah, я только прицепился к слову "динамический тип". Меня вирт методы в С++ весьма доставляют)) По моей логике, тип то один T* - и меняется только поведение.Как там пишут "один интерфейс - множество реализаций". Взглянув на Foo* fn(), я точно знаю, что там тип Foo* - а то что поведение будет зависеть от наличие полиморфизма - это уже детали реализации на которые программист не обращает внимание. Пишите код и думаете о всех последствиях полиморфного вызова? Нет. Вы точно знаете по названию метода и возвращаемому значению, что произойдет. А будет это под музыку, или по-пьяне - это уже детали чёрного ящика.
0
|
|
|
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
|
||||
| 16.11.2016, 00:00 | ||||
|
Добавлено через 1 минуту Добавлено через 7 минут
0
|
||||
|
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
|
||
| 16.11.2016, 00:32 | ||
Т* можно чётко сказать, какие методы можно вызвать - других там нету и не будет.
0
|
||
|
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
|
||
| 16.11.2016, 01:21 | ||
|
0
|
||
|
Комп_Оратор)
|
|||||||
| 16.11.2016, 01:27 | |||||||
|
В связи с этим вопрос. Получается, что параметр по умолчанию, это грабли для ленивых? Ведь если перегрузить явно, то проблем не возникает?
0
|
|||||||
|
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
|
|||
| 16.11.2016, 01:37 | |||
auto тип будет определён однозначно ведь. Думаю вы прибегаете к термину "динамический тип", который описали выше. Но мне эта "динамика" больше напоминает поведение, чем физический свойства. Добавлено через 1 минуту
1
|
|||
|
Комп_Оратор)
|
||
| 16.11.2016, 01:46 | ||
|
Я всегда думал, что если при вызове шаблона вариант кода определяется на стадии компиляции, то при вызове виртуального метода на указателе базового класса, компилятор вынужден генерировать все ветви исполнения ( с любыми наследниками, и в.т.ч. базового (если он не абстрактный)). А фактический вызов в рантайме это переход на ветвь которая определяется по скрытому логическому блоку анализирующему RTTI. То есть, нет в действительности, динамического типа. Так мне казалось. А сейчас что-то не могу переварить увиденное. Нужно время и чтиво. Видимо работа с в-методами через в-тэйбл не вошли в мой тэйбл до конца.
0
|
||
|
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
|
||
| 16.11.2016, 01:52 | ||
|
0
|
||
|
Комп_Оратор)
|
||
| 16.11.2016, 01:59 | ||
1
|
||
|
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
|
||
| 16.11.2016, 02:07 | ||
|
тип объекта на который он ссылается. Поэтому я не путаю. Возможность потомков записать себя в указатель на родительский класс, это свойство от наследование. При этом компилятор всем сердцем верит, что там объект типа Base* и явно вам будет об этом говорить на протяжении всего программирования. После компиляции нету уже понятия тип и только адрес и операции. Еще раз) Имея указатель T*, мы имеем именно адрес на объект типа Т. То, что этотобъект наделён полиморфным свойством от Полиморфизма за счёт определённых действий, не в коем случаи не говорит нам, что мы можем получить с указателя Т*, что-тодругое. Разименнуем указатель, который имеет другой "динамический" тип получим по факту славную срезку со всеми вытекающими. Во вторых, при работе с вирт методами будет механизм позднего связывания. А во всем другом - этот указатель ничем не отличается от других которые "действительно" указывают на Base*. Заметьте я специально взял слово действительно в кавычки, потому что все указатели T* хранят адрес на объект типа ТP.S. Пишу как hoggy, спорю со всеми как hoggy, вот бы еще знаний и опыта как у него) А то пока с моими 19 месяцами в С++ - спорить аргументировано на некоторые темы тяжело )
0
|
||
|
Неэпический
|
|||||||||
| 16.11.2016, 02:19 | |||||||||
Сообщение было отмечено Kant как решение
Решениеptr->foo() и ptr->foo(42)приведут к вызову разных виртуальных функций. Собственно, всё это можно "на пальцах" описать на другом примере:
можно рассказать немного о раннем и позднем связывании. Упростим всё донельзя. Компилятор всегда строит код основываясь на статических типах. Вопрос лишь в том, как именно он его построит. Раннее связывание - заранее известно что и как будет, связывание произойдет во время компиляции. Позднее связывание - заранее неизвестно что к чему и связывание произойдет во время выполнения. Но код и для того и для другого строится всё равно при компиляции. Смотрим на код выше (описываю немного не по порядку). Вызов в строке "П1" - pObj->foo(10);.Функция-член foo не виртуальная, поэтому будет использовано раннее связывание. Компилятор возьмет и пропишет код вызова Base::foo с заданным параметром, независимо от того, на что на самом деле указывает указатель. Вызов в строке "П3" - pObj->zoo();.В классе Derived функция-член zoo виртуальная. Однако компилятор ничего не знает о динамическом типе объекта, на который указывает указатель pObj. В классе Base функция-член zoo не виртуальная, поэтому компилятор, основываясь на статическом типе, делает раннее связывание, строя код для вызова Base::zoo. Вызов в строке "П2" - pObj->bar();.У нас же нет функции-члена bar без параметров. Зато в Base::foo есть параметр, заданный по-умолчанию, поэтому этот вызов будет легальным, если преобразовать его в pObj->bar(значение).Вызов нужно построить уже сейчас. А это значит, что нужно использовать раннее связывание для параметров. Всё что у нас есть - указатель на Base. Поэтому компилятор, основываясь на статическом типе, считает, что работает с объектом типа Base и впихивает 42. Теперь он может построить вызов pObj->bar(42).Функция-член Base::bar виртуальная, это заставляет компилятор использовать уже позднее связывание для вызова, а это совершенно другая тактика построения кода. Он может построить команды так: 1) взять в первых байтах объекта указатель на таблицу виртуальных функций, 2) пройти по адресу в указателе, и вызвать из этой таблицы функцию, соответствующую bar(int). Псевдокод: ((vptr_t*)pObj))->bar_addr(42);Таким образом и получаем, что связывание виртуальных функций будет поздним, а их параметров - ранним. Конечно, можно было организовать и позднее связывание параметров, но для этого пришлось бы городить еще один огород с таблицами. А так ли оно нужно? Да врядли оно настолько востребовано. Просто нужно понимать что делаешь и тогда проблем не будет. ![]() Добавлено через 7 минут Извини, но объяснять - это не моё.
7
|
|||||||||
|
Комп_Оратор)
|
||
| 16.11.2016, 02:20 | ||
|
А механизм v-table работает независимо от типа и в этом вторая половинка магии "динамической" типизации. Но вот, оказывается, что когда явно перегружен метод без аргумента, то v-table содержит их 2-штуки и у компилятора есть достаточно информации для вызова. А вот если используется аргумент по умолчанию, то различие аргументов нигде нельзя отметить, - нет для них места в v-table. И получается логический сбой! Это очень интересный момент. Жаль, что это компилируется, мне кажется.
0
|
||
| 16.11.2016, 02:20 | |
|
Помогаю со студенческими работами здесь
20
Формальные и фактические параметры в процедурах и функциях Как в JavaScript передаются параметры в функциях? По ссылке или по значению.
Параметры по умолчанию в С. Параметры по умолчанию в функции Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
|
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/
O1rJuneU_ls
https:/ / vkvideo. ru/ video-115721503_456239114
|
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ВВЕДЕНИЕ
Введу сокращения:
аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
|
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi
ветка по-частям.
коммит Create переделка под биомассу. txt
вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
|
|
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ *
Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях.
Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её.
Последовательность действий:. . .
|
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
|
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение.
И на уровне агентов добавится между грибами или бактериями взаимодействий.
До того я пробовал подход через многомерные массивы,. . .
|
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Налог на собак: https:/ / **********/ gallery/ V06K53e
Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf
Пост отсюда. . .
|