编译时多态与运行时多态


1. 编译时多态

含义

  • 编译时多态(Static Polymorphism)是在编译阶段通过函数或操作的重载、模板等机制实现的多样化行为。
  • 也称为静态多态,因为函数调用在编译时就绑定(静态绑定)。

实现方式

  • 函数重载:根据参数类型或数量选择不同函数。
  • 运算符重载:自定义运算符行为。
  • 模板:通过模板参数生成不同类型的函数或类(模板特化)。

特点

  • 效率高:编译时解析,无运行时开销。
  • 类型固定:需要在编译时确定调用类型。
  • 无虚函数:不涉及虚函数表(vtable,参考上下文)。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

// 函数重载
void print(int x) { std::cout << "Int: " << x << "\n"; }
void print(double x) { std::cout << "Double: " << x << "\n"; }

// 模板
template<typename T>
T add(T a, T b) { return a + b; }

int main() {
print(5); // 调用 print(int)
print(5.5); // 调用 print(double)
std::cout << add(3, 4) << "\n"; // 输出: 7 (int)
std::cout << add(3.5, 4.5) << "\n"; // 输出: 8.0 (double)
}

2. 运行时多态

含义

  • 运行时多态(Dynamic Polymorphism)是在运行阶段通过虚函数和继承实现的动态行为。
  • 也称为动态多态,因为函数调用在运行时根据对象实际类型绑定(动态绑定)。

实现方式

  • 虚函数:通过 virtual 关键字声明,派生类重写基类虚函数(参考上下文)。
  • 基类指针或引用:指向派生类对象,动态调用对应函数。

特点

  • 灵活性高:支持动态类型,运行时决定行为。
  • 性能开销:涉及虚函数表(vtable)和虚函数表指针(vptr,参考上下文),增加内存和运行时查找成本。
  • 依赖继承:需通过类层次结构实现。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

class Base {
public:
virtual void func() { std::cout << "Base::func\n"; }
virtual ~Base() = default;
};

class Derived : public Base {
public:
void func() override { std::cout << "Derived::func\n"; }
};

int main() {
Base* ptr = new Derived();
ptr->func(); // 输出: Derived::func(运行时决定)
delete ptr;
}

3. 对比总结

特性 编译时多态 运行时多态
实现方式 函数重载、模板、运算符重载 虚函数、继承
绑定时间 编译时(静态绑定) 运行时(动态绑定)
性能 无运行时开销,高效 有 vtable/vptr 开销
灵活性 类型需编译时确定 支持运行时动态类型
典型场景 通用编程、模板库 多态对象、插件系统

与上下文联系

  • 虚函数(参考上下文):运行时多态的核心,依赖 vtable 和 vptr(参考上下文)。
  • 虚继承(参考上下文):与运行时多态无关,但可能在多态类层次中出现,需注意虚析构函数(参考上下文)。
  • 内存对齐(参考上下文):运行时多态的 vptr 可能影响对象大小和对齐,编译时多态无此问题。

4. 综合示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>

// 编译时多态:模板
template<typename T>
void print(T x) { std::cout << "Template: " << x << "\n"; }

// 运行时多态:虚函数
class Base {
public:
virtual void func() { std::cout << "Base::func\n"; }
virtual ~Base() = default;
};

class Derived : public Base {
public:
void func() override { std::cout << "Derived::func\n"; }
};

int main() {
// 编译时多态
print(5); // 输出: Template: 5
print(5.5); // 输出: Template: 5.5

// 运行时多态
Base* ptr = new Derived();
ptr->func(); // 输出: Derived::func
delete ptr;
}