Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.52/25: Рейтинг темы: голосов - 25, средняя оценка - 4.52
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826

Вызов виртуального метода в конструкторе

07.10.2015, 18:20. Показов 5238. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Помню расматривался этот вопрос на форуме - хочу освежить память почему при вызове виртуального метода внутри конструктора UB
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
07.10.2015, 18:20
Ответы с готовыми решениями:

Вызов виртуального метода при создании
Добрый вечер, библиотека навязала следующее поведение: - объект создан и валиден, если выделена память, вызван конструктор и...

Вызов виртуального метода класса наследника из вектора
#include <iostream> #include <vector> using namespace std; class A { public: virtual void print() { cout << "A" <<...

Вызов виртуального метода базового класса из указателя производного
Допустим есть такой код: #include <iostream> class Base { public: virtual void f() { std::cout << "Base\n"; } ...

12
202 / 138 / 88
Регистрация: 21.12.2014
Сообщений: 369
07.10.2015, 18:50
Ссылка по теме: http://www.e-reading.club/chap... e_CPP.html
1
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.10.2015, 19:39
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
почему при вызове виртуального метода внутри конструктора UB
я конечно может быть ошибаюсь, но вроде бы нет никакого UB.

объект считается построенным тогда, когда полностью отрабатывает его конструктор.
который включает в себя конструкторы базовых классов, и конструкторы членнов-данных.

и пока конструктор ещё не отработал до конца, объект считается не построенным.
а поскольку базовые конструкторы всегда вызываются первее, чем конструторы потомка,
то имеем ситуацию: на момент работы контруктора, потомка ещё не существует.
его конструктор ещё даже не начал запускаться.


а поскольку нельзя запустить метод того, чего ещё не существует,
то при вызове виртуальной функции-члена,
происходит вызов функции-члена этого же класса,
а не класса наследника.

этот фактор создает иллюзию, что якобы на период действия конструктора,
полиморфизм вообще не работает.

на самом деле работает.
просто наследника ещё не существует,
и поэтому скрытый указатель на таблицу виртуальных фуункций
настроен на базовый класс, а не на класс наследника.
1
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
07.10.2015, 19:49  [ТС]
Цитата Сообщение от hoggy Посмотреть сообщение
я конечно может быть ошибаюсь, но вроде бы нет никакого UB
так я в ступоре из-за этого. Вот есть проблески, что при каких-то действиях возможет вызов виртуального метода без реализации, что приведёт к UB - следовательно всю механику обозначили как UB.

