第15章 多态

多态的概念与原理

多态是面向对象编程的核心特性之一,它允许使用统一的接口处理不同类型的对象,实现”一个接口,多种实现”的设计理念。

多态的核心原理

  1. 接口与实现分离:通过抽象接口定义行为,具体实现由派生类提供
  2. 运行时绑定:调用哪个具体实现由对象的实际类型决定,而非声明类型
  3. 代码复用:统一的接口使得代码可以处理不同类型的对象
  4. 扩展性:新的派生类可以无缝集成到现有系统中

多态的类型

C++支持两种类型的多态:

  1. 编译时多态(静态多态):在编译阶段确定调用哪个函数

    • 函数重载
    • 运算符重载
    • 模板
  2. 运行时多态(动态多态):在运行阶段确定调用哪个函数

    • 虚函数
    • 纯虚函数
    • 抽象类

运行时多态的实现

虚函数

核心特性:虚函数是在基类中声明并在派生类中重写的成员函数,通过虚函数表(vtable)实现运行时多态。

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
29
30
31
32
33
34
35
36
37
38
39
class Base {
public:
virtual void doSomething() {
std::cout << "Base::doSomething()" << std::endl;
}

virtual ~Base() {
std::cout << "Base::~Base()" << std::endl;
}
};

class Derived : public Base {
public:
void doSomething() override {
std::cout << "Derived::doSomething()" << std::endl;
}

~Derived() {
std::cout << "Derived::~Derived()" << std::endl;
}
};

// 多态调用
void usePolymorphism(Base* ptr) {
ptr->doSomething(); // 根据实际类型调用相应的方法
}

int main() {
Base* basePtr = new Base();
Base* derivedPtr = new Derived();

usePolymorphism(basePtr); // 调用 Base::doSomething()
usePolymorphism(derivedPtr); // 调用 Derived::doSomething()

delete basePtr;
delete derivedPtr;

return 0;
}

虚函数表(vtable)与虚指针(vptr)

核心原理:虚函数的实现依赖于虚函数表和虚指针机制。

  1. 虚函数表(vtable):每个包含虚函数的类都有一个虚函数表,存储该类所有虚函数的地址
  2. 虚指针(vptr):每个对象都有一个虚指针,指向其所属类的虚函数表
  3. 运行时绑定:当调用虚函数时,通过对象的虚指针找到虚函数表,再根据函数在表中的位置找到并调用相应的函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 虚函数表的内部实现原理
class Base {
public:
virtual void func1() {}
virtual void func2() {}
void func3() {} // 非虚函数
};

class Derived : public Base {
public:
void func1() override {} // 重写基类虚函数
virtual void func4() {} // 新增虚函数
};

// Base的虚函数表: [&Base::func1, &Base::func2]
// Derived的虚函数表: [&Derived::func1, &Base::func2, &Derived::func4]

纯虚函数与抽象类

核心特性:纯虚函数是在基类中声明但不提供实现的虚函数,包含纯虚函数的类称为抽象类。

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
29
30
31
32
33
34
35
// 抽象类
class AbstractShape {
public:
virtual ~AbstractShape() = default;
virtual void draw() const = 0; // 纯虚函数
virtual double area() const = 0; // 纯虚函数
virtual std::string name() const { return "AbstractShape"; } // 普通虚函数
};

// 具体实现类
class Circle : public AbstractShape {
private:
double radius;
public:
explicit Circle(double r) : radius(r) {}

void draw() const override {
std::cout << "Drawing a circle with radius " << radius << std::endl;
}

double area() const override {
return M_PI * radius * radius;
}

std::string name() const override {
return "Circle";
}
};

// 使用抽象类
void processShape(const AbstractShape& shape) {
shape.draw();
std::cout << "Area: " << shape.area() << std::endl;
std::cout << "Name: " << shape.name() << std::endl;
}

接口

核心特性:接口是只包含纯虚函数的抽象类,用于定义行为契约。

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
29
30
31
32
33
34
35
36
37
38
39
// 接口定义
class Drawable {
public:
virtual ~Drawable() = default;
virtual void draw() const = 0;
virtual void resize(double factor) = 0;
};

class Colorable {
public:
virtual ~Colorable() = default;
virtual void setColor(const std::string& color) = 0;
virtual std::string getColor() const = 0;
};

// 实现多个接口
class ColoredCircle : public Drawable, public Colorable {
private:
double radius;
std::string color;
public:
ColoredCircle(double r, std::string c) : radius(r), color(std::move(c)) {}

void draw() const override {
std::cout << "Drawing a " << color << " circle with radius " << radius << std::endl;
}

void resize(double factor) override {
radius *= factor;
}

void setColor(const std::string& c) override {
color = c;
}

std::string getColor() const override {
return color;
}
};

