第15章 多态

多态的概念与原理

多态是面向对象编程的核心特性之一,它允许使用统一的接口处理不同类型的对象,实现”一个接口,多种实现”的设计理念。在专家级C++开发中,多态不仅是代码组织工具,更是性能优化和系统设计的关键技术。

多态的核心原理

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

多态的类型

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

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

    • 函数重载
    • 运算符重载
    • 模板(函数模板、类模板、可变参数模板)
    • constexpr if(C++17+)
    • 概念(Concepts,C++20+)
  2. 运行时多态(动态多态):在运行阶段确定调用哪个函数

    • 虚函数
    • 纯虚函数
    • 抽象类
    • 虚继承
    • 协变返回类型

多态的底层实现

虚函数表(vtable)深度分析

核心原理:虚函数表是编译器为每个包含虚函数的类生成的静态数组,存储该类所有虚函数的地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 虚函数表布局分析
class Base {
public:
virtual void func1() {}
virtual void func2() {}
void func3() {} // 非虚函数
int value;
};

class Derived : public Base {
public:
void func1() override {}
virtual void func4() {}
int derivedValue;
};

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

// 内存布局(64位系统):
// Base对象: [vptr (8 bytes)] [value (4 bytes)] [padding (4 bytes)]
// Derived对象: [vptr (8 bytes)] [Base::value (4 bytes)] [padding (4 bytes)] [derivedValue (4 bytes)] [padding (4 bytes)]

虚函数调用的汇编分析

核心步骤

  1. 从对象指针获取虚指针(vptr)
  2. 通过虚指针访问虚函数表(vtable)
  3. 根据函数偏移量获取函数地址
  4. 调用函数
1
2
3
4
5
6
7
8
9
// 虚函数调用的汇编伪代码
Base* ptr = new Derived();
ptr->func1(); // 虚函数调用

// 对应的汇编伪代码:
// mov rax, [ptr] // 获取对象地址
// mov rax, [rax] // 获取vptr
// mov rcx, [rax] // 获取func1的地址(vtable[0])
// call rcx // 调用函数

虚函数表的内存开销

核心分析

  • 每个包含虚函数的类都有一个虚函数表
  • 每个对象都有一个虚指针(通常8字节,64位系统)
  • 虚函数表存储在只读数据段(.rodata)

内存使用计算

  • 类开销:虚函数表大小 = 虚函数数量 * 指针大小
  • 对象开销:每个对象增加一个虚指针的大小

多态的性能分析

虚函数调用vs普通函数调用

性能差异

  • 普通函数调用:直接地址调用,开销极小
  • 虚函数调用:需要多次内存访问(vptr -> 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
void benchmarkFunctionCalls() {
Base* basePtr = new Derived();
Derived* derivedPtr = new Derived();

// 虚函数调用
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < 10000000; ++i) {
basePtr->func1(); // 虚函数调用
}
auto end = std::chrono::high_resolution_clock::now();
std::cout << "Virtual calls: "
<< std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()
<< "ms" << std::endl;

// 普通函数调用
start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < 10000000; ++i) {
derivedPtr->func1(); // 普通函数调用(静态绑定)
}
end = std::chrono::high_resolution_clock::now();
std::cout << "Non-virtual calls: "
<< std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()
<< "ms" << std::endl;

delete basePtr;
delete derivedPtr;
}

运行时多态的实现

虚函数

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

高级特性

  • 虚函数的默认参数:默认参数是静态绑定的,使用基类声明中的默认值
  • 虚函数与const限定符:const和非const版本的成员函数可以重载,const属性是函数签名的一部分
  • 虚函数与引用:多态同样适用于引用,引用的静态类型决定可访问的接口,动态类型决定实际调用的函数
  • 虚函数与final关键字:使用final关键字防止虚函数被进一步重写
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
class Base {
public:
virtual void doSomething() {
std::cout << "Base::doSomething()" << std::endl;
}

// 虚函数的默认参数(静态绑定)
virtual void doSomethingWithDefault(int value = 10) {
std::cout << "Base::doSomethingWithDefault() with value " << value << std::endl;
}

// const版本的虚函数
virtual void doSomethingConst() const {
std::cout << "Base::doSomethingConst()" << std::endl;
}

// 使用final关键字防止重写
virtual void doSomethingFinal() final {
std::cout << "Base::doSomethingFinal()" << std::endl;
}

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

class Derived : public Base {
public:
void doSomething() override {
std::cout << "Derived::doSomething()" << std::endl;
Base::doSomething(); // 显式调用基类方法
}

// 默认参数不会被重写(静态绑定)
void doSomethingWithDefault(int value = 20) override {
std::cout << "Derived::doSomethingWithDefault() with value " << value << std::endl;
}

// 重写const版本的虚函数
void doSomethingConst() const override {
std::cout << "Derived::doSomethingConst()" << std::endl;
}

// 错误:不能重写final方法
// void doSomethingFinal() override {
// std::cout << "Derived::doSomethingFinal()" << std::endl;
// }

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

// 多态调用
void usePolymorphism(Base* ptr) {
ptr->doSomething(); // 根据实际类型调用相应的方法
ptr->doSomethingWithDefault(); // 使用基类的默认参数
ptr->doSomethingConst(); // 调用const版本的虚函数
ptr->doSomethingFinal(); // 调用final方法
}

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

std::cout << "Calling on Base* pointing to Base:" << std::endl;
usePolymorphism(basePtr);

std::cout << "\nCalling on Base* pointing to Derived:" << std::endl;
usePolymorphism(derivedPtr);

delete basePtr;
delete derivedPtr;

return 0;
}

纯虚函数与抽象类

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

设计原则

  • 接口分离原则:接口应该小而专注,只包含必要的方法
  • 单一职责原则:每个接口应该只负责一个功能领域
  • 依赖倒置原则:高层模块应该依赖于抽象接口,而不是具体实现

高级应用

  • 混合接口和实现:抽象类可以包含部分实现,减少派生类的代码重复
  • 模板方法模式:通过抽象类定义算法骨架,派生类实现具体步骤
  • 策略模式:通过接口定义算法家族,运行时选择具体实现
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
// 抽象类(带有部分实现)
class AbstractShape {
public:
virtual ~AbstractShape() = default;

// 纯虚函数
virtual void draw() const = 0;
virtual double area() const = 0;

// 普通虚函数(带有默认实现)
virtual std::string name() const {
return "AbstractShape";
}

// 非虚函数(模板方法模式)
void process() const {
std::cout << "Processing " << name() << ":" << std::endl;
draw();
std::cout << "Area: " << area() << std::endl;
std::cout << "Processing completed." << std::endl;
}
};

// 具体实现类
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";
}
};

class Rectangle : public AbstractShape {
private:
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}

void draw() const override {
std::cout << "Drawing a rectangle with width " << width << " and height " << height << std::endl;
}

double area() const override {
return width * height;
}

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

// 使用抽象类
void processShape(const AbstractShape& shape) {
shape.process(); // 调用模板方法
}

