Во многих источниках книги и т. Д. Написаны «не вызывайте this-> virtualFunction в конструкторе дочернего класса», а в некоторых источниках объясняют, почему вы не должны этого делать. Потому что на момент строительства класс вообще не создан. Таким образом, виртуальная функция, которая будет вызываться из дочернего конструктора, будет функцией базового класса. Это означает, что в теле дочернего конструктора VPTR этого класса указывалось на базу VTABLE.
Итак, мой вопрос,
Какой момент в построении объекта, когда VPTR дочернего класса будет переопределен для обращения к его виртуальной таблице? Я предполагаю, что некоторый автоматически сгенерированный код делает это в конце тела конструктора или после того, как тело конструктора будет выполнено.
И второй вопрос,
почему VPTR переопределяется в конце строительства? Может быть, для этого есть несколько важных причин?
Почему нельзя переопределить VPTR в начале тела конструктора или после создания базового класса?
Child::Child() :
Base()
//<----- Why not here?
//members initialization
{
//<----- Why not here?
//code
}
Во многих источниках книги и т. Д. Написаны «не вызывайте this-> virtualFunction в конструкторе дочернего класса»
Я сомневаюсь, что. Часто рекомендуется не вызывать виртуальные функции из база конструктор класса, чтобы избежать путаницы, если вы ожидаете, что они вызовут окончательные переопределения, а не версии базового класса. И вы, конечно, не должны вызывать их из базового класса, если они там чисто виртуальные — это дает неопределенное поведение.
В конструкторе производного класса они четко определены и делают то, что вы ожидаете.
Таким образом, виртуальная функция, которая будет вызываться из дочернего конструктора, будет функцией базового класса.
Нет, во время дочернего конструктора, динамический тип Child
и вызовы виртуальных функций будут использовать Child
переопределение.
Какой момент в построении объекта, когда VPTR дочернего класса будет переопределен для обращения к его виртуальной таблице?
После того, как все конструкторы базового класса завершены, и до того, как дочерние классы будут инициализированы. Child
Функции-члены, включая виртуальные функции, могут вызываться из инициализаторов-членов (но не из инициализаторов базового класса) или из тела конструктора.
Вы должны быть осторожны, вызывая их от инициализаторов, так как они могут получить доступ к неинициализированным членам. Но в теле конструктора все базовые объекты и члены инициализируются, поэтому они достаточно безопасны.
почему VPTR переопределяется в конце строительства?
Это не так. Это происходит в первой точке, которую вы указываете <----- Why not here?
,
Я не согласен с вашей чрезмерно упрощенной причиной, по которой вы не должны вызывать виртуальную функцию. Во-первых, VTABLE на самом деле не определяется стандартом C ++ и фактически зависит от реализации:
Когда создается VTable в C ++?
Вызов виртуальной функции из конструктора разрешен стандартом, и на самом деле он должен вызывать правильно в рамках наемного уровня на этом уровне (с некоторыми ограничениями)
Конструкторы C ++: почему этот вызов виртуальной функции небезопасен?
http://www.parashift.com/c%2B%2B-faq-lite/calling-virtuals-from-ctors.html
Однако есть много, много причин, чтобы этого не делать.