编译时多态的实现

函数重载

核心特性:函数重载允许在同一个作用域内定义多个同名函数,通过参数列表的不同来区分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Calculator {
public:
// 重载函数
int add(int a, int b) {
return a + b;
}

double add(double a, double b) {
return a + b;
}

std::string add(const std::string& a, const std::string& b) {
return a + b;
}

// 注意:返回类型不同不构成重载
// void add(int a, int b) { /* ... */ } // 错误:与第一个add冲突
};

运算符重载

核心特性:运算符重载允许为自定义类型定义运算符的行为。

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class Vector2D {
private:
double x, y;
public:
Vector2D(double x = 0, double y = 0) : x(x), y(y) {}

// 重载加法运算符
Vector2D operator+(const Vector2D& other) const {
return Vector2D(x + other.x, y + other.y);
}

// 重载减法运算符
Vector2D operator-(const Vector2D& other) const {
return Vector2D(x - other.x, y - other.y);
}

// 重载乘法运算符(标量乘法)
Vector2D operator*(double scalar) const {
return Vector2D(x * scalar, y * scalar);
}

// 重载输出运算符(友元函数)
friend std::ostream& operator<<(std::ostream& os, const Vector2D& vec) {
os << "(" << vec.x << ", " << vec.y << ")";
return os;
}
};

// 使用示例
void useVector2D() {
Vector2D v1(1, 2);
Vector2D v2(3, 4);

Vector2D v3 = v1 + v2;
Vector2D v4 = v1 - v2;
Vector2D v5 = v1 * 2.0;

std::cout << "v1: " << v1 << std::endl;
std::cout << "v2: " << v2 << std::endl;
std::cout << "v1 + v2: " << v3 << std::endl;
std::cout << "v1 - v2: " << v4 << std::endl;
std::cout << "v1 * 2: " << v5 << std::endl;
}

模板

核心特性:模板允许定义通用的函数或类,在编译时根据实际类型生成具体的代码。

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// 函数模板
template <typename T>
T maximum(T a, T b) {
return a > b ? a : b;
}

// 类模板
template <typename T>
class Stack {
private:
std::vector<T> elements;
public:
void push(const T& value) {
elements.push_back(value);
}

T pop() {
if (elements.empty()) {
throw std::runtime_error("Stack is empty");
}
T value = elements.back();
elements.pop_back();
return value;
}

bool isEmpty() const {
return elements.empty();
}
};

// 使用示例
void useTemplates() {
// 使用函数模板
int maxInt = maximum(10, 20);
double maxDouble = maximum(3.14, 2.71);
std::string maxString = maximum(std::string("apple"), std::string("banana"));

// 使用类模板
Stack<int> intStack;
intStack.push(1);
intStack.push(2);
intStack.push(3);

while (!intStack.isEmpty()) {
std::cout << intStack.pop() << " ";
}
std::cout << std::endl;

Stack<std::string> stringStack;
stringStack.push("hello");
stringStack.push("world");

while (!stringStack.isEmpty()) {
std::cout << stringStack.pop() << " ";
}
std::cout << std::endl;
}

多态的高级应用

虚函数与默认参数

核心原则:虚函数的默认参数是静态绑定的,即使用基类声明中的默认参数值。

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
class Base {
public:
virtual void doSomething(int value = 10) {
std::cout << "Base::doSomething() with value " << value << std::endl;
}
};

class Derived : public Base {
public:
void doSomething(int value = 20) override {
std::cout << "Derived::doSomething() with value " << value << std::endl;
}
};

// 使用示例
void testDefaultArguments() {
Base* basePtr = new Base();
Base* derivedPtr = new Derived();

basePtr->doSomething(); // 输出: Base::doSomething() with value 10
derivedPtr->doSomething(); // 输出: Derived::doSomething() with value 10 (注意:使用基类的默认参数)

delete basePtr;
delete derivedPtr;
}

虚函数与const限定符

核心特性:const和非const版本的成员函数可以重载,虚函数的const属性是其签名的一部分。

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
29
30
31
32
33
34
35
36
37
38
39
class Base {
public:
virtual void doSomething() {
std::cout << "Base::doSomething() (non-const)" << std::endl;
}

virtual void doSomething() const {
std::cout << "Base::doSomething() (const)" << std::endl;
}
};