// 工厂函数
std::unique_ptr<AbstractShape> createShape(const std::string& type, double... args) {
if (type == "circle") {
return std::make_unique<Circle>(args[0]);
} else if (type == "rectangle") {
return std::make_unique<Rectangle>(args[0], args[1]);
} else {
throw std::invalid_argument("Unknown shape type: " + type);
}
}

接口

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

现代C++接口设计

  • 使用纯虚函数:只定义方法签名,不提供实现
  • 虚析构函数:确保派生类的析构函数被正确调用
  • 空基类优化:接口类通常不包含成员变量,利用空基类优化减少内存开销
  • 多重继承:接口可以多重继承,实现多个行为契约

接口设计最佳实践

  • 命名约定:接口名称通常使用形容词形式(如Drawable、Colorable)
  • 方法数量:每个接口应该只包含相关的方法,遵循单一职责原则
  • 参数设计:使用值语义或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
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 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 Serializable {
public:
virtual ~Serializable() = default;
virtual std::string serialize() const = 0;
virtual void deserialize(const std::string& data) = 0;
};

// 实现多个接口
class ColoredCircle : public Drawable, public Colorable, public Serializable {
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;
}

std::string serialize() const override {
return "{\"type\":\"circle\",\"radius\":\"" + std::to_string(radius) + "\",\"color\":\"" + color + "\"}";
}

void deserialize(const std::string& data) override {
// 简单的反序列化实现
// 实际应用中应该使用JSON库
size_t radiusPos = data.find("radius");
size_t colorPos = data.find("color");
if (radiusPos != std::string::npos && colorPos != std::string::npos) {
// 提取半径和颜色值
}
}
};

// 接口使用示例
void useInterfaces() {
ColoredCircle circle(5.0, "red");

// 使用Drawable接口
Drawable& drawable = circle;
drawable.draw();
drawable.resize(1.5);

// 使用Colorable接口
Colorable& colorable = circle;
colorable.setColor("blue");
std::cout << "Color: " << colorable.getColor() << std::endl;

// 使用Serializable接口
Serializable& serializable = circle;
std::string data = serializable.serialize();
std::cout << "Serialized: " << data << std::endl;

// 多态使用
std::vector<std::unique_ptr<Drawable>> drawables;
drawables.push_back(std::make_unique<ColoredCircle>(3.0, "green"));

for (const auto& item : drawables) {
item->draw();
}
}

编译时多态的实现

函数重载

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

高级特性

  • 名称修饰(Name Mangling):编译器通过修饰函数名来区分重载函数,包含参数类型信息
  • 重载解析:编译器根据实参类型、数量和顺序选择最匹配的函数
  • 隐式类型转换:在重载解析中会考虑标准类型转换
  • 引用折叠:在模板重载中处理引用类型的特殊规则
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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冲突

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

运算符重载

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

高级应用

  • 表达式模板:用于优化复杂表达式的计算(如Eigen库)
  • 智能指针运算符:重载*和->运算符实现指针语义
  • 迭代器运算符:重载++, –, *, ->等实现容器遍历
  • 类型转换运算符:实现自定义类型之间的隐式转换
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
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);
}

// 重载复合赋值运算符
Vector2D& operator+=(const Vector2D& other) {
x += other.x;
y += other.y;
return *this;
}

// 重载下标运算符
double& operator[](size_t index) {
if (index == 0) return x;
if (index == 1) return y;
throw std::out_of_range("Vector2D index out of range");
}

// 重载类型转换运算符
explicit operator bool() const {
return x != 0.0 || y != 0.0;
}

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

// 友元函数:标量乘法的左操作数版本
friend Vector2D operator*(double scalar, const Vector2D& vec) {
return vec * scalar;
}
};

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

Vector2D v3 = v1 + v2;
Vector2D v4 = v1 - v2;
Vector2D v5 = v1 * 2.0;
Vector2D v6 = 2.0 * v1; // 友元函数版本

v1 += v2;

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;
std::cout << "2 * v1: " << v6 << std::endl;
}

模板与静态多态

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

高级模板技术

  • SFINAE(替换失败不是错误):用于条件性启用模板重载
  • 模板特化:为特定类型提供自定义实现
  • 部分特化:为模板参数的子集提供特化
  • 可变参数模板:处理任意数量的模板参数
  • 模板模板参数:接受模板作为参数的模板
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
// 函数模板
template <typename T>
T maximum(T a, T b) {
return a > b ? a : b;
}

// 模板特化
template <>
const char* maximum(const char* a, const char* b) {
return std::strcmp(a, b) > 0 ? a : b;
}

// 可变参数模板
template <typename... Args>
void print(Args&&... args) {
(std::cout << ... << std::forward<Args>(args)) << std::endl;
}

// 类模板
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();
}

// 模板成员函数
template <typename U>
void push_multiple(U&&... values) {
(push(std::forward<U>(values)), ...);
}
};

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

// 使用类模板
Stack<int> intStack;
intStack.push_multiple(1, 2, 3, 4, 5);

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;

// 使用可变参数模板
print("The maximum values are:", maxInt, ", ", maxDouble, ", ", maxString);
}

CRTP(奇异递归模板模式)

核心特性:CRTP是一种静态多态技术,通过模板继承实现编译时多态,避免虚函数的运行时开销。

优势

  • 零运行时开销:所有调用在编译时解析
  • 内联友好:编译器可以更好地优化调用
  • 类型安全:在编译时捕获类型错误
  • 灵活性:可以在基类中访问派生类的成员
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
// CRTP基类
template <typename Derived>
class Base {
public:
void interface() {
// 静态多态调用
static_cast<Derived*>(this)->implementation();
}

void commonFunction() {
std::cout << "Common functionality from Base" << std::endl;
}
};

// 派生类
class Derived1 : public Base<Derived1> {
public:
void implementation() {
std::cout << "Implementation from Derived1" << std::endl;
}
};

// 另一个派生类
class Derived2 : public Base<Derived2> {
public:
void implementation() {
std::cout << "Implementation from Derived2" << std::endl;
}
};

// 通用函数,使用静态多态
template <typename T>
void useBase(Base<T>& obj) {
obj.interface();
obj.commonFunction();
}

// CRTP的高级应用:计数功能
template <typename Derived>
class Counter {
private:
static inline size_t count = 0;
public:
Counter() {
++count;
}

~Counter() {
--count;
}

static size_t getCount() {
return count;
}

Derived& derived() {
return static_cast<Derived&>(*this);
}
};

class MyClass : public Counter<MyClass> {
public:
void doSomething() {
std::cout << "MyClass::doSomething()" << std::endl;
}
};

// 使用示例
void useCRTP() {
Derived1 d1;
Derived2 d2;

useBase(d1);
useBase(d2);

// 使用计数功能
{
MyClass obj1;
MyClass obj2;
std::cout << "MyClass count: " << MyClass::getCount() << std::endl; // 输出: 2
}
std::cout << "MyClass count after scope: " << MyClass::getCount() << std::endl; // 输出: 0
}

