Date Редакция Категория comp Теги Cpp

Объект в С++ представляет собой непрерывный участок памяти. Указатель на такой объект содержит адрес этого участка. Когда вызывается метод объекта, этот вызов транслируется в вызов обычной функции, содержащей дополнительный аргумент — указатель на объект. Например,

ClassName *object;
object->method(5);

преобразуется в

ClassName_method(object, 5);

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

Рассмотрим следующие классы:

Class A
{
public:
    int a;
    virtual void f(int);
    virtual void g(int);
    virtual void h(int);
};

Class B : public A
{
public:
    int b;
    virtual void g(int);
};

Class C : public B
{
public:
    int c;
    virtual void h(int);
};

Объект класса С выглядит примерно так:

vtbl.png

Если класс А содержит виртуальный метод и этот метод замещен в подклассе В, то адрес первоначального метода заменяется адресом нового метода в таблице vtbl. То же самое происходит и при замещении методов из B методами класса C.

Компилятор преобразует вызов виртуального метода в косвенный вызов через vtbl. Например

C *pc = new C;
pc->g(2);

преобразуется в

(*(pc->vptr[1]))(pc, 2);

Итак, когда вы делаете любой метод виртуальным, компилятор вставляет внутрь класса указатель vptr на таблицу виртуальных методов vtbl. В результате, размер класса увеличивается на 4 байта (для 32-разрядных платформ). Виртуальная таблица vtbl является статическим массивом указателей на функции (методы). Поэтому различные экземпляры класса, содержащего виртуальный метод, используют общую виртуальную таблицу.

Что читать:

  1. Ellis M.A., Stroustrup B. The Annotated C++ Reference Manual, Addison-Wesley Professional, 1990, c. 227.
  2. Вайнер Р., Пинсон Л. C++ изнутри, ДиаСофт, 1993, с. 202.


Комментарии

comments powered by Disqus