class Derived : public Base {
public:
void doSomething() override {
std::cout << "Derived::doSomething() (non-const)" << std::endl;
}

void doSomething() const override {
std::cout << "Derived::doSomething() (const)" << std::endl;
}
};

// 使用示例
void testConstPolymorphism() {
Derived d;
const Derived& constRef = d;

d.doSomething(); // 调用非const版本
constRef.doSomething(); // 调用const版本

Base* basePtr = new Derived();
const Base* constBasePtr = new Derived();

basePtr->doSomething(); // 调用非const版本
constBasePtr->doSomething(); // 调用const版本

delete basePtr;
delete constBasePtr;
}

虚函数与引用

核心特性:多态同样适用于引用,引用的静态类型决定了可访问的接口,而动态类型决定了实际调用的函数。

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
29
30
class Base {
public:
virtual void doSomething() {
std::cout << "Base::doSomething()" << std::endl;
}
};

class Derived : public Base {
public:
void doSomething() override {
std::cout << "Derived::doSomething()" << std::endl;
}

void doSomethingElse() {
std::cout << "Derived::doSomethingElse()" << std::endl;
}
};

// 使用示例
void testReferencePolymorphism() {
Derived d;
Base& baseRef = d;

baseRef.doSomething(); // 多态调用:Derived::doSomething()
// baseRef.doSomethingElse(); // 错误:Base接口中没有此方法

// 向下转型
Derived& derivedRef = static_cast<Derived&>(baseRef);
derivedRef.doSomethingElse(); // 可以调用派生类特有方法
}

多态与继承层次

核心特性:在复杂的继承层次中,多态允许通过基类指针或引用调用任何派生类的虚函数。

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
class Animal {
public:
virtual ~Animal() = default;
virtual void makeSound() const = 0;
virtual void move() const = 0;
virtual std::string name() const = 0;
};

class Mammal : public Animal {
public:
void move() const override {
std::cout << "Mammal moves by walking" << std::endl;
}
};

class Bird : public Animal {
public:
void move() const override {
std::cout << "Bird moves by flying" << std::endl;
}
};

class Fish : public Animal {
public:
void move() const override {
std::cout << "Fish moves by swimming" << std::endl;
}
};

class Dog : public Mammal {
public:
void makeSound() const override {
std::cout << "Dog barks" << std::endl;
}

std::string name() const override {
return "Dog";
}
};

class Cat : public Mammal {
public:
void makeSound() const override {
std::cout << "Cat meows" << std::endl;
}

std::string name() const override {
return "Cat";
}
};

class Eagle : public Bird {
public:
void makeSound() const override {
std::cout << "Eagle screeches" << std::endl;
}

std::string name() const override {
return "Eagle";
}
};

class Salmon : public Fish {
public:
void makeSound() const override {
std::cout << "Salmon makes no sound" << std::endl;
}

std::string name() const override {
return "Salmon";
}
};

// 使用多态处理不同类型的动物
void processAnimal(const Animal& animal) {
std::cout << "Processing " << animal.name() << ":" << std::endl;
animal.makeSound();
animal.move();
std::cout << std::endl;
}

// 使用示例
void testAnimalPolymorphism() {
Dog dog;
Cat cat;
Eagle eagle;
Salmon salmon;

processAnimal(dog);
processAnimal(cat);
processAnimal(eagle);
processAnimal(salmon);
}

多态的优缺点

优点

  1. 代码复用:统一的接口可以处理不同类型的对象,减少重复代码
  2. 扩展性:新的派生类可以无缝集成到现有系统中,无需修改现有代码
  3. 灵活性:通过基类指针或引用可以动态选择合适的实现
  4. 可维护性:代码结构清晰,易于理解和维护
  5. 抽象能力:通过抽象类和接口可以定义清晰的行为契约

缺点

  1. 性能开销:虚函数调用需要通过虚函数表查找,比普通函数调用慢
  2. 内存开销:每个包含虚函数的类都需要虚函数表,每个对象都需要虚指针
  3. 复杂性:复杂的继承层次可能导致代码难以理解和维护
  4. 向下转型风险:需要小心使用类型转换,避免运行时错误
  5. 设计难度:正确设计抽象接口需要丰富的经验

多态的最佳实践

1. 正确使用虚函数

核心原则:只对需要多态的函数使用虚函数,避免不必要的性能开销。

最佳实践

  • 基类析构函数应该声明为virtual
  • 派生类重写虚函数时使用override关键字
  • 考虑使用final关键字防止不必要的覆盖
  • 避免在构造函数和析构函数中调用虚函数

2. 合理设计抽象接口