现代C++概念(Concepts)

核心特性:C++20引入的概念(Concepts)用于约束模板参数,提供更清晰的错误信息和更简洁的代码。

优势

  • 更清晰的接口约束
  • 更友好的编译错误信息
  • 减少SFINAE的复杂性
  • 提高代码可读性
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
// 定义概念
template <typename T>
concept Arithmetic = std::is_arithmetic_v<T>;

template <typename T>
concept Printable = requires(T t) {
{ std::cout << t } -> std::same_as<std::ostream&>;
};

template <typename T>
concept Numeric = Arithmetic<T> && Printable<T>;

// 使用概念约束模板参数
template <Numeric T>
T add(T a, T b) {
return a + b;
}

// 概念与CRTP结合
template <typename T>
concept Drawable = requires(T t) {
{ t.draw() } -> std::same_as<void>;
};

template <Drawable Derived>
class Shape {
public:
void render() {
static_cast<Derived*>(this)->draw();
}
};

class Circle : public Shape<Circle> {
public:
void draw() {
std::cout << "Drawing a circle" << std::endl;
}
};

class Square : public Shape<Square> {
public:
void draw() {
std::cout << "Drawing a square" << std::endl;
}
};

// 概念与auto结合(C++20)
auto createShape() -> Shape<auto> {
return Circle{};
}

// 使用示例
void useConcepts() {
// 正确使用
std::cout << add(1, 2) << std::endl;
std::cout << add(1.5, 2.5) << std::endl;

// 错误:字符串不满足Arithmetic概念
// std::cout << add("hello", "world") << std::endl;

Circle circle;
Square square;

circle.render();
square.render();
}

多态的高级应用

虚函数与默认参数

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

设计注意事项

  • 避免在虚函数中使用默认参数,因为这会导致行为不一致
  • 考虑使用函数重载或参数对象模式替代默认参数
  • 如果必须使用默认参数,确保所有派生类使用相同的默认值
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
class Base {
public:
virtual void doSomething(int value = 10) {
std::cout << "Base::doSomething() with value " << value << std::endl;
}

// 推荐:使用函数重载替代默认参数
void doSomething() {
doSomething(10);
}
};

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

// 推荐:保持重载的一致性
void doSomething() {
doSomething(20); // 现在可以使用派生类的默认值
}
};

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

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

// 使用重载版本(动态绑定)
basePtr->doSomething(); // 输出: Base::doSomething() with value 10
static_cast<Derived*>(derivedPtr)->doSomething(); // 输出: Derived::doSomething() with value 20

delete basePtr;
delete derivedPtr;
}

虚函数与const限定符

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

高级应用

  • 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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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;
}

// const重载与返回类型
virtual Base& getSelf() {
return *this;
}

virtual const Base& getSelf() const {
return *this;
}
};

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;
}

// 协变返回类型
Derived& getSelf() override {
return *this;
}

const Derived& getSelf() const override {
return *this;
}
};

// 使用示例
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版本

// 测试协变返回类型
Base& baseRef = basePtr->getSelf();
const Base& constBaseRef = constBasePtr->getSelf();

delete basePtr;
delete constBasePtr;
}

虚函数与引用

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

高级应用

  • 引用包装器:使用std::reference_wrapper实现可复制的引用
  • 类型擦除:通过引用实现运行时多态
  • 完美转发:在模板中保持引用类型信息
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
class Base {
public:
virtual void doSomething() {
std::cout << "Base::doSomething()" << std::endl;
}

virtual ~Base() = default;
};

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

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

// 使用std::reference_wrapper实现多态集合
void testReferenceWrapper() {
Derived d1, d2;
Base b;

std::vector<std::reference_wrapper<Base>> objects = {b, d1, d2};

for (auto& obj : objects) {
obj.get().doSomething(); // 多态调用
}
}

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

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

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

// 测试引用包装器
testReferenceWrapper();
}

类型擦除

核心特性:类型擦除是一种技术,通过基类指针或引用隐藏具体类型信息,实现运行时多态。

高级实现

  • 基于继承的类型擦除:使用虚函数接口
  • 基于模板的类型擦除:使用std::function等
  • 值语义类型擦除:如std::any(C++17+)
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
// 基于继承的类型擦除
class AnyCallable {
public:
virtual ~AnyCallable() = default;
virtual void operator()() = 0;
};

template <typename F>
class CallableWrapper : public AnyCallable {
private:
F func;
public:
explicit CallableWrapper(F&& f) : func(std::forward<F>(f)) {}

void operator()() override {
func();
}
};

class Event {
private:
std::vector<std::unique_ptr<AnyCallable>> handlers;
public:
template <typename F>
void addHandler(F&& handler) {
handlers.push_back(std::make_unique<CallableWrapper<F>>(std::forward<F>(handler)));
}

void trigger() {
for (const auto& handler : handlers) {
(*handler)();
}
}
};

// 使用示例
void testTypeErasure() {
Event event;

// 添加lambda作为处理函数
event.addHandler([]() {
std::cout << "Lambda handler called" << std::endl;
});

// 添加函数对象作为处理函数
struct Handler {
void operator()() {
std::cout << "Functor handler called" << std::endl;
}
};
event.addHandler(Handler{});

// 添加普通函数作为处理函数
void freeFunction() {
std::cout << "Free function handler called" << std::endl;
}
event.addHandler(freeFunction);

// 触发事件
event.trigger();

// 使用std::any(C++17+)
std::any value = 42;
std::cout << "std::any containing int: " << std::any_cast<int>(value) << std::endl;

value = std::string("hello");
std::cout << "std::any containing string: " << std::any_cast<std::string>(value) << std::endl;
}

硬件感知的多态设计

核心特性:考虑硬件特性(如缓存、分支预测、SIMD)的多态设计,提高代码性能。

优化策略

  • 缓存友好:合理设计对象布局,减少缓存未命中
  • 分支预测:减少虚函数调用的分支预测失败
  • SIMD友好:设计支持向量化的接口
  • 内存局部性:提高数据和指令的局部性
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// 缓存友好的多态设计
class Shape {
public:
virtual ~Shape() = default;
virtual void draw() const = 0;
virtual double area() const = 0;

// 数据成员放在基类中,提高缓存局部性
struct BoundingBox {
double x, y, width, height;
} boundingBox;
protected:
Shape(double x, double y, double width, double height)
: boundingBox{x, y, width, height} {}
};

