子类虚函数表和父类虚函数表
时间: 2025-06-23 10:28:45 浏览: 13
### C++ 子类与父类虚函数表的区别和工作原理
#### 虚函数表的概念
在 C++ 中,为了支持多态特性,引入了虚函数表(vtable)。每个含有虚函数的类都有一个对应的虚函数表。这个表格存储着该类所有虚函数的地址。通过基类指针或引用调用对象的方法时,实际执行的是子类中相应方法版本。
#### 父类的虚函数表结构
对于拥有虚函数的父类而言,编译器为其构建了一个静态数组形式的虚函数表。每当实例化此类的一个新对象时,都会设置一个隐藏成员变量——`vptr` (虚函数指针),用于指向该类特定的虚函数表位置[^1]。
```cpp
class Base {
public:
virtual void func1() {}
virtual void func2() {}
};
// 假设Base类有一个虚函数表如下:
// vtable_Base = [func1, func2]
```
#### 子类的虚函数表扩展
当创建子类并重载某些来自父类的虚函数时,子类不会复制整个父类的虚函数表;相反,它会基于父类已有的虚函数表进行修改:
- 继承自父类的所有未被覆写的虚函数保持不变;
- 对于那些已被子类覆写过的虚函数项,则替换为新的实现入口地址;
- 新增加的任何其他虚函数也将作为额外条目加入到子类自己的虚函数表里[^2]。
```cpp
class Derived : public Base {
public:
void func1() override {} // 重写了func1
virtual void func3() {} // 添加的新虚函数
};
// 此时Derived类可能具有这样的虚函数表布局:
// vtable_Derived = [func1(Derived), func2(Base), func3(Derived)]
```
#### 动态绑定过程解析
考虑下面的例子说明动态绑定的过程:
```cpp
#include <iostream>
using namespace std;
class Animal {
public:
virtual void speak() const { cout << "Animal sound." << endl; }
};
class Dog : public Animal {
public:
void speak() const override { cout << "Woof!" << endl; }
};
int main(){
Animal *p_animal = new Dog();
p_animal->speak(); // 输出"Woof!"
}
```
在这个例子中,尽管 `p_animal` 是一个指向 `Animal` 类型的指针,但由于它是用来表示一个具体的 `Dog` 实例,所以最终调用了 `Dog::speak()` 方法而非默认的 `Animal::speak()` 。这是因为 `p_animal` 的 `vptr` 指向了属于 `Dog` 的那张虚函数表,在那里找到了最新的 `speak` 函数定义[^3]。
阅读全文
相关推荐


