核心原则:抽象接口应该简洁明了,只包含必要的方法。

最佳实践

  • 使用纯虚函数定义接口
  • 接口应该符合单一职责原则
  • 避免在接口中包含实现细节
  • 考虑使用组合而非继承来扩展功能

3. 处理多态与异常

核心原则:异常处理应该与多态设计相结合,确保异常能够正确传播。

最佳实践

  • 异常类型应该有合理的层次结构
  • 虚函数可以抛出异常,但派生类抛出的异常应该与基类兼容
  • 析构函数不应该抛出异常
  • 考虑使用RAII模式管理资源

4. 性能优化

核心原则:在性能关键的代码中,需要平衡多态的便利性和性能开销。

最佳实践

  • 对于性能关键的代码,考虑使用编译时多态(模板)
  • 避免深层的继承层次
  • 合理使用内联函数
  • 考虑使用CRTP(奇异递归模板模式)实现静态多态

5. 类型转换

核心原则:在多态系统中,类型转换应该安全可靠。

最佳实践

  • 尽量避免向下转型
  • 使用dynamic_cast进行安全的向下转型
  • 考虑使用工厂模式或策略模式减少类型转换的需要
  • 对于编译时已知的类型转换,使用static_cast

多态的实际应用场景

1. 图形用户界面(GUI)

核心需求:处理不同类型的UI组件,如按钮、文本框、列表等。

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
class Widget {
public:
virtual ~Widget() = default;
virtual void draw() const = 0;
virtual void resize(int width, int height) = 0;
virtual void setPosition(int x, int y) = 0;
virtual void handleEvent(const Event& event) = 0;
};

class Button : public Widget {
private:
std::string label;
int x, y, width, height;
public:
Button(const std::string& label, int x, int y, int width, int height)
: label(label), x(x), y(y), width(width), height(height) {}

void draw() const override {
std::cout << "Drawing button with label '" << label << "' at (" << x << ", " << y << ")" << std::endl;
}

void resize(int width, int height) override {
this->width = width;
this->height = height;
}

void setPosition(int x, int y) override {
this->x = x;
this->y = y;
}

void handleEvent(const Event& event) override {
if (event.type == EventType::CLICK) {
std::cout << "Button clicked: " << label << std::endl;
}
}
};

class TextBox : public Widget {
private:
std::string text;
int x, y, width, height;
public:
TextBox(const std::string& text, int x, int y, int width, int height)
: text(text), x(x), y(y), width(width), height(height) {}

void draw() const override {
std::cout << "Drawing text box with text '" << text << "' at (" << x << ", " << y << ")" << std::endl;
}

void resize(int width, int height) override {
this->width = width;
this->height = height;
}

void setPosition(int x, int y) override {
this->x = x;
this->y = y;
}

void handleEvent(const Event& event) override {
if (event.type == EventType::KEY_PRESS) {
std::cout << "Text box key press: " << event.key << std::endl;
}
}
};

// 使用多态管理UI组件
class UIManager {
private:
std::vector<std::unique_ptr<Widget>> widgets;
public:
void addWidget(std::unique_ptr<Widget> widget) {
widgets.push_back(std::move(widget));
}

void drawAll() const {
for (const auto& widget : widgets) {
widget->draw();
}
}

void handleEvent(const Event& event) {
for (const auto& widget : widgets) {
widget->handleEvent(event);
}
}
};

2. 数据库访问层

核心需求:支持不同类型的数据库,如MySQL、PostgreSQL、SQLite等。

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
class Database {
public:
virtual ~Database() = default;
virtual void connect(const std::string& connectionString) = 0;
virtual void disconnect() = 0;
virtual std::unique_ptr<ResultSet> executeQuery(const std::string& query) = 0;
virtual int executeUpdate(const std::string& query) = 0;
};

class MySQLDatabase : public Database {
public:
void connect(const std::string& connectionString) override {
std::cout << "Connecting to MySQL database: " << connectionString << std::endl;
}

void disconnect() override {
std::cout << "Disconnecting from MySQL database" << std::endl;
}

std::unique_ptr<ResultSet> executeQuery(const std::string& query) override {
std::cout << "Executing MySQL query: " << query << std::endl;
// 实现查询逻辑
return nullptr;
}

int executeUpdate(const std::string& query) override {
std::cout << "Executing MySQL update: " << query << std::endl;
// 实现更新逻辑
return 0;
}
};

