在C++中,基类和子类都有自己的虚函数表(vtable),但它们之间的关系和内容有所不同。
1、基类的虚函数表
- 每个包含至少一个虚函数的基类都有自己的虚函数表。
- 如果基类中的虚函数没有被派生类覆盖,那么在基类的虚函数表中相应的条目将指向基类中该虚函数的实现。
- 如果基类中包含纯虚函数,这些纯虚函数在虚函数表中的条目通常是空的或者指向一个特定的“纯虚函数处理器”。
2、子类的虚函数表
- 派生类会继承其基类的虚函数表,但也会创建自己的虚函数表。
- 子类的虚函数表中首先会复制基类的虚函数表内容。
- 如果子类覆盖了(override)基类的某个虚函数,子类虚函数表中的相应条目会被更新,指向子类中该函数的新实现。
- 子类还可以添加自己的虚函数,这些新的虚函数会被添加到子类的虚函数表的末尾。
- 如果子类本身也是其他类的基类,它的虚函数表将继续被继承和可能被修改。
3、总结
基类和子类虚函数表的关系如下:
继承:子类会自动继承其直接基类的虚函数表。
覆盖:子类可以覆盖基类中的虚函数,这会改变子类虚函数表中对应的条目。
扩展:子类可以添加自己的虚函数,这些函数会被添加到子类虚函数表的末尾。
4、示例
class Base
{
public:
virtual void f() { std::cout << "Base::f" << std::endl; }
virtual void g() { std::cout << "Base::g" << std::endl; }
};
class Derived : public Base
{
public:
void f() override { std::cout << "Derived::f" << std::endl; }
void h() { std::cout << "Derived::h" << std::endl; }
};
// 假设 Base 和 Derived 类的虚函数表如下:
// Base 的虚函数表:
// [0] Base::f
// [1] Base::g
// Derived 的虚函数表:
// [0] Derived::f (覆盖 Base::f)
// [1] Base::g (未覆盖,所以仍然指向 Base 的实现)
// [2] Derived::h (新的虚函数)
在这个例子中,Derived类的虚函数表包含了对 Base类虚函数表的继承,以及对虚函数 f() 的覆盖和新的虚函数 h() 的添加。
通过这种方式,C++的虚函数表机制使得通过基类指针调用函数时,能够动态地选择正确的函数版本,从而实现多态性。
参考文献:C++多态虚函数表详解(多重继承、多继承情况)_一个类有几个虚函数表-CSDN博客
dll中的抽象基类的成员函数声明顺序 与 使用dll中定义的 抽象基类的成员函数 声明顺序不一致时,会导致错误的调用。(先mark下遇到的bug)