Объект в С++ представляет собой непрерывный участок памяти. Указатель на такой объект содержит адрес этого участка. Когда вызывается метод объекта, этот вызов транслируется в вызов обычной функции, содержащей дополнительный аргумент — указатель на объект. Например,
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
. То же самое происходит и при замещении методов из B методами класса C.
Компилятор преобразует вызов виртуального метода в косвенный вызов через vtbl
. Например
C *pc = new C;
pc->g(2);
преобразуется в
(*(pc->vptr[1]))(pc, 2);
Итак, когда вы делаете любой метод виртуальным, компилятор вставляет внутрь класса указатель vptr
на таблицу виртуальных методов vtbl
. В результате, размер класса увеличивается на 4 байта (для 32-разрядных платформ). Виртуальная таблица vtbl
является статическим массивом указателей на функции (методы). Поэтому различные экземпляры класса, содержащего виртуальный метод, используют общую виртуальную таблицу.
Что читать:
- Ellis M.A., Stroustrup B. The Annotated C++ Reference Manual, Addison-Wesley Professional, 1990, c. 227.
- Вайнер Р., Пинсон Л. C++ изнутри, ДиаСофт, 1993, с. 202.
Комментарии
comments powered by Disqus