class Circle : public Shape {
private:
double radius;
public:
Circle(double x, double y, double r)
: Shape(x, y, r * 2, r * 2), radius(r) {}

void draw() const override {
std::cout << "Drawing circle at (" << boundingBox.x << ", " << boundingBox.y
<< ") with radius " << radius << std::endl;
}

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

class Rectangle : public Shape {
public:
Rectangle(double x, double y, double width, double height)
: Shape(x, y, width, height) {}

void draw() const override {
std::cout << "Drawing rectangle at (" << boundingBox.x << ", " << boundingBox.y
<< ") with dimensions " << boundingBox.width << "x" << boundingBox.height << std::endl;
}

double area() const override {
return boundingBox.width * boundingBox.height;
}
};

// SIMD友好的多态接口
class SIMDProcessable {
public:
virtual ~SIMDProcessable() = default;

// 标量版本
virtual void process(float* data, size_t size) = 0;

// SIMD版本(如果支持)
virtual void processSIMD(float* data, size_t size) {
// 默认实现:使用标量版本
process(data, size);
}

// 检查是否支持SIMD
virtual bool supportsSIMD() const {
return false;
}
};

class SimpleProcessor : public SIMDProcessable {
public:
void process(float* data, size_t size) override {
for (size_t i = 0; i < size; ++i) {
data[i] = data[i] * 2.0f + 1.0f;
}
}
};

#ifdef __AVX2__
class AVX2Processor : public SIMDProcessable {
public:
void process(float* data, size_t size) override {
for (size_t i = 0; i < size; ++i) {
data[i] = data[i] * 2.0f + 1.0f;
}
}

void processSIMD(float* data, size_t size) override {
size_t i = 0;
for (; i + 7 < size; i += 8) {
__m256 vec = _mm256_loadu_ps(&data[i]);
vec = _mm256_mul_ps(vec, _mm256_set1_ps(2.0f));
vec = _mm256_add_ps(vec, _mm256_set1_ps(1.0f));
_mm256_storeu_ps(&data[i], vec);
}

// 处理剩余元素
for (; i < size; ++i) {
data[i] = data[i] * 2.0f + 1.0f;
}
}

bool supportsSIMD() const override {
return true;
}
};
#endif

// 使用示例
void testHardwareAwarePolymorphism() {
// 测试缓存友好设计
std::vector<std::unique_ptr<Shape>> shapes;
shapes.push_back(std::make_unique<Circle>(0, 0, 5));
shapes.push_back(std::make_unique<Rectangle>(10, 10, 20, 30));
shapes.push_back(std::make_unique<Circle>(40, 40, 10));

for (const auto& shape : shapes) {
shape->draw();
std::cout << "Area: " << shape->area() << std::endl;
}

// 测试SIMD友好设计
std::vector<float> data(1024);
std::generate(data.begin(), data.end(), []() { return static_cast<float>(rand()) / RAND_MAX; });

std::unique_ptr<SIMDProcessable> processor;

#ifdef __AVX2__
processor = std::make_unique<AVX2Processor>();
std::cout << "Using AVX2 processor" << std::endl;
#else
processor = std::make_unique<SimpleProcessor>();
std::cout << "Using simple processor" << std::endl;
#endif

if (processor->supportsSIMD()) {
processor->processSIMD(data.data(), data.size());
} else {
processor->process(data.data(), data.size());
}

std::cout << "Processed first 4 elements: "
<< data[0] << ", " << data[1] << ", " << data[2] << ", " << data[3] << 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
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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;
}

// 基于多态的工厂模式
class AnimalFactory {
public:
static std::unique_ptr<Animal> createAnimal(const std::string& type) {
if (type == "dog") {
return std::make_unique<Dog>();
} else if (type == "cat") {
return std::make_unique<Cat>();
} else if (type == "eagle") {
return std::make_unique<Eagle>();
} else if (type == "salmon") {
return std::make_unique<Salmon>();
} else {
throw std::invalid_argument("Unknown animal type: " + type);
}
}
};

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

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

// 使用工厂创建对象
std::vector<std::string> animalTypes = {"dog", "cat", "eagle", "salmon"};

std::cout << "\nUsing factory pattern:" << std::endl;
for (const auto& type : animalTypes) {
auto animal = AnimalFactory::createAnimal(type);
processAnimal(*animal);
}
}

多态的优缺点

优点

  1. 代码复用:统一的接口可以处理不同类型的对象,减少重复代码
  2. 扩展性:新的派生类可以无缝集成到现有系统中,无需修改现有代码
  3. 灵活性:通过基类指针或引用可以动态选择合适的实现
  4. 可维护性:代码结构清晰,易于理解和维护
  5. 抽象能力:通过抽象类和接口可以定义清晰的行为契约
  6. 解耦:降低模块间的耦合度,提高系统的可测试性
  7. 多态与设计模式:支持多种设计模式,如策略模式、工厂模式、观察者模式等

缺点

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

性能开销详细分析

虚函数调用开销

  • 内存访问:需要访问vptr → vtable → 函数地址
  • 分支预测:虚函数调用是间接分支,容易导致分支预测失败
  • 缓存影响:vtable访问可能导致缓存未命中

性能数据

  • 虚函数调用:约2-5个时钟周期的额外开销
  • 普通函数调用:约0-1个时钟周期
  • 内联函数:0个时钟周期(无调用开销)

多态的最佳实践

1. 正确使用虚函数

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

最佳实践

  • 基类析构函数应该声明为virtual
  • 派生类重写虚函数时使用override关键字
  • 考虑使用final关键字防止不必要的覆盖
  • 避免在构造函数和析构函数中调用虚函数
  • 对于性能关键路径,考虑使用编译时多态替代运行时多态

高级技巧

  • 使用[[nodiscard]]标记虚函数返回值,提高代码质量
  • 考虑使用consteval(C++20+)在编译时计算多态相关值
  • 使用std::variant(C++17+)和std::visit实现基于变体的多态

2. 合理设计抽象接口

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

最佳实践

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

设计模式应用

  • 接口隔离原则:将大接口拆分为小而专注的接口
  • 依赖倒置原则:高层模块依赖抽象,而非具体实现
  • 开闭原则:对扩展开放,对修改封闭

3. 处理多态与异常

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

最佳实践

  • 异常类型应该有合理的层次结构
  • 虚函数可以抛出异常,但派生类抛出的异常应该与基类兼容
  • 析构函数不应该抛出异常
  • 考虑使用RAII模式管理资源
  • 使用异常规范(C++11前)或noexcept(C++11+)标记函数的异常行为

异常安全级别

  • 无抛出保证:函数不会抛出异常
  • 强异常安全:如果抛出异常,程序状态保持不变
  • 基本异常安全:如果抛出异常,程序状态仍然有效,但可能改变

4. 性能优化策略

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

最佳实践

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

高级优化技术

  • 虚函数表缓存:在热点代码中缓存虚函数指针
  • 多态分派优化:使用跳转表或其他技术优化分派
  • SIMD与多态结合:为不同类型提供SIMD优化的实现
  • 硬件感知优化:根据目标硬件调整多态实现

5. 类型转换与安全性

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

最佳实践

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

类型转换安全策略

  • 运行时检查:使用dynamic_cast并检查结果
  • 类型标识:在基类中添加类型标识方法
  • 访问者模式:使用访问者模式避免显式类型转换
  • 类型擦除:使用类型擦除技术隐藏具体类型

6. 现代C++特性的应用

