我对虚函数或更好的说法有一些疑问,我们可以说运行时多态性。据我说,我假设它的工作方式如下,
将为每个具有至少一个虚拟成员函数的类创建一个虚拟表(V-Table)。我相信这是静态表,因此它是为每个类而不是为每个对象创建的。如果我在这里错了,请纠正我。
这个 V-Table 有虚函数的地址。如果类有 4 个虚函数,那么这个表就有 4 个条目指向对应的 4 个函数。
编译器将添加一个虚拟指针(V-Ptr)作为该类的隐藏成员。这个虚拟指针将指向虚拟表中的起始地址。
假设我有这样的程序,
class Base
{
virtual void F1();
virtual void F2();
virtual void F3();
virtual void F4();
}
class Der1 : public Base //Overrides only first 2 functions of Base class
{
void F1(); //Overrides Base::F1()
void F2(); //Overrides Base::F2()
}
class Der2 : public Base //Overrides remaining functions of Base class
{
void F3(); //Overrides Base::F3()
void F4(); //Overrides Base::F4()
}
int main()
{
Base* p1 = new Der1; //Believe Vtable will populated in compile time itself
Base* p2 = new Der2;
p1->F1(); //how does it call Der1::F1()
p2->F3(); //how does it call Base::F3();
}
如果 V-Table 在编译时填充,为什么将其称为运行时多态性?请使用上面的示例向我解释有多少 vtable 和 vptr 以及它是如何工作的。根据我的说法,Base、Der1 和 Der2 类将有 3 个 Vtable。在 Der1 Vtable 中,它有自己的 F1() 和 F2() 地址,而对于 F3() 和 F4(),地址将指向 Base 类。此外 3 Vptr 将作为隐藏成员添加到 Base、Der1 和 Der2 类中。如果一切都是在编译时决定的,那么在运行时究竟会发生什么?如果我的概念有误,请纠正我。