2015-01-05 5 views
1

По моему мнению, VTable необходим для вызова самой производной версии функции. У него будут записи о самой производной версии функции ... Мое сомнение в том, почему нам нужен VTable для базового класса. Поскольку выполнение вызовов с базовым объектом всегда необходимо вызвать функции базового класса.C++, почему базовому классу нужен VTable

+1

Vtable - это деталь реализации; какую реализацию вы используете? (GCC, Microsoft, Clang и т. Д.) И почему вы говорите, что базовому классу нужен один? –

+0

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

ответ

1

Поскольку R Shau не понравилось мое редактирование, я даю свой ответ высоко, основываясь на его.

VTable - это способ борьбы с полиморфизмом. Хотя VTable - это метод, широко используемый компиляторами C++, они могут предоставить любое другое решение.

Если базовый класс имеет одну или несколько функций-членов virtual, конструктор базового класса присваивает VTable объекту.

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

Пример:

struct Base 
{ 
    Base() {} 

    virtual void m() {} 

    virtual ~Base() {} 
}; 

struct Derived : public Base 
{ 
    Derived() : Base() {} 

    void m() {} 

    ~Derived() {} 
}; 

void foo() 
{ 
    Base b; 
    Derived d; 

    Base * bPtr; 
} 

bPtr может указывать на Base

bPtr = & b; 
    bPtr->m(); 

или Derived

bPtr = & d; 
    bPtr->m(); 

Поскольку bPtr имеет тип Base *, как выполнить вызов полиморфного bPtr->m(), что должно привести к вызову Base::m(), если bPtr указывает на b и Derived::m(), если bPtr указывает на d? Ответ: найдите адрес m() метода в VTable.

Что происходит при решении bPtr->m() что-то вроде этого:

bPtr pointing to Base object 
    bPtr-> vtable_pointer -> VTable of Base -> m() -> points to address of Base::m() 

    bPtr pointing to Derived object 
    bPtr-> vtable_pointer -> VTable of Derived -> m() -> points to address of Derived::m() 

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

+0

Твердое объяснение .. Спасибо – senjes

0

Если базовый класс имеет одну или несколько функций-членов virtual, конструктор базового класса присваивает VTable объекту.

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

Пример:

struct Base 
{ 
    Base() {} 
    virtual ~Base() {} 
}; 

struct Derived : public Base 
{ 
    Derived() : Base() {} 
    ~Derived() {} 
}; 

void foo() 
{ 
    Base b; 
    Derived d; 
} 

Base::Base() вызывается непосредственно в строке

Base b; 

Она вызывается косвенно, через Derived::Derived() в линии

Derived d; 

Как реализация Base знать, Base::Base() вызывается непосредственно для Base или косвенно для Derived? Без этого знания он должен убедиться, что это поведение работает для обоих из них - это означает, что для них есть VTable.

+0

vtable - это подробности реализации, но я думаю, что это вряд ли будет ** построено ** конструктор базового класса. – doc

+0

@doc, что лучше построить vtable? –

+0

перед входом в основной()? во время компиляции? – doc

Смежные вопросы