核心原则:利用现代C++特性提高多态代码的安全性和性能。

最佳实践

  • 使用智能指针(std::unique_ptr, std::shared_ptr)管理多态对象的生命周期
  • 利用C++20概念(Concepts)约束模板参数,实现更安全的静态多态
  • 使用std::span(C++20+)和其他现代容器简化多态代码
  • 利用结构化绑定(C++17+)和折叠表达式(C++17+)简化模板代码
  • 使用模块(C++20+)提高编译速度和代码组织

现代C++多态模式

  • 基于范围的for循环:简化多态对象集合的遍历
  • lambda表达式:实现轻量级的函数对象
  • 协程:在异步编程中实现多态行为
  • 反射:使用C++23反射特性简化多态代码

7. 测试与调试策略

核心原则:多态代码需要专门的测试和调试策略,确保正确性和性能。

最佳实践

  • 为每个派生类编写单元测试
  • 测试多态行为,确保基类指针能正确调用派生类实现
  • 使用静态分析工具检测多态相关的问题
  • 性能分析:识别虚函数调用的热点
  • 内存分析:检测多态对象的内存泄漏

调试技巧

  • 使用调试器查看对象的vptr和vtable
  • 打印对象的类型信息(使用typeid
  • 使用断言验证类型转换的安全性
  • 日志记录:在关键多态操作中添加日志

多态的实际应用场景

1. 图形用户界面(GUI)

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

高级实现

  • 事件系统:使用多态实现事件分发和处理
  • 渲染系统:支持不同渲染后端的多态接口
  • 布局系统:基于多态的布局管理器
  • 主题系统:通过多态实现可切换的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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
// 事件系统
class Event {
public:
enum class Type {
CLICK,
KEY_PRESS,
MOUSE_MOVE,
RESIZE
};

Type type;
int x, y;
char key;

Event(Type t) : type(t), x(0), y(0), key(0) {}
};

// 基础组件接口
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 bool handleEvent(const Event& event) = 0;
virtual bool containsPoint(int x, int y) const = 0;

// 组件状态
struct State {
int x, y, width, height;
bool visible = true;
bool enabled = true;
} state;
protected:
Widget(int x, int y, int width, int height)
: state{x, y, width, height} {}
};

// 按钮组件
class Button : public Widget {
private:
std::string label;
std::function<void()> onClickCallback;
public:
Button(const std::string& label, int x, int y, int width, int height)
: Widget(x, y, width, height), label(label) {}

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

void resize(int width, int height) override {
state.width = width;
state.height = height;
}

void setPosition(int x, int y) override {
state.x = x;
state.y = y;
}

bool handleEvent(const Event& event) override {
if (!state.visible || !state.enabled) return false;

if (event.type == Event::Type::CLICK && containsPoint(event.x, event.y)) {
std::cout << "Button clicked: " << label << std::endl;
if (onClickCallback) {
onClickCallback();
}
return true;
}
return false;
}

bool containsPoint(int x, int y) const override {
return x >= state.x && x < state.x + state.width &&
y >= state.y && y < state.y + state.height;
}

void setOnClickCallback(std::function<void()> callback) {
onClickCallback = std::move(callback);
}
};

// 文本框组件
class TextBox : public Widget {
private:
std::string text;
bool focused = false;
public:
TextBox(const std::string& text, int x, int y, int width, int height)
: Widget(x, y, width, height), text(text) {}

void draw() const override {
std::cout << "Drawing text box with text '" << text << "' at ("
<< state.x << ", " << state.y << ") size "
<< state.width << "x" << state.height;
if (focused) {
std::cout << " [FOCUSED]";
}
std::cout << std::endl;
}

void resize(int width, int height) override {
state.width = width;
state.height = height;
}

void setPosition(int x, int y) override {
state.x = x;
state.y = y;
}

bool handleEvent(const Event& event) override {
if (!state.visible || !state.enabled) return false;

if (event.type == Event::Type::CLICK) {
focused = containsPoint(event.x, event.y);
return focused;
} else if (event.type == Event::Type::KEY_PRESS && focused) {
if (event.key == '\b' && !text.empty()) {
text.pop_back();
} else if (event.key >= 32 && event.key <= 126) {
text += event.key;
}
std::cout << "Text box updated: '" << text << "'" << std::endl;
return true;
}
return false;
}

bool containsPoint(int x, int y) const override {
return x >= state.x && x < state.x + state.width &&
y >= state.y && y < state.y + state.height;
}

const std::string& getText() const {
return text;
}
};

// 容器组件(支持嵌套)
class Container : public Widget {
private:
std::vector<std::unique_ptr<Widget>> children;
public:
Container(int x, int y, int width, int height)
: Widget(x, y, width, height) {}

void addChild(std::unique_ptr<Widget> widget) {
children.push_back(std::move(widget));
}

void draw() const override {
std::cout << "Drawing container at ("
<< state.x << ", " << state.y << ") size "
<< state.width << "x" << state.height << std::endl;

for (const auto& child : children) {
child->draw();
}
}

void resize(int width, int height) override {
state.width = width;
state.height = height;
// 可以实现布局逻辑
}

void setPosition(int x, int y) override {
state.x = x;
state.y = y;
// 可以实现子组件位置调整
}

bool handleEvent(const Event& event) override {
if (!state.visible || !state.enabled) return false;

// 从后往前处理,确保上层组件先处理事件
for (auto it = children.rbegin(); it != children.rend(); ++it) {
if ((*it)->handleEvent(event)) {
return true;
}
}
return false;
}

bool containsPoint(int x, int y) const override {
return x >= state.x && x < state.x + state.width &&
y >= state.y && y < state.y + state.height;
}
};

// UI管理器
class UIManager {
private:
std::unique_ptr<Container> rootContainer;
public:
UIManager() : rootContainer(std::make_unique<Container>(0, 0, 800, 600)) {}

void addWidget(std::unique_ptr<Widget> widget) {
rootContainer->addChild(std::move(widget));
}

void drawAll() const {
rootContainer->draw();
}

void handleEvent(const Event& event) {
rootContainer->handleEvent(event);
}

void resize(int width, int height) {
rootContainer->resize(width, height);
}
};

// 使用示例
void useGUI() {
UIManager uiManager;

// 创建按钮
auto button = std::make_unique<Button>("Click Me", 100, 100, 120, 40);
button->setOnClickCallback([]() {
std::cout << "Button callback executed!" << std::endl;
});

// 创建文本框
auto textBox = std::make_unique<TextBox>("Enter text here", 100, 160, 200, 40);

// 添加到UI管理器
uiManager.addWidget(std::move(button));
uiManager.addWidget(std::move(textBox));

// 绘制UI
uiManager.drawAll();

// 模拟事件
Event clickEvent(Event::Type::CLICK);
clickEvent.x = 150;
clickEvent.y = 120;
uiManager.handleEvent(clickEvent);

Event keyEvent(Event::Type::KEY_PRESS);
keyEvent.key = 'H';
uiManager.handleEvent(keyEvent);

keyEvent.key = 'e';
uiManager.handleEvent(keyEvent);

keyEvent.key = 'l';
uiManager.handleEvent(keyEvent);

keyEvent.key = 'l';
uiManager.handleEvent(keyEvent);

keyEvent.key = 'o';
uiManager.handleEvent(keyEvent);
}

