不,没有这种可能性。vptr
仅从构造函数和析构函数更新。
来自析构函数的更新是出于一个非常具体的原因:确保从类的析构函数内部调用的所有虚函数都A
将调用定义在层次结构中A
或更高层次中的虚函数,而不是来自位于层次结构中较低的类的函数。vptr
基本上,这与在每个构造函数中更新指针的原因相同(对称) 。
例如,在这个层次结构中
struct A {
virtual void foo() { std::cout << "A" << std::endl; }
~A() { foo(); }
};
struct B : A {
virtual void foo() { std::cout << "B" << std::endl; }
~B() { foo(); }
};
struct C : B {
virtual void foo() { std::cout << "C" << std::endl; }
~C() { foo(); }
};
C c;
对象的析构链中的每个析构函数c
都会调用虚函数foo
。C
will callC::foo
的析构函数,will B
call B::foo
(not C::foo
) 的析构函数和A
will call A::foo
(再次,not C::foo
) 的析构函数。之所以会发生这种情况,是因为每个析构函数都显式地将vptr
指针设置为指向其自己类的虚拟表。
相同行为的更复杂的示例可能如下所示
struct A;
extern void (A::*fun)();
struct A {
virtual void foo() { std::cout << "A" << std::endl; }
~A() { (this->*fun)(); }
};
void (A::*fun)() = &A::foo;
struct B : A {
virtual void foo() { std::cout << "B" << std::endl; }
~B() { (this->*fun)(); }
};
struct C : B {
virtual void foo() { std::cout << "C" << std::endl; }
~C() { (this->*fun)(); }
};
C c;
不同的是,这个例子更可能在物理上使用vptr
和虚拟方法表来解析调用。前面的示例通常由编译器优化为对正确的直接非虚拟调用foo
。