2011-07-06 1 views
5

Речь идет не о "When VTABLE is created?". Скорее, когда VPTR должен быть инициализирован? Это в начале/конце конструктора или до/после конструктора?Когда инициализация vptr (указывающая на vtable) инициализируется для полиморфного класса?

A::A() : i(0), j(0) -->> here ? 
{ 
    -->> here ? 
    //... 
    -->> here ? 
} 

ответ

14

Аппарат для виртуальных вызовов (обычно это v-стол, но не обязательно) настраивается во время ctor-initializer, после создания базовых подобъектов и до построения элементов. Раздел [class.base.init] декреты:

Функции-члены (в том числе функции виртуальных элементов, 10.3) могут быть вызваны для строящегося объекта. Аналогичным образом, строящийся объект может быть операндом оператора typeid (5.2.8) или dynamic_cast (5.2.7). Однако, если эти операции выполняются в ctor-инициализаторе (или в функции, вызываемой прямо или косвенно из ctor-initializer ) до того, как все инициализаторы для базовых классов завершили, результат операции не определено.

Фактически, при построении базовых подобъектов существует механизм виртуальных функций, но он настроен для базового класса. Раздел [class.cdtor] говорит: ]

Функции членов, включая виртуальные функции (10.3), могут быть вызваны во время строительства или уничтожения (12.6.2). Когда виртуальная функция вызывается прямо или косвенно из конструктора или из деструктора, в том числе при построении или уничтожении нестатических элементов данных класса, и объектом, к которому применяется вызов, является объект (назовите его x) под строительство или разрушение, вызванная функция является окончательным переадресатором в классе конструктора или деструктора, а не одним переопределением его в более производном классе. Если вызов виртуальной функции использует явный член класса (5.2.5), а выражение объекта ссылается на полный объект x или на один из подобъектов базового класса этого объекта, но не на x или на один из его субобъектов базового класса, поведение не определено ,

+0

Doe s это означает, что 'vptr' будет изменяться каждый раз, когда построены базовые подобъекты, если существует много уровней деривации? – fengqi

2

он инициализируется между конструкторами базы и производных классов:

class Base { Base() { } virtual void f(); }; 
class Derived { Derived(); virtual void f(); }; 

Это происходит, когда сырье памяти преобразуется в объект базы. Это происходит, когда базовый объект преобразуется в объект Derived во время построения объекта. То же самое происходит в обратном порядке при уничтожении объекта. То есть каждый раз при изменении типа изменяется указатель vtable . (Я уверен, что кто-то замечает, что vtables не нужно существовать в соответствии со стандартом std ..)

0

This msdn article explains it in great detali

Там говорится:

"И последний ответ ... как можно было ожидать Это происходит в конструкторе.."

поэтому ..
A :: A(): i (0), j (0)
{
- >> здесь!
// ...
//
}

Но будьте осторожны, скажем, у вас есть класс А и класс A1, полученный из А.

  • Если вы создаете новый объект, vptr будет установлен в самом начале конструктора класса а
  • Но если вы должны были создать новый объект A1:

«Вот вся последовательность событий, когда вы создаете экземпляр класса A1:

  1. A1 :: A1 вызывает A ::
  2. A :: A устанавливает виртуальные таблицы к А в виртуальные таблицы
  3. A: : A и возвратил
  4. A1 :: A1 устанавливает виртуальные таблицы на таблицу
  5. A1 :: A1 выполняется и возвращает A1 в "
+1

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