2. 数据库访问层

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

高级实现

  • 连接池:使用多态实现数据库连接池
  • 事务管理:支持不同数据库的事务处理
  • 查询构建器:基于多态的SQL查询构建
  • ORM映射:对象关系映射的多态实现
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
// 结果集接口
class ResultSet {
public:
virtual ~ResultSet() = default;
virtual bool next() = 0;
virtual int getInt(int columnIndex) = 0;
virtual std::string getString(int columnIndex) = 0;
virtual double getDouble(int columnIndex) = 0;
virtual bool getBoolean(int columnIndex) = 0;
};

// 数据库接口
class Database {
public:
virtual ~Database() = default;
virtual void connect(const std::string& connectionString) = 0;
virtual void disconnect() = 0;
virtual bool isConnected() const = 0;
virtual std::unique_ptr<ResultSet> executeQuery(const std::string& query) = 0;
virtual int executeUpdate(const std::string& query) = 0;
virtual void beginTransaction() = 0;
virtual void commit() = 0;
virtual void rollback() = 0;
};

// MySQL实现
class MySQLDatabase : public Database {
private:
bool connected = false;
std::string connectionString;
public:
void connect(const std::string& connectionString) override {
std::cout << "Connecting to MySQL database: " << connectionString << std::endl;
// 实际实现:使用MySQL客户端库连接
this->connectionString = connectionString;
this->connected = true;
}

void disconnect() override {
std::cout << "Disconnecting from MySQL database" << std::endl;
// 实际实现:关闭MySQL连接
this->connected = false;
}

bool isConnected() const override {
return connected;
}

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;
}

void beginTransaction() override {
std::cout << "Starting MySQL transaction" << std::endl;
// 实际实现:开始事务
}

void commit() override {
std::cout << "Committing MySQL transaction" << std::endl;
// 实际实现:提交事务
}

void rollback() override {
std::cout << "Rolling back MySQL transaction" << std::endl;
// 实际实现:回滚事务
}
};

// PostgreSQL实现
class PostgreSQLDatabase : public Database {
private:
bool connected = false;
std::string connectionString;
public:
void connect(const std::string& connectionString) override {
std::cout << "Connecting to PostgreSQL database: " << connectionString << std::endl;
// 实际实现:使用PostgreSQL客户端库连接
this->connectionString = connectionString;
this->connected = true;
}

void disconnect() override {
std::cout << "Disconnecting from PostgreSQL database" << std::endl;
// 实际实现:关闭PostgreSQL连接
this->connected = false;
}

bool isConnected() const override {
return connected;
}

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;
}

void beginTransaction() override {
std::cout << "Starting PostgreSQL transaction" << std::endl;
// 实际实现:开始事务
}

void commit() override {
std::cout << "Committing PostgreSQL transaction" << std::endl;
// 实际实现:提交事务
}

void rollback() override {
std::cout << "Rolling back PostgreSQL transaction" << std::endl;
// 实际实现:回滚事务
}
};

// 数据库连接池
class DatabasePool {
private:
std::vector<std::unique_ptr<Database>> connections;
std::queue<Database*> availableConnections;
std::mutex mutex;
std::condition_variable cv;
int maxConnections;
std::string connectionString;
std::string dbType;
public:
DatabasePool(const std::string& type, const std::string& connStr, int maxConn = 10)
: maxConnections(maxConn), connectionString(connStr), dbType(type) {
initializePool();
}

void initializePool() {
for (int i = 0; i < maxConnections; ++i) {
auto db = createDatabase();
if (db) {
db->connect(connectionString);
availableConnections.push(db.get());
connections.push_back(std::move(db));
}
}
}

std::unique_ptr<Database> createDatabase() {
if (dbType == "mysql") {
return std::make_unique<MySQLDatabase>();
} else if (dbType == "postgresql") {
return std::make_unique<PostgreSQLDatabase>();
} else {
throw std::invalid_argument("Unknown database type: " + dbType);
}
}

std::unique_ptr<Database, std::function<void(Database*)>> acquireConnection() {
std::unique_lock<std::mutex> lock(mutex);
cv.wait(lock, [this]() { return !availableConnections.empty(); });

Database* db = availableConnections.front();
availableConnections.pop();

return std::unique_ptr<Database, std::function<void(Database*)>>(
db, [this](Database* db) {
std::unique_lock<std::mutex> lock(mutex);
availableConnections.push(db);
cv.notify_one();
}
);
}

~DatabasePool() {
for (auto& conn : connections) {
if (conn->isConnected()) {
conn->disconnect();
}
}
}
};

// 数据库工厂
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);
}
}

static std::unique_ptr<DatabasePool> createPool(const std::string& type, const std::string& connStr, int maxConn = 10) {
return std::make_unique<DatabasePool>(type, connStr, maxConn);
}
};

// 事务包装器
class Transaction {
private:
Database& db;
bool committed = false;
public:
explicit Transaction(Database& database) : db(database) {
db.beginTransaction();
}

~Transaction() {
if (!committed) {
try {
db.rollback();
} catch (...) {
// 忽略回滚错误
}
}
}

void commit() {
db.commit();
committed = true;
}

void rollback() {
db.rollback();
committed = true;
}
};

// 使用示例
void useDatabase() {
try {
// 创建数据库连接池
auto pool = DatabaseFactory::createPool("mysql", "host=localhost;port=3306;dbname=test;user=root;password=123456", 5);

// 获取连接
auto db = pool->acquireConnection();

// 使用事务
{
Transaction tx(*db);

// 执行更新
db->executeUpdate("INSERT INTO users (name, email) VALUES ('John Doe', 'john@example.com')");
db->executeUpdate("UPDATE settings SET value = '1' WHERE key = 'enabled'");

// 提交事务
tx.commit();
}

// 执行查询
auto result = db->executeQuery("SELECT * FROM users");

// 处理结果
// while (result->next()) {
// std::cout << "User: " << result->getString(1) << " " << result->getString(2) << std::endl;
// }

std::cout << "Database operations completed successfully" << std::endl;

} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
}

3. 日志系统

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

高级实现

  • 日志级别:支持不同级别的日志(DEBUG、INFO、WARN、ERROR、FATAL)
  • 日志格式化:可自定义的日志格式
  • 异步日志:基于多态的异步日志系统
  • 日志轮转:支持文件日志的自动轮转
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
// 日志级别
enum class LogLevel {
DEBUG,
INFO,
WARN,
ERROR,
FATAL
};