Или я путаю с чем-то ... (
0
Неэпический
 Аватар для Croessmah
18146 / 10730 / 2066
Регистрация: 27.09.2012
Сообщений: 27,029
Записей в блоге: 1
07.10.2015, 19:53
Лучший ответ Сообщение было отмечено rikimaru2013 как решение

Решение

Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Вот есть проблески, что при каких-то действиях возможет вызов виртуального метода без реализации, что приведёт к UB - следовательно всю механику обозначили как UB.
10.4
6. Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call (10.3) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined.
1
 Аватар для OstapBender
594 / 532 / 76
Регистрация: 22.03.2011
Сообщений: 1,585
07.10.2015, 19:53
по-моему там работает простое правило: вируальный метод вызываемый в конструкторе трактуется как обычный (не виртуальный)
1
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
07.10.2015, 20:01  [ТС]
При вызове деструктора
C++
1
A* ptr = new C(); delete ptr; // при C -> B- > A
Вызовется
C++
1
2
3
4
ptr->_(*(_vfptr + смещение_до_деструктора));
// тот в свою очередь вызовет 
B::~B(); 
A::~A();
Разве вызывая виртуальный метод в деструкторе ~B::, мы не имеет на момент вызова __vfptr значение указателя с указанием на адресс таблици класса С, которая будет вызывать свои методы переопределённые: в которых возможно обращение к полям которых уже нету (так как ~C:: отработал)
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.10.2015, 20:09
Лучший ответ Сообщение было отмечено rikimaru2013 как решение

Решение

Цитата Сообщение от rikimaru2013 Посмотреть сообщение
следовательно всю механику обозначили как UB.
если так, тогда весь полиморф можно назвать одним большим UB.
потому что вызвать чисто-виртульную функцию без туловища - как нефиг нафиг.

кстати, обратите внимание:
Цитата Сообщение от hoggy Посмотреть сообщение
этот фактор создает иллюзию, что якобы на период действия конструктора,
полиморфизм вообще не работает.
Цитата Сообщение от OstapBender Посмотреть сообщение
о-моему там работает простое правило: вируальный метод вызываемый в конструкторе трактуется как обычный (не виртуальный)
Добавлено через 3 минуты
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
При вызове деструктора
аналогично с конструкторами:

первыми разрушаются потомки, потом предки.
когда отрабатывает диструктор потомка,
он перестает существовать.
и указатель на vtbl модифицируется,
указывая на ещё остающуюся в живых часть предка.

соотвественно, на момент работы диструктора базового класса,
в живых остается только сам базовый объект, и его предки.
а вот потомков уже не существует.

и как я уже писал выше - нельзя позвать то, чего не существует.
1
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
07.10.2015, 20:11  [ТС]
Пока работает конструктор Base, инициализируя базовую часть объекта Derived, этот объект относится к типу Base. Именно так его воспринимают все части C++, и в этом есть смысл: части объекта, относящиеся к Derived, еще не инициализированы, поэтому безопаснее считать, что их не существует вовсе. Объект не является объектом производного класса до тех пор, пока не начнется исполнение конструктора последнего. То же относится и к деструкторам
Понравилась фраза
Объект не является объектом производного класса до тех пор, пока не начнется исполнение конструктора последнего. То же относится и к деструкторам
Если они верна - возьму на вооружение. Раставила все точки...


Цитата Сообщение от hoggy Посмотреть сообщение
когда отрабатывает диструктор потомка,
он перестает существовать.
и указатель на vtbl модифицируется
Спасибо, потому что гуглил __vfptr и на msdn кратко про него " ... инициализация происходит в контрукторе класса". Проверил VS2013 - в списке инициализации, если вызвать виртуальный метод и в самом конструкторе, то vfptr уже с новыми значениями. Тоесть при входе в список инициализации класса B - он уже проиничен таблицей данного класса
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.10.2015, 20:24
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Понравилась фраза
только не "начнется", а "завершиться":

Объект не является объектом производного класса до тех пор,
пока не завершиться исполнение его конструктора
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
07.10.2015, 20:30  [ТС]
Цитата Сообщение от hoggy Посмотреть сообщение
только не "начнется", а "завершиться":
тогда почему
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
using namespace std;
 
class A
{
 
};
class B : public A
{
public:
    B()
    {
        cout << (dynamic_cast<B*>(this) != nullptr) << endl;
    }
};
 
int main()
{
    A* a = new B();
}
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.10.2015, 20:36
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
тогда почему
потому что не гарантируется.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9006 / 4707 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
07.10.2015, 20:58
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
cout << (dynamic_cast<B*>(this) != nullptr) << endl;
а кастить зачем?
https://www.cyberforum.ru/post4983727.html
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
07.10.2015, 20:58
Помогаю со студенческими работами здесь

Переопределение виртуального метода
Нужно написать виртуальный метод в родительском классе , который находит площадь круга. Затем переопределить этот виртуальный метод в...

Реализация виртуального метода в двух классах-наследниках
Здравствуйте! Есть три класса, абстрактный CGraphicsObject, и два его наследника Circle и Parallelogram В CGraphicsObject содержится...

Автоматический вызов функций в конструкторе
В общем друзья, надо разобраться как можно в конструкторе объекта класса, автоматически вызывать функции, переопределенные этим классом. ...

Почему при переопределении виртуального метода в производном классе выводится метод базового?
Всем добра! Помогите разобраться почему при переопределении виртуального метода в производном классе выводится метод базового ? По идеи...

Преобразование типа при вызове виртуального метода через указатель на базовый класс
Доброго времени суток. Наткнулся на вот такой вопрос в сети и пока что не смог на него ответить, может быть у Вас получится: В каких...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru