所有已知的实现都使用 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++ 的工作方式。甚至很难想象与更改现有对象的类型相关的语义。