## 虚函数调用的时间复杂度分析
### 核心结论
**虚函数调用的时间复杂度是 O(1)——常数时间。**
但它比普通成员函数调用多出少量固定的额外开销(两次内存访问和一次间接跳转),不随继承层次深度或对象数量变化。
---
## 一、为什么是 O(1)?
虚函数调用在运行时的执行步骤是固定的,与以下因素无关:
- 继承链的深度(无论多少层覆盖,vtable 索引固定)
- 对象数量(每个对象只需读自己的 vptr)
- 虚函数的数量(索引在编译时确定)
因此,其时间开销是**有上界的常数**,符合 O(1) 的定义。
---
## 二、普通函数 vs 虚函数调用的实际步骤对比
### 1. 普通非虚成员函数调用
```cpp
obj.nonVirtualFunc(); // 或 ptr->nonVirtualFunc()
```
编译器生成:
- 直接 `call` 函数地址(编译时已解析)
- 传递 `this` 指针(通常通过寄存器或栈)
**指令数**:约 1~2 条(算上参数传递)。
### 2. 虚函数调用
```cpp
ptr->virtualFunc();
```
编译器生成类似(x86-64 示意):
```asm
mov rax, [ptr] ; 1. 读取对象的 vptr(对象首地址)
mov rax, [rax + offset] ; 2. 从 vtable 中读取虚函数地址(offset 编译时固定)
call rax ; 3. 间接调用
``