// 日志记录器接口
class Logger {
public:
virtual ~Logger() = default;
virtual void log(LogLevel level, const std::string& message) = 0;
virtual void logDebug(const std::string& message) = 0;
virtual void logInfo(const std::string& message) = 0;
virtual void logWarn(const std::string& message) = 0;
virtual void logError(const std::string& message) = 0;
virtual void logFatal(const std::string& message) = 0;
virtual void setMinLevel(LogLevel level) = 0;
};

// 日志格式化器
class LogFormatter {
public:
virtual ~LogFormatter() = default;
virtual std::string format(LogLevel level, const std::string& message) = 0;
};

// 简单日志格式化器
class SimpleFormatter : public LogFormatter {
public:
std::string format(LogLevel level, const std::string& message) override {
std::string levelStr;
switch (level) {
case LogLevel::DEBUG: levelStr = "DEBUG";
break;
case LogLevel::INFO: levelStr = "INFO";
break;
case LogLevel::WARN: levelStr = "WARN";
break;
case LogLevel::ERROR: levelStr = "ERROR";
break;
case LogLevel::FATAL: levelStr = "FATAL";
break;
}

auto now = std::chrono::system_clock::now();
auto time = std::chrono::system_clock::to_time_t(now);
std::stringstream ss;
ss << std::put_time(std::localtime(&time), "%Y-%m-%d %H:%M:%S");

return "[" + ss.str() + "] [" + levelStr + "] " + message;
}
};

// 详细日志格式化器
class DetailedFormatter : public LogFormatter {
public:
std::string format(LogLevel level, const std::string& message) override {
std::string levelStr;
switch (level) {
case LogLevel::DEBUG: levelStr = "DEBUG";
break;
case LogLevel::INFO: levelStr = "INFO";
break;
case LogLevel::WARN: levelStr = "WARN";
break;
case LogLevel::ERROR: levelStr = "ERROR";
break;
case LogLevel::FATAL: levelStr = "FATAL";
break;
}

auto now = std::chrono::system_clock::now();
auto time = std::chrono::system_clock::to_time_t(now);
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;

std::stringstream ss;
ss << std::put_time(std::localtime(&time), "%Y-%m-%d %H:%M:%S") << "." << std::setfill('0') << std::setw(3) << ms.count();

// 获取线程ID
std::thread::id threadId = std::this_thread::get_id();
std::stringstream threadSs;
threadSs << threadId;

return "[" + ss.str() + "] [" + levelStr + "] [Thread: " + threadSs.str() + "] " + message;
}
};

// 控制台日志记录器
class ConsoleLogger : public Logger {
private:
LogLevel minLevel = LogLevel::INFO;
std::unique_ptr<LogFormatter> formatter;
public:
ConsoleLogger(std::unique_ptr<LogFormatter> fmt = std::make_unique<SimpleFormatter>())
: formatter(std::move(fmt)) {}

void log(LogLevel level, const std::string& message) override {
if (level < minLevel) return;

std::string formattedMessage = formatter->format(level, message);

if (level >= LogLevel::ERROR) {
std::cerr << formattedMessage << std::endl;
} else {
std::cout << formattedMessage << std::endl;
}
}

void logDebug(const std::string& message) override {
log(LogLevel::DEBUG, message);
}

void logInfo(const std::string& message) override {
log(LogLevel::INFO, message);
}

void logWarn(const std::string& message) override {
log(LogLevel::WARN, message);
}

void logError(const std::string& message) override {
log(LogLevel::ERROR, message);
}

void logFatal(const std::string& message) override {
log(LogLevel::FATAL, message);
}

void setMinLevel(LogLevel level) override {
minLevel = level;
}
};

// 文件日志记录器
class FileLogger : public Logger {
private:
LogLevel minLevel = LogLevel::INFO;
std::unique_ptr<LogFormatter> formatter;
std::ofstream file;
std::mutex mutex;
public:
FileLogger(const std::string& filename, std::unique_ptr<LogFormatter> fmt = std::make_unique<SimpleFormatter>())
: formatter(std::move(fmt)) {
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(LogLevel level, const std::string& message) override {
if (level < minLevel) return;

std::string formattedMessage = formatter->format(level, message);

std::lock_guard<std::mutex> lock(mutex);
if (file.is_open()) {
file << formattedMessage << std::endl;
}
}

void logDebug(const std::string& message) override {
log(LogLevel::DEBUG, message);
}

void logInfo(const std::string& message) override {
log(LogLevel::INFO, message);
}

void logWarn(const std::string& message) override {
log(LogLevel::WARN, message);
}

void logError(const std::string& message) override {
log(LogLevel::ERROR, message);
}

void logFatal(const std::string& message) override {
log(LogLevel::FATAL, message);
}

void setMinLevel(LogLevel level) override {
minLevel = level;
}
};

// 异步日志记录器包装器
class AsyncLogger : public Logger {
private:
std::unique_ptr<Logger> logger;
std::queue<std::pair<LogLevel, std::string>> logQueue;
std::mutex queueMutex;
std::condition_variable cv;
std::thread workerThread;
std::atomic<bool> running = true;
public:
explicit AsyncLogger(std::unique_ptr<Logger> logger) : logger(std::move(logger)) {
workerThread = std::thread([this]() {
while (running) {
std::pair<LogLevel, std::string> logEntry;
bool hasEntry = false;

{
std::unique_lock<std::mutex> lock(queueMutex);
cv.wait(lock, [this]() {
return !logQueue.empty() || !running;
});

if (!logQueue.empty()) {
logEntry = logQueue.front();
logQueue.pop();
hasEntry = true;
}
}

if (hasEntry) {
logger->log(logEntry.first, logEntry.second);
}
}
});
}

~AsyncLogger() override {
running = false;
cv.notify_one();
if (workerThread.joinable()) {
workerThread.join();
}
}

void log(LogLevel level, const std::string& message) override {
std::unique_lock<std::mutex> lock(queueMutex);
logQueue.emplace(level, message);
cv.notify_one();
}

void logDebug(const std::string& message) override {
log(LogLevel::DEBUG, message);
}

void logInfo(const std::string& message) override {
log(LogLevel::INFO, message);
}

void logWarn(const std::string& message) override {
log(LogLevel::WARN, message);
}

void logError(const std::string& message) override {
log(LogLevel::ERROR, message);
}

void logFatal(const std::string& message) override {
log(LogLevel::FATAL, message);
}

void setMinLevel(LogLevel level) override {
logger->setMinLevel(level);
}
};

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

void log(LogLevel level, const std::string& message) {
std::lock_guard<std::mutex> lock(mutex);
for (const auto& logger : loggers) {
logger->log(level, message);
}
}

void logDebug(const std::string& message) {
log(LogLevel::DEBUG, message);
}

void logInfo(const std::string& message) {
log(LogLevel::INFO, message);
}

void logWarn(const std::string& message) {
log(LogLevel::WARN, message);
}

void logError(const std::string& message) {
log(LogLevel::ERROR, message);
}

void logFatal(const std::string& message) {
log(LogLevel::FATAL, message);
}

void setMinLevel(LogLevel level) {
std::lock_guard<std::mutex> lock(mutex);
for (const auto& logger : loggers) {
logger->setMinLevel(level);
}
}
};

