C ++ дочерний конструктор и VPTR

Во многих источниках книги и т. Д. Написаны «не вызывайте this-> virtualFunction в конструкторе дочернего класса», а в некоторых источниках объясняют, почему вы не должны этого делать. Потому что на момент строительства класс вообще не создан. Таким образом, виртуальная функция, которая будет вызываться из дочернего конструктора, будет функцией базового класса. Это означает, что в теле дочернего конструктора VPTR этого класса указывалось на базу VTABLE.

Итак, мой вопрос,
Какой момент в построении объекта, когда VPTR дочернего класса будет переопределен для обращения к его виртуальной таблице? Я предполагаю, что некоторый автоматически сгенерированный код делает это в конце тела конструктора или после того, как тело конструктора будет выполнено.

И второй вопрос,
почему VPTR переопределяется в конце строительства? Может быть, для этого есть несколько важных причин?
Почему нельзя переопределить VPTR в начале тела конструктора или после создания базового класса?

Child::Child() :
Base()
//<----- Why not here?
//members initialization
{
//<----- Why not here?
//code
}

0

Решение

Во многих источниках книги и т. Д. Написаны «не вызывайте this-> virtualFunction в конструкторе дочернего класса»

Я сомневаюсь, что. Часто рекомендуется не вызывать виртуальные функции из база конструктор класса, чтобы избежать путаницы, если вы ожидаете, что они вызовут окончательные переопределения, а не версии базового класса. И вы, конечно, не должны вызывать их из базового класса, если они там чисто виртуальные — это дает неопределенное поведение.

В конструкторе производного класса они четко определены и делают то, что вы ожидаете.

Таким образом, виртуальная функция, которая будет вызываться из дочернего конструктора, будет функцией базового класса.

Нет, во время дочернего конструктора, динамический тип Childи вызовы виртуальных функций будут использовать Child переопределение.

Какой момент в построении объекта, когда VPTR дочернего класса будет переопределен для обращения к его виртуальной таблице?

После того, как все конструкторы базового класса завершены, и до того, как дочерние классы будут инициализированы. Child Функции-члены, включая виртуальные функции, могут вызываться из инициализаторов-членов (но не из инициализаторов базового класса) или из тела конструктора.

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

почему VPTR переопределяется в конце строительства?

Это не так. Это происходит в первой точке, которую вы указываете <----- Why not here?,

1

Другие решения

Я не согласен с вашей чрезмерно упрощенной причиной, по которой вы не должны вызывать виртуальную функцию. Во-первых, VTABLE на самом деле не определяется стандартом C ++ и фактически зависит от реализации:

Когда создается VTable в C ++?

Вызов виртуальной функции из конструктора разрешен стандартом, и на самом деле он должен вызывать правильно в рамках наемного уровня на этом уровне (с некоторыми ограничениями)

Конструкторы C ++: почему этот вызов виртуальной функции небезопасен?
http://www.parashift.com/c%2B%2B-faq-lite/calling-virtuals-from-ctors.html

Однако есть много, много причин, чтобы этого не делать.

  • Конструктор для производного класса еще не был вызван. Любой доступ к любым членам производного класса приведет к неопределенному поведению.
  • Существует эмпирическое правило, что конструкторы должны быть максимально простыми и тупыми. Это связано с тем, что обработка ошибок в конструкторах может быть огромной болью из-за того, что деструктор не вызывается, и единственный способ вернуть состояние чувственной ошибки — вызвать исключение.
  • Это часто нарушает принцип инверсии зависимостей и может пересекать линию деметры, и, как правило, приводит к сильной связи с кодом.
1

По вопросам рекламы [email protected]