在C++中,虚函数的调用是通过虚指针(vptr)和虚表(vtable)来实现的。当一个类含有虚函数时,编译器会为这个类创建一个虚表,虚表中存放着虚函数的地址。同时,编译器会在类的实例中添加一个指向虚表的指针(vptr)。当调用虚函数时,程序会通过对象的vptr找到虚表,然后在虚表中查找并调用相应的虚函数。
以下是虚函数调用的实现过程:
编译器为每个包含虚函数的类创建一个虚表(vtable)。虚表中存放着虚函数的地址,按照虚函数在类中的声明顺序排列。
编译器在类的实例中添加一个指向虚表的指针(vptr)。vptr通常位于对象实例的内存布局的开始位置,这样可以保证访问vptr的代价最小。
当调用虚函数时,首先通过对象的vptr找到虚表。然后在虚表中根据虚函数的索引(即在类中声明的顺序)查找到虚函数的地址。最后,调用找到的虚函数。
以下是一个简单的示例,展示了虚函数调用的实现过程:
#include<iostream>
class Base {
public:
virtual void foo() {
std::cout << "Base::foo()"<< std::endl;
}
};
class Derived : public Base {
public:
void foo() override {
std::cout << "Derived::foo()"<< std::endl;
}
};
int main() {
Base* base_ptr = new Derived();
base_ptr->foo(); // 输出 "Derived::foo()"
delete base_ptr;
return 0;
}
在这个示例中,Base
类包含一个虚函数foo()
,Derived
类重写了这个虚函数。当我们通过Base
类的指针调用foo()
时,程序会通过base_ptr
的vptr找到Derived
类的虚表,然后在虚表中查找并调用Derived::foo()
。