Все известные реализации используют vptr, но детали сильно различаются. Vptr - это способ для реализаций представлять тип объекта полиморфного класса (класс с виртуальными функциями), а иногда и классов с виртуальными базовыми классами (очень зависит от реализации).
Обратите внимание, что во многих случаях классы с более чем простым наследованием (одиночное не виртуальное наследование) имеют более одного vptr.
Значение vptr является функцией типа самого производного объекта, созданного.
Тип объекта не может быть изменен пользователем в течение его жизни; во время строительства тип объекта меняется в процессе его строительства; во время разрушения он меняется обратно. (Недопустимо ссылаться на объект во время строительства или разрушения с помощью имени или другого выражения, тип которого не соответствует объекту.)
Вы можете повторно использовать пространство существующего объекта для создания объекта другого типа, но это не тот же объект:
struct X {
A a;
B b;
// requires: construction doesn't throw
};
void replace (X &x) {
x.~X();
B &b = *new (&x) B; // hope no exception here
b.f(); // use as a normal B object
x.f(); // undefined: cannot use x as a real object
X *p = &x; // legal: x isn't used as an object, only as an address
b.~B(); // clean up ressources if needed
new (&x) X; // valid: &x refers to storage, as if a void*
// x refers to a valid X object
}
Такое повторное использование объекта не меняет тип любого существующего объекта: replace(x)
не просто воздействует на x
(оно уничтожает и восстанавливает один), оно действует на место хранения x
, После вызова replace(x)
имя x
может использоваться для ссылки на вновь созданный объект X
, который фактически взял идентификатор ранее существующего объекта X
.
Никакой операции над объектом (которая поддерживает объект в живых) даже не разрешается изменять его тип в C ++. У vptr нет возможности изменить созданный объект.
Изменение типа объявленного объекта разрушило бы систему типов C ++ и инварианты объявленных объектов. Компилятор не будет знать, какой класс уничтожать, какие виртуальные функции вызывать, где находятся базовые классы и т. Д. Это полностью изменит способ работы C ++. Трудно даже представить семантику, связанную с изменением типа существующего объекта.