C++ 的多态(Polymorphism)是面向对象编程(OOP)的核心特性之一,指的是相同的接口,不同的实现,可以让不同的对象有不同的表现形式。
一、多态的分类
C++ 的多态分为静态多态和动态多态,它们的绑定时机不同:
| 多态类型 | 实现方式 | 绑定时机 | 开销 |
|---|---|---|---|
| 动态多态 | 继承 + 虚函数 | 运行期 | 需要 vtable 指针查询 |
| 静态多态 | 函数重载、运算符重载、模板(CRTP) | 编译期 | 无额外运行时开销 |
二、动态多态(虚函数)
动态多态是真正的 OOP 多态,依赖继承和虚函数,在运行时动态决定调用哪个函数。
1. 继承 + 虚函数
#include <iostream>
class Animal {
public:
virtual void makeSound() { // 虚函数
std::cout << "Animal makes a sound" << std::endl;
}
virtual ~Animal() = default; // 确保基类析构函数为虚函数
};
class Dog : public Animal {
public:
void makeSound() override {
std::cout << "Dog barks" << std::endl;
}
};
class Cat : public Animal {
public:
void makeSound() override {
std::cout << "Cat meows" << std::endl;
}
};
int main() {
Animal* a1 = new Dog();
Animal* a2 = new Cat();
a1->makeSound(); // Dog barks
a2->makeSound(); // Cat meows
delete a1;
delete a2;
return 0;
}
特点:
- 绑定时机:运行期(动态绑定)
- 实现方式:
virtual关键字 - 开销:
- 每个含虚函数的类都有虚函数表(vtable)
- 每个对象有一个虚指针(vptr) 指向
vtable - 调用虚函数时会查找 vtable,有一定性能开销
2. 纯虚函数(抽象类)
如果一个类至少有一个纯虚函数,它就是抽象类,不能直接实例化。
#include <iostream>
class Animal {
public:
virtual void makeSound() = 0; // 纯虚函数
virtual ~Animal() = default;
};
class Dog : public Animal {
public:
void makeSound() override {
std::cout << "Dog barks" << std::endl;
}
};
int main() {
// Animal a; // ❌错误,抽象类不能实例化
Dog d;
d.makeSound(); // Dog barks
return 0;
}
特点:
- 必须在派生类中实现纯虚函数,否则派生类也是抽象类
- 用于定义接口(如
std::istream、std::ostream)
三、静态多态
1. 函数重载(Function Overloading)
函数重载指的是同一作用域下多个函数的名字相同,但参数列表不同,编译器根据参数类型和数量来选择正确的函数。
class OverloadingExample {
void display(int a) {
System.out.println("Display method with integer:" + a);
}
void display(string b) {
System.out.println("Display method with string:" + b);
}
}
特点:
- 绑定时机:编译期(静态绑定)
- 实现方式:同名函数,参数不同
- 应用场景:简化接口,提高可读性
2. 运算符重载(Operator Overloading)
运算符重载允许我们自定义类的操作符行为,使其更直观。例如,为 Vector 类重载 + 号:
#include <iostream>
class Vector {
public:
int x, y;
Vector(int a, int b) : x(a), y(b) {}
// 重载 + 运算符
Vector operator+(const Vector& other) {
return Vector(x + other.x, y + other.y);
}
void print() {
std::cout << "(" << x << ", " << y << ")" << std::endl;
}
};
int main() {
Vector v1(1, 2), v2(3, 4);
Vector v3 = v1 + v2;
v3.print(); // 输出 (4, 6)
return 0;
}
特点:
- 绑定时机:编译期
- 实现方式:重载
+、-、*等运算符 - 应用场景:自定义数据类型(如数学向量、复数等)
3. 模板多态(基于 CRTP 的静态多态)
模板支持泛型编程,在编译时决定具体的实现。
template<class T>
T GetMax(T a, T b) {
return (a > b ? a : b);
}
int main() {
int i = 5, j = 6, k;
long 1 = 10, m = 5, n;
k = GetMax<int>(i, j);
n = GetMax<long>(l, m);
cout << k << endl;
cout << n << end1;
return 0;
}
特点:
- 绑定时机:编译期
- 实现方式:利用模板静态分派
- 应用场景:替代虚函数以提高性能(如 STL 容器、数学库等)
四、多态的应用场景
- 函数重载:提供多种操作方式,提高可读性
- 运算符重载:自定义数据结构的操作
- 模板编程(CRTP):提高执行效率
- 虚函数(运行时多态):
- 面向对象设计(统一接口)
- 插件系统(如 Qt 的
QObject) - 游戏引擎(多种不同
Enemy共享EnemyBase)
五、总结
| 多态类型 | 关键技术 | 绑定时机 | 是否需要继承 | 适用场景 |
|---|---|---|---|---|
| 函数重载 | 参数不同的同名函数 | 编译期 | 否 | 提供多种调用方式 |
| 运算符重载 | 重载 +、- 等 | 编译期 | 否 | 自定义数据类型运算 |
| 模板(CRTP) | 模板继承 | 编译期 | 否 | 替代虚函数,提高性能 |
| 虚函数 | virtual 关键字 | 运行期 | 是 | 统一接口,动态扩展 |
2264

被折叠的 条评论
为什么被折叠?