// 日志记录器工厂
class LoggerFactory {
public:
static std::unique_ptr<Logger> createConsoleLogger(LogLevel minLevel = LogLevel::INFO, bool detailed = false) {
auto logger = std::make_unique<ConsoleLogger>(
detailed ? std::make_unique<DetailedFormatter>() : std::make_unique<SimpleFormatter>()
);
logger->setMinLevel(minLevel);
return logger;
}

static std::unique_ptr<Logger> createFileLogger(const std::string& filename, LogLevel minLevel = LogLevel::INFO, bool detailed = false) {
auto logger = std::make_unique<FileLogger>(
filename,
detailed ? std::make_unique<DetailedFormatter>() : std::make_unique<SimpleFormatter>()
);
logger->setMinLevel(minLevel);
return logger;
}

static std::unique_ptr<Logger> createAsyncLogger(std::unique_ptr<Logger> logger) {
return std::make_unique<AsyncLogger>(std::move(logger));
}

static std::unique_ptr<LogManager> createLogManager() {
return std::make_unique<LogManager>();
}
};

// 使用示例
void useLogger() {
// 创建日志管理器
auto logManager = LoggerFactory::createLogManager();

// 添加控制台日志记录器(详细格式)
auto consoleLogger = LoggerFactory::createConsoleLogger(LogLevel::DEBUG, true);
logManager->addLogger(std::move(consoleLogger));

// 添加文件日志记录器(简单格式,异步)
auto fileLogger = LoggerFactory::createFileLogger("application.log", LogLevel::INFO, false);
auto asyncFileLogger = LoggerFactory::createAsyncLogger(std::move(fileLogger));
logManager->addLogger(std::move(asyncFileLogger));

// 记录不同级别的日志
logManager->logDebug("This is a debug message");
logManager->logInfo("Application started");
logManager->logWarn("Low memory warning");
logManager->logError("Failed to connect to database");
logManager->logFatal("Critical system failure");

// 模拟长时间运行的操作,测试异步日志
std::cout << "Simulating long-running operation..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));

logManager->logInfo("Operation completed");
logManager->logInfo("Application exited");
}

// 全局日志管理器(单例模式)
class GlobalLogger {
private:
static std::unique_ptr<LogManager> instance;
static std::once_flag initFlag;

GlobalLogger() = default;

static void initialize() {
instance = LoggerFactory::createLogManager();

// 添加默认日志记录器
auto consoleLogger = LoggerFactory::createConsoleLogger(LogLevel::INFO);
instance->addLogger(std::move(consoleLogger));
}
public:
static LogManager& get() {
std::call_once(initFlag, initialize);
return *instance;
}

static void addLogger(std::unique_ptr<Logger> logger) {
get().addLogger(std::move(logger));
}

static void setMinLevel(LogLevel level) {
get().setMinLevel(level);
}

// 便捷方法
static void debug(const std::string& message) {
get().logDebug(message);
}

static void info(const std::string& message) {
get().logInfo(message);
}

static void warn(const std::string& message) {
get().logWarn(message);
}

static void error(const std::string& message) {
get().logError(message);
}

static void fatal(const std::string& message) {
get().logFatal(message);
}
};

// 静态成员初始化
std::unique_ptr<LogManager> GlobalLogger::instance = nullptr;
std::once_flag GlobalLogger::initFlag;

// 全局日志宏
#define LOG_DEBUG(msg) GlobalLogger::debug(msg)
#define LOG_INFO(msg) GlobalLogger::info(msg)
#define LOG_WARN(msg) GlobalLogger::warn(msg)
#define LOG_ERROR(msg) GlobalLogger::error(msg)
#define LOG_FATAL(msg) GlobalLogger::fatal(msg)

// 全局日志使用示例
void useGlobalLogger() {
// 添加上下文特定的日志记录器
auto fileLogger = LoggerFactory::createFileLogger("application.log", LogLevel::DEBUG, true);
GlobalLogger::addLogger(std::move(fileLogger));

// 使用宏记录日志
LOG_DEBUG("Global logger initialized");
LOG_INFO("Application starting");

try {
// 模拟一些操作
LOG_DEBUG("Performing some operation");
throw std::runtime_error("Simulated error");
} catch (const std::exception& e) {
LOG_ERROR(std::string("Exception caught: ") + e.what());
}

LOG_INFO("Application exiting");
}

总结

多态是C++面向对象编程的核心特性之一,它通过接口与实现分离、运行时绑定、代码复用和扩展性,为构建复杂的软件系统提供了强大的工具。本章节深入探讨了多态的各种实现机制、高级应用和最佳实践,涵盖了从基础概念到专家级技术的全面内容。

关键要点

1. 多态的类型与实现

  • 编译时多态:通过函数重载、模板、CRTP等技术实现,具有零运行时开销
  • 运行时多态:通过虚函数、纯虚函数和抽象类实现,提供更大的灵活性
  • 类型擦除:通过基类指针、std::anystd::function等技术实现

2. 底层实现与性能分析

  • 虚函数表(vtable):编译器为每个包含虚函数的类生成的静态数组
  • 虚指针(vptr):每个对象中指向虚函数表的指针
  • 性能开销:虚函数调用比普通函数调用慢约2-5个时钟周期
  • 优化策略:缓存友好设计、分支预测优化、SIMD集成

3. 现代C++特性的应用

  • 概念(Concepts):C++20引入的模板约束机制
  • 协变返回类型:派生类虚函数可以返回基类虚函数返回类型的派生类型
  • 智能指针:管理多态对象的生命周期
  • 结构化绑定:简化多态代码的使用

4. 高级设计模式

  • CRTP:奇异递归模板模式,实现静态多态
  • 工厂模式:基于多态创建对象
  • 策略模式:通过多态选择不同的算法实现
  • 观察者模式:通过多态实现事件通知机制

5. 最佳实践与设计原则

  • 接口设计:遵循单一职责原则,保持接口简洁
  • 继承层次:保持浅而宽的继承层次,避免深层继承
  • 异常安全:确保多态代码的异常安全性
  • 性能平衡:在性能关键路径上合理选择多态实现方式

6. 实际应用场景

  • 图形用户界面:处理不同类型的UI组件
  • 数据库访问:支持不同类型的数据库系统
  • 日志系统:实现灵活的日志记录和管理
  • 插件系统:通过多态实现可扩展的插件架构

通过合理应用多态,开发者可以创建更加灵活、可扩展和可维护的C++代码,充分发挥面向对象编程的优势。同时,结合现代C++特性和性能优化技术,可以在保持代码清晰性和可维护性的同时,获得优异的运行性能。

本章节提供的技术深度和实践指导,旨在帮助开发者从理解多态的基本概念,到掌握其高级应用,最终能够在实际项目中灵活运用多态技术解决复杂问题,构建高质量的C++应用程序。