1. 多态的基本概念
多态(Polymorphism)是面向对象编程的核心特性之一,允许同一个接口表现出不同的行为。C++支持两种多态:
- 编译时多态(静态多态):函数重载、运算符重载、模板
- 运行时多态(动态多态):虚函数机制
2. 编译时多态
2.1 函数重载
class Calculator {
public:
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
};
int main() {
Calculator calc;
cout << calc.add(1, 2) << endl; // 调用第一个
cout << calc.add(1.5, 2.5) << endl; // 调用第二个
cout << calc.add(1, 2, 3) << endl; // 调用第三个
}2.2 运算符重载
class Complex {
private:
double real, imag;
public:
Complex(double r = 0, double i = 0) : real(r), imag(i) {}
// 重载 + 运算符
Complex operator+(const Complex& other) const {
return Complex(real + other.real, imag + other.imag);
}
// 重载 << 运算符(友元函数)
friend ostream& operator<<(ostream& os, const Complex& c) {
os << c.real << " + " << c.imag << "i";
return os;
}
};
int main() {
Complex c1(3, 4), c2(1, 2);
Complex c3 = c1 + c2; // 使用重载的+运算符
cout << c3 << endl; // 输出: 4 + 6i
}2.3 模板
template<typename T>
T getMax(T a, T b) {
return (a > b) ? a : b;
}
template<typename T>
class Stack {
private:
vector<T> elements;
public:
void push(const T& elem) { elements.push_back(elem); }
T pop() {
T elem = elements.back();
elements.pop_back();
return elem;
}
};3. 运行时多态(重点)
3.1 虚函数基础
class Animal {
public:
// 虚函数
virtual void makeSound() {
cout << "Animal makes a sound" << endl;
}
// 普通函数
void sleep() {
cout << "Animal is sleeping" << endl;
}
};
class Dog : public Animal {
public:
// 重写虚函数
void makeSound() override {
cout << "Dog barks: Woof!" << endl;
}
void sleep() {
cout << "Dog is sleeping" << endl;
}
};
class Cat : public Animal {
public:
void makeSound() override {
cout << "Cat meows: Meow!" << endl;
}
};
int main() {
Animal* animal1 = new Dog();
Animal* animal2 = new Cat();
// 多态调用(运行时绑定)
animal1->makeSound(); // 输出: Dog barks: Woof!
animal2->makeSound(); // 输出: Cat meows: Meow!
// 非多态调用(编译时绑定)
animal1->sleep(); // 输出: Animal is sleeping
delete animal1;
delete animal2;
}3.2 虚函数表(VTable)机制
class Base {
public:
virtual void func1() { cout << "Base::func1" << endl; }
virtual void func2() { cout << "Base::func2" << endl; }
void func3() { cout << "Base::func3" << endl; }
};
class Derived : public Base {
public:
void func1() override { cout << "Derived::func1" << endl; }
virtual void func4() { cout << "Derived::func4" << endl; }
};
// 内存布局示意:
// Base对象: [vptr] -> [Base::func1] [Base::func2]
// Derived对象: [vptr] -> [Derived::func1] [Base::func2] [Derived::func4]虚函数表工作原理:
void demonstrateVTable() {
Base* ptr = new Derived();
// 调用虚函数时的过程:
// 1. 通过ptr找到对象
// 2. 通过对象的vptr找到虚函数表
// 3. 在虚函数表中找到对应函数的地址
// 4. 调用该函数
ptr->func1(); // 调用Derived::func1
ptr->func2(); // 调用Base::func2
delete ptr;
}4. 纯虚函数和抽象类
4.1 纯虚函数
class Shape { // 抽象类
public:
// 纯虚函数
virtual double area() = 0;
virtual double perimeter() = 0;
// 抽象类可以有普通成员函数
void display() {
cout << "面积: " << area() << endl;
cout << "周长: " << perimeter() << endl;
}
};
class Rectangle : public Shape {
private:
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
double area() override {
return width * height;
}
double perimeter() override {
return 2 * (width + height);
}
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) {}
double area() override {
return 3.14159 * radius * radius;
}
double perimeter() override {
return 2 * 3.14159 * radius;
}
};4.2 接口类(Interface)
// C++中的接口通常用纯虚函数实现
class IDrawable {
public:
virtual ~IDrawable() = default;
virtual void draw() = 0;
virtual void setColor(string color) = 0;
};
class IResizable {
public:
virtual ~IResizable() = default;
virtual void resize(double factor) = 0;
};
// 多重继承实现多个接口
class Widget : public IDrawable, public IResizable {
private:
string color;
double size;
public:
void draw() override {
cout << "Drawing widget with color: " << color << endl;
}
void setColor(string c) override {
color = c;
}
void resize(double factor) override {
size *= factor;
}
};5. 虚析构函数
5.1 为什么需要虚析构函数
class Base {
public:
Base() { cout << "Base构造" << endl; }
~Base() { cout << "Base析构" << endl; } // 非虚析构函数
};
class Derived : public Base {
private:
int* data;
public:
Derived() : data(new int[100]) {
cout << "Derived构造" << endl;
}
~Derived() {
delete[] data;
cout << "Derived析构" << endl;
}
};
int main() {
Base* ptr = new Derived();
delete ptr; // 问题:只调用Base析构函数,内存泄漏!
}5.2 解决方案
class Base {
public:
Base() { cout << "Base构造" << endl; }
virtual ~Base() { cout << "Base析构" << endl; } // 虚析构函数
};
// 现在delete ptr会正确调用Derived的析构函数6. 高级多态应用
6.1 工厂模式
class Product {
public:
virtual ~Product() = default;
virtual void use() = 0;
};
class ConcreteProductA : public Product {
public:
void use() override {
cout << "Using Product A" << endl;
}
};
class ConcreteProductB : public Product {
public:
void use() override {
cout << "Using Product B" << endl;
}
};
class Factory {
public:
static unique_ptr<Product> createProduct(string type) {
if (type == "A") {
return make_unique<ConcreteProductA>();
} else if (type == "B") {
return make_unique<ConcreteProductB>();
}
return nullptr;
}
};6.2 策略模式
class SortStrategy {
public:
virtual ~SortStrategy() = default;
virtual void sort(vector<int>& data) = 0;
};
class BubbleSort : public SortStrategy {
public:
void sort(vector<int>& data) override {
cout << "使用冒泡排序" << endl;
// 实现冒泡排序
}
};
class QuickSort : public SortStrategy {
public:
void sort(vector<int>& data) override {
cout << "使用快速排序" << endl;
// 实现快速排序
}
};
class Sorter {
private:
unique_ptr<SortStrategy> strategy;
public:
void setStrategy(unique_ptr<SortStrategy> s) {
strategy = move(s);
}
void performSort(vector<int>& data) {
if (strategy) {
strategy->sort(data);
}
}
};7. 完整示例:游戏角色系统
#include <iostream>
#include <vector>
#include <memory>
#include <string>
using namespace std;
// 技能接口
class ISkill {
public:
virtual ~ISkill() = default;
virtual void execute() = 0;
virtual int getDamage() = 0;
};
// 具体技能
class FireballSkill : public ISkill {
public:
void execute() override {
cout << "发射火球!造成" << getDamage() << "点伤害" << endl;
}
int getDamage() override { return 50; }
};
class LightningSkill : public ISkill {
public:
void execute() override {
cout << "释放闪电!造成" << getDamage() << "点伤害" << endl;
}
int getDamage() override { return 75; }
};
// 角色基类
class Character {
protected:
string name;
int health;
int mana;
vector<unique_ptr<ISkill>> skills;
public:
Character(string n, int h, int m)
: name(n), health(h), mana(m) {}
virtual ~Character() = default;
// 纯虚函数
virtual void attack() = 0;
virtual void defend() = 0;
// 虚函数
virtual void display() {
cout << name << " - HP: " << health << ", MP: " << mana << endl;
}
void addSkill(unique_ptr<ISkill> skill) {
skills.push_back(move(skill));
}
void useSkill(int index) {
if (index >= 0 && index < skills.size()) {
skills[index]->execute();
}
}
};
// 战士类
class Warrior : public Character {
private:
int armor;
public:
Warrior(string n) : Character(n, 150, 50), armor(30) {}
void attack() override {
cout << name << " 挥舞巨剑攻击!" << endl;
}
void defend() override {
cout << name << " 举盾防御!护甲值: " << armor << endl;
}
void display() override {
Character::display();
cout << "职业: 战士, 护甲: " << armor << endl;
}
};
// 法师类
class Mage : public Character {
private:
int spellPower;
public:
Mage(string n) : Character(n, 80, 150), spellPower(50) {}
void attack() override {
cout << name << " 施放魔法攻击!法术强度: " << spellPower << endl;
}
void defend() override {
cout << name << " 使用魔法护盾!" << endl;
}
void display() override {
Character::display();
cout << "职业: 法师, 法术强度: " << spellPower << endl;
}
};
// 游戏管理器
class GameManager {
private:
vector<unique_ptr<Character>> characters;
public:
void addCharacter(unique_ptr<Character> character) {
characters.push_back(move(character));
}
void showAllCharacters() {
cout << "\n=== 所有角色 ===" << endl;
for (const auto& character : characters) {
character->display(); // 多态调用
cout << "---" << endl;
}
}
void battleDemo() {
cout << "\n=== 战斗演示 ===" << endl;
for (const auto& character : characters) {
character->attack(); // 多态调用
character->defend(); // 多态调用
character->useSkill(0);
cout << endl;
}
}
};
int main() {
GameManager game;
// 创建角色
auto warrior = make_unique<Warrior>("亚瑟");
warrior->addSkill(make_unique<FireballSkill>());
auto mage = make_unique<Mage>("梅林");
mage->addSkill(make_unique<LightningSkill>());
// 添加到游戏
game.addCharacter(move(warrior));
game.addCharacter(move(mage));
// 展示多态
game.showAllCharacters();
game.battleDemo();
return 0;
}8. 多态的性能考虑
8.1 虚函数开销
- 空间开销:每个对象多一个vptr指针(通常8字节)
- 时间开销:间接调用,无法内联优化
8.2 优化建议
// 1. 避免在构造/析构函数中调用虚函数
// 2. 小型频繁调用的函数考虑非虚实现
// 3. 使用final关键字优化
class OptimizedDerived final : public Base {
void func() override final { } // 编译器可优化
};多态是C++实现灵活、可扩展代码的关键特性,合理使用能大大提高代码的可维护性和复用性。