class PostgreSQLDatabase : public Database {
public:
void connect(const std::string& connectionString) override {
std::cout << "Connecting to PostgreSQL database: " << connectionString << std::endl;
}

void disconnect() override {
std::cout << "Disconnecting from PostgreSQL database" << std::endl;
}

std::unique_ptr<ResultSet> executeQuery(const std::string& query) override {
std::cout << "Executing PostgreSQL query: " << query << std::endl;
// 实现查询逻辑
return nullptr;
}

int executeUpdate(const std::string& query) override {
std::cout << "Executing PostgreSQL update: " << query << std::endl;
// 实现更新逻辑
return 0;
}
};

// 数据库工厂
class DatabaseFactory {
public:
static std::unique_ptr<Database> createDatabase(const std::string& type) {
if (type == "mysql") {
return std::make_unique<MySQLDatabase>();
} else if (type == "postgresql") {
return std::make_unique<PostgreSQLDatabase>();
} else {
throw std::invalid_argument("Unknown database type: " + type);
}
}
};

// 使用示例
void useDatabase() {
try {
auto db = DatabaseFactory::createDatabase("mysql");
db->connect("host=localhost;port=3306;dbname=test;user=root;password=123456");
db->executeQuery("SELECT * FROM users");
db->disconnect();

auto pgDb = DatabaseFactory::createDatabase("postgresql");
pgDb->connect("host=localhost;port=5432;dbname=test;user=postgres;password=123456");
pgDb->executeQuery("SELECT * FROM users");
pgDb->disconnect();
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
}

3. 日志系统

核心需求:支持不同类型的日志输出,如控制台、文件、网络等。

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
class Logger {
public:
virtual ~Logger() = default;
virtual void log(const std::string& message) = 0;
virtual void logError(const std::string& message) = 0;
virtual void logWarning(const std::string& message) = 0;
virtual void logInfo(const std::string& message) = 0;
};

class ConsoleLogger : public Logger {
public:
void log(const std::string& message) override {
std::cout << "[LOG] " << message << std::endl;
}

void logError(const std::string& message) override {
std::cerr << "[ERROR] " << message << std::endl;
}

void logWarning(const std::string& message) override {
std::cout << "[WARNING] " << message << std::endl;
}

void logInfo(const std::string& message) override {
std::cout << "[INFO] " << message << std::endl;
}
};

class FileLogger : public Logger {
private:
std::ofstream file;
public:
explicit FileLogger(const std::string& filename) {
file.open(filename, std::ios::out | std::ios::app);
if (!file) {
throw std::runtime_error("Failed to open log file: " + filename);
}
}

~FileLogger() override {
if (file.is_open()) {
file.close();
}
}

void log(const std::string& message) override {
file << "[LOG] " << message << std::endl;
}

void logError(const std::string& message) override {
file << "[ERROR] " << message << std::endl;
}

void logWarning(const std::string& message) override {
file << "[WARNING] " << message << std::endl;
}

void logInfo(const std::string& message) override {
file << "[INFO] " << message << std::endl;
}
};

// 日志管理器
class LogManager {
private:
std::vector<std::unique_ptr<Logger>> loggers;
public:
void addLogger(std::unique_ptr<Logger> logger) {
loggers.push_back(std::move(logger));
}

void log(const std::string& message) {
for (const auto& logger : loggers) {
logger->log(message);
}
}

void logError(const std::string& message) {
for (const auto& logger : loggers) {
logger->logError(message);
}
}

void logWarning(const std::string& message) {
for (const auto& logger : loggers) {
logger->logWarning(message);
}
}

void logInfo(const std::string& message) {
for (const auto& logger : loggers) {
logger->logInfo(message);
}
}
};

// 使用示例
void useLogger() {
LogManager logManager;
logManager.addLogger(std::make_unique<ConsoleLogger>());
logManager.addLogger(std::make_unique<FileLogger>("application.log"));

logManager.logInfo("Application started");
logManager.logWarning("Low memory warning");
logManager.logError("Failed to connect to database");
logManager.logInfo("Application exited");
}

总结

多态是C++面向对象编程的核心特性之一,它通过接口与实现分离、运行时绑定、代码复用和扩展性,为构建复杂的软件系统提供了强大的工具。

关键要点

  • 理解编译时多态和运行时多态的区别与应用场景
  • 掌握虚函数、纯虚函数和抽象类的使用方法
  • 了解虚函数表和虚指针的实现原理
  • 合理设计抽象接口,遵循单一职责原则
  • 平衡多态的便利性和性能开销
  • 遵循多态的最佳实践,提高代码的可维护性和可扩展性

通过合理应用多态,开发者可以创建更加灵活、可扩展和可维护的C++代码,充分发挥面向对象编程的优势。