C++ 类与面向对象编程示例

功能描述

本示例程序展示了 C++ 中面向对象编程的核心概念,包括:

  • 类的定义和基本结构
  • 构造函数和析构函数
  • 成员变量和成员方法
  • 访问控制(public、private)
  • 拷贝构造函数
  • 静态成员
  • 运算符重载
  • 继承与多态
  • 虚函数和纯虚函数
  • 抽象类
  • 组合与聚合
  • 移动语义
  • 智能指针

代码解析

1. 基本类结构

1
2
3
4
5
6
7
8
9
class Rectangle {
private:
double width;
double height;

public:
// 构造函数和析构函数
// 成员方法
};

说明

  • 类是一种用户定义的数据类型,包含数据成员(变量)和成员函数(方法)。
  • private 部分包含只能在类内部访问的成员。
  • public 部分包含可以在类外部访问的成员。

2. 构造函数和析构函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 默认构造函数
Rectangle() : width(0), height(0) {
std::cout << "默认构造函数被调用" << std::endl;
}

// 参数化构造函数
Rectangle(double w, double h) : width(w), height(h) {
std::cout << "参数化构造函数被调用" << std::endl;
}

// 拷贝构造函数
Rectangle(const Rectangle& other) : width(other.width), height(other.height) {
std::cout << "拷贝构造函数被调用" << std::endl;
}

// 析构函数
~Rectangle() {
std::cout << "析构函数被调用" << 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
double getWidth() const {
return width;
}

double getHeight() const {
return height;
}

void setWidth(double w) {
width = w;
}

void setHeight(double h) {
height = h;
}

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

double perimeter() const {
return 2 * (width + height);
}

void display() const {
std::cout << "矩形: " << width << " x " << height << std::endl;
std::cout << "面积: " << area() << std::endl;
std::cout << "周长: " << perimeter() << std::endl;
}

说明

  • 成员方法是类的函数,用于操作对象的数据。
  • const 成员方法不能修改对象的状态。
  • getter 方法用于获取私有成员变量的值。
  • setter 方法用于设置私有成员变量的值。
  • 其他方法用于执行特定的操作,如计算面积和周长。

4. 静态成员

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class BankAccount {
private:
std::string accountNumber;
std::string accountHolder;
double balance;
static int accountCount; // 静态成员变量

public:
// 构造函数
BankAccount(const std::string& num, const std::string& holder, double initialBalance)
: accountNumber(num), accountHolder(holder), balance(initialBalance) {
accountCount++;
}

// 静态成员方法
static int getAccountCount() {
return accountCount;
}
};

// 静态成员变量的初始化
int BankAccount::accountCount = 0;

说明

  • 静态成员变量属于类,而不是对象,所有对象共享同一个静态成员变量。
  • 静态成员变量必须在类外部初始化。
  • 静态成员方法可以在没有对象的情况下调用,只能访问静态成员变量。

5. 运算符重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Point {
private:
int x;
int y;

public:
Point(int x = 0, int y = 0) : x(x), y(y) {}

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

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

// 重载相等运算符
bool operator==(const Point& other) const {
return x == other.x && y == other.y;
}
};

说明

  • 运算符重载允许自定义运算符在类对象上的行为。
  • 重载运算符的函数名是 operator 后跟运算符符号。
  • 运算符重载函数可以是成员函数或全局函数。

6. 继承与多态

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 Shape {
public:
virtual void draw() const {
std::cout << "绘制形状" << std::endl;
}

virtual double getArea() const {
return 0;
}

virtual ~Shape() {}
};

// 派生类
class Circle : public Shape {
private:
double radius;

public:
Circle(double r) : radius(r) {}

void draw() const override {
std::cout << "绘制圆形" << std::endl;
}

double getArea() const override {
return 3.14159 * radius * radius;
}
};

说明

  • 继承允许一个类(派生类)继承另一个类(基类)的成员。
  • virtual 关键字用于声明虚函数,支持运行时多态。
  • override 关键字表示重写基类的虚函数。
  • 虚析构函数确保派生类的析构函数被正确调用。

7. 抽象类和纯虚函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Animal {
public:
virtual void makeSound() const = 0; // 纯虚函数
virtual void eat() const {
std::cout << "动物在吃东西" << std::endl;
}

virtual ~Animal() {}
};

class Dog : public Animal {
public:
void makeSound() const override {
std::cout << "汪汪汪!" << std::endl;
}
};

说明

  • 包含纯虚函数的类是抽象类,不能直接实例化。
  • 纯虚函数是没有实现的虚函数,派生类必须提供实现。
  • 抽象类用于定义接口,派生类提供具体实现。

8. 组合与聚合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Engine {
public:
void start() const {
std::cout << "引擎启动" << std::endl;
}
};

class Car {
private:
Engine engine; // 组合:Car 拥有一个 Engine

public:
void start() const {
engine.start();
std::cout << "汽车启动" << std::endl;
}
};

说明

  • 组合是一种”拥有”关系,其中一个类包含另一个类的对象。
  • 聚合是一种”使用”关系,其中一个类引用另一个类的对象,但不拥有它。

9. 移动语义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class MyString {
private:
char* data;

public:
// 移动构造函数
MyString(MyString&& other) noexcept : data(other.data) {
other.data = nullptr;
std::cout << "移动构造函数被调用" << std::endl;
}

// 移动赋值运算符
MyString& operator=(MyString&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
other.data = nullptr;
std::cout << "移动赋值运算符被调用" << std::endl;
}
return *this;
}
};

说明

  • 移动语义允许资源从一个对象转移到另一个对象,避免不必要的复制。
  • 移动构造函数和移动赋值运算符接受右值引用(&&)。
  • noexcept 表示函数不会抛出异常。

10. 智能指针

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
#include <memory>

class Person {
private:
std::string name;

public:
Person(const std::string& n) : name(n) {
std::cout << "Person " << name << " 被创建" << std::endl;
}

~Person() {
std::cout << "Person " << name << " 被销毁" << std::endl;
}

void sayHello() const {
std::cout << "你好,我是 " << name << std::endl;
}
};

// 使用智能指针
std::unique_ptr<Person> p1 = std::make_unique<Person>("张三");
p1->sayHello();

std::shared_ptr<Person> p2 = std::make_shared<Person>("李四");
std::shared_ptr<Person> p3 = p2; // 共享所有权

说明

  • 智能指针是管理动态内存的工具,自动处理内存的分配和释放。
  • std::unique_ptr 拥有独占所有权,不能复制。
  • std::shared_ptr 共享所有权,使用引用计数。
  • std::make_uniquestd::make_shared 是创建智能指针的推荐方式。

编译和运行

在 Windows 上编译(使用 g++):

1
g++ -std=c++11 -fexec-charset=GBK -o classes classes.cpp

运行程序:

1
.\classes.exe

输出结果:

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
=== 1. 矩形类 ===
默认构造函数被调用
矩形: 0 x 0
面积: 0
周长: 0
参数化构造函数被调用
矩形: 5 x 3
面积: 15
周长: 16
拷贝构造函数被调用
矩形: 5 x 3
面积: 15
周长: 16
矩形: 7 x 4
面积: 28
周长: 22
析构函数被调用
析构函数被调用
析构函数被调用

=== 2. 银行账户类 ===
账户: 123456
持有人: John Doe
余额: $1000
存入: $500
取出: $200
账户: 123456
持有人: John Doe
余额: $1300
总账户数: 2

=== 3. 点类与运算符重载 ===
p1: (3, 4)
p2: (1, 2)
p1 + p2: (4, 6)
p1 - p2: (2, 2)
p1 == p5: true

=== 4. 继承与多态 ===
绘制形状
面积: 0
绘制圆形
面积: 78.5397
绘制矩形
面积: 28

=== 5. 抽象类与接口 ===
汪汪汪!
动物在吃东西
喵喵喵!
动物在吃东西

=== 6. 组合与聚合 ===
引擎启动
汽车启动

=== 7. 移动语义 ===
构造函数被调用
移动构造函数被调用
移动赋值运算符被调用
析构函数被调用
析构函数被调用

=== 8. 智能指针 ===
Person 张三 被创建
你好,我是 张三
Person 李四 被创建
你好,我是 李四
你好,我是 李四
Person 李四 被销毁
Person 张三 被销毁

技术要点

1. 面向对象编程的四大特性

  • 封装:将数据和操作数据的方法封装在一个类中,隐藏实现细节。
  • 继承:一个类可以继承另一个类的属性和方法,实现代码复用。
  • 多态:通过虚函数,不同的对象可以以不同的方式响应相同的消息。
  • 抽象:通过抽象类和接口,定义对象的行为而不实现具体细节。

2. 构造函数和析构函数的使用

  • 构造函数:用于初始化对象,确保对象在创建时处于有效状态。
  • 析构函数:用于清理对象占用的资源,如动态内存、文件句柄等。
  • 拷贝构造函数:用于创建一个新对象作为现有对象的副本。
  • 移动构造函数:用于将资源从一个对象转移到另一个对象,避免不必要的复制。

3. 访问控制

  • public:可以在任何地方访问。
  • private:只能在类内部访问。
  • protected:可以在类内部和派生类中访问。

4. 虚函数和多态

  • 虚函数:在基类中声明,派生类可以重写的函数。
  • 纯虚函数:没有实现的虚函数,派生类必须提供实现。
  • 抽象类:包含纯虚函数的类,不能直接实例化。
  • 多态:通过基类指针或引用调用虚函数时,会根据对象的实际类型调用相应的函数。

5. 运算符重载

  • 可以重载大多数 C++ 运算符,如 +-*/==!= 等。
  • 运算符重载函数可以是成员函数或全局函数。
  • 某些运算符必须作为成员函数重载,如 =[]()->

6. 静态成员

  • 静态成员变量:属于类,所有对象共享,必须在类外部初始化。
  • 静态成员方法:可以在没有对象的情况下调用,只能访问静态成员变量。
  • 静态成员:常用于计数、缓存、工具函数等。

7. 智能指针的使用

  • std::unique_ptr:独占所有权,不能复制,只能移动。
  • std::shared_ptr:共享所有权,使用引用计数。
  • std::weak_ptr:不增加引用计数的 shared_ptr 观察者。
  • 智能指针:可以避免内存泄漏,是现代 C++ 中管理动态内存的推荐方式。

8. 移动语义

  • 右值引用:使用 && 表示,指向临时对象。
  • 移动构造函数:将资源从一个对象转移到另一个对象。
  • 移动赋值运算符:将资源从一个对象转移到另一个已存在的对象。
  • 移动语义:可以提高性能,特别是对于大型对象。

9. 组合与继承的选择

  • 组合:”拥有”关系,一个类包含另一个类的对象。
  • 继承:”是”关系,一个类是另一个类的特殊类型。
  • 优先使用组合:组合比继承更灵活,减少了类之间的耦合。

10. 代码组织和最佳实践

  • 头文件和源文件分离:类声明放在头文件(.h)中,实现放在源文件(.cpp)中。
  • 命名约定:类名使用 PascalCase,成员变量使用 camelCase,常量使用全大写。
  • 初始化列表:使用构造函数初始化列表初始化成员变量,而不是在构造函数体中赋值。
  • const 正确性:对于不修改对象状态的成员函数,使用 const 修饰。
  • 避免使用原始指针:优先使用智能指针管理动态内存。

常见问题

1. 内存泄漏

问题:使用 new 分配内存后,没有使用 delete 释放内存。
解决方案:使用智能指针管理动态内存,或确保每次 new 都有对应的 delete

2. 构造函数和析构函数的顺序

问题:不了解构造函数和析构函数的调用顺序。
解决方案

  • 构造顺序:基类构造函数 → 成员变量构造函数 → 派生类构造函数。
  • 析构顺序:派生类析构函数 → 成员变量析构函数 → 基类析构函数。

3. 虚函数的使用

问题:没有将基类的析构函数声明为虚函数,导致派生类的析构函数不被调用。
解决方案:对于有虚函数的类,将析构函数声明为虚函数。

4. 运算符重载的返回类型

问题:运算符重载函数的返回类型不正确。
解决方案

  • 对于 operator=,返回 *this 的引用。
  • 对于 operator+operator- 等,返回新对象。

5. 静态成员的初始化

问题:静态成员变量没有在类外部初始化。
解决方案:在类外部使用 类型 类名::成员名 = 值; 的形式初始化静态成员变量。

6. 访问控制错误

问题:试图在类外部访问 private 成员。
解决方案:将需要在类外部访问的成员声明为 public,或提供 public 的 getter 和 setter 方法。

7. 继承中的作用域

问题:派生类中的成员与基类中的成员同名,导致基类成员被隐藏。
解决方案:使用 基类名::成员名 访问被隐藏的基类成员,或避免使用同名成员。

8. 智能指针的循环引用

问题:两个对象使用 shared_ptr 相互引用,导致内存泄漏。
解决方案:使用 weak_ptr 打破循环引用。

9. 移动语义的使用

问题:不知道何时使用移动语义,或如何实现移动构造函数。
解决方案

  • 对于包含动态资源的类,实现移动构造函数和移动赋值运算符。
  • 使用 std::move() 将左值转换为右值引用。

10. 代码组织

问题:类的声明和实现都放在一个文件中,导致代码难以维护。
解决方案:将类声明放在头文件中,实现放在源文件中,使用包含保护符防止头文件被重复包含。

代码优化建议

  1. 使用初始化列表

    • 优先使用构造函数初始化列表初始化成员变量,而不是在构造函数体中赋值。
    • 初始化列表可以提高性能,特别是对于大型对象。
  2. 使用 const 修饰符

    • 对于不修改对象状态的成员函数,使用 const 修饰。
    • 对于不修改参数的函数参数,使用 const 引用。
  3. 使用智能指针

    • 优先使用 std::unique_ptrstd::shared_ptr 管理动态内存。
    • 避免使用原始指针和手动内存管理。
  4. 实现移动语义

    • 对于包含动态资源的类,实现移动构造函数和移动赋值运算符。
    • 使用 std::move() 优化对象的传递。
  5. 使用 override 关键字

    • 在重写基类虚函数时,使用 override 关键字,让编译器检查是否正确重写。
  6. 避免使用宏

    • 优先使用 const 变量、枚举和内联函数,而不是宏。
  7. 使用命名空间

    • 将相关的类和函数放在一个命名空间中,避免命名冲突。
  8. 分离接口和实现

    • 将类声明放在头文件中,实现放在源文件中。
    • 使用 Pimpl 手法(指向实现的指针)减少编译依赖。
  9. 使用现代 C++ 特性

    • 使用 C++11 及以上的特性,如自动类型推导、范围 for 循环、lambda 表达式等。
    • 避免使用过时的特性,如 auto_ptrbind1st/bind2nd 等。
  10. 编写单元测试

    • 为类编写单元测试,确保类的行为符合预期。
    • 使用测试框架,如 Google Test、Catch2 等。

总结

C++ 的面向对象编程提供了强大的工具,用于创建模块化、可维护、可扩展的代码:

  • :封装数据和行为,提供了一种组织代码的方式。
  • 继承:实现代码复用,建立类型层次结构。
  • 多态:通过虚函数,实现运行时的动态行为。
  • 抽象:通过抽象类和接口,定义对象的行为契约。
  • 现代 C++ 特性:移动语义、智能指针等,提高代码的性能和安全性。

通过合理使用这些特性,可以创建高质量的 C++ 代码,解决复杂的问题。面向对象编程不仅是一种编程范式,更是一种思维方式,帮助开发者更好地理解和建模现实世界的问题。

classes.cpp

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
#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include <cstring>

// 1. 矩形类 - 基本类结构示例
class Rectangle {
private:
double width; // 宽度
double height; // 高度

public:
// 默认构造函数
Rectangle() : width(0), height(0) {
std::cout << "默认构造函数被调用" << std::endl;
}

// 参数化构造函数
Rectangle(double w, double h) : width(w), height(h) {
std::cout << "参数化构造函数被调用" << std::endl;
}

// 拷贝构造函数
Rectangle(const Rectangle& other) : width(other.width), height(other.height) {
std::cout << "拷贝构造函数被调用" << std::endl;
}

// 析构函数
~Rectangle() {
std::cout << "析构函数被调用" << std::endl;
}

// 获取宽度
double getWidth() const {
return width;
}

// 获取高度
double getHeight() const {
return height;
}

// 设置宽度
void setWidth(double w) {
width = w;
}

// 设置高度
void setHeight(double h) {
height = h;
}

// 计算面积
double area() const {
return width * height;
}

// 计算周长
double perimeter() const {
return 2 * (width + height);
}

// 显示信息
void display() const {
std::cout << "矩形: " << width << " x " << height << std::endl;
std::cout << "面积: " << area() << std::endl;
std::cout << "周长: " << perimeter() << std::endl;
}
};

// 2. 银行账户类 - 静态成员示例
class BankAccount {
private:
std::string accountNumber; // 账户号
std::string accountHolder; // 账户持有人
double balance; // 余额
static int accountCount; // 静态成员变量,用于计数

public:
// 构造函数
BankAccount(const std::string& num, const std::string& holder, double initialBalance)
: accountNumber(num), accountHolder(holder), balance(initialBalance) {
accountCount++;
}

// 存款
void deposit(double amount) {
if (amount > 0) {
balance += amount;
std::cout << "存入: $" << amount << std::endl;
}
}

// 取款
bool withdraw(double amount) {
if (amount > 0 && balance >= amount) {
balance -= amount;
std::cout << "取出: $" << amount << std::endl;
return true;
}
std::cout << "取款失败" << std::endl;
return false;
}

// 获取余额
double getBalance() const {
return balance;
}

// 显示信息
void display() const {
std::cout << "账户: " << accountNumber << std::endl;
std::cout << "持有人: " << accountHolder << std::endl;
std::cout << "余额: $" << balance << std::endl;
}

// 静态成员方法,获取账户总数
static int getAccountCount() {
return accountCount;
}
};

// 静态成员变量的初始化
int BankAccount::accountCount = 0;

// 3. 点类 - 运算符重载示例
class Point {
private:
int x; // x坐标
int y; // y坐标

public:
// 构造函数
Point(int x = 0, int y = 0) : x(x), y(y) {}

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

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

// 重载相等运算符
bool operator==(const Point& other) const {
return x == other.x && y == other.y;
}

// 显示信息
void display() const {
std::cout << "(" << x << ", " << y << ")" << std::endl;
}
};

// 4. 形状类 - 继承与多态示例
class Shape {
public:
// 虚函数,绘制形状
virtual void draw() const {
std::cout << "绘制形状" << std::endl;
}

// 虚函数,获取面积
virtual double getArea() const {
return 0;
}

// 虚析构函数
virtual ~Shape() {}
};

// 圆形类 - 继承自形状类
class Circle : public Shape {
private:
double radius; // 半径

public:
// 构造函数
Circle(double r) : radius(r) {}

// 重写绘制方法
void draw() const override {
std::cout << "绘制圆形" << std::endl;
}

// 重写获取面积方法
double getArea() const override {
return 3.14159 * radius * radius;
}
};

// 矩形类 - 继承自形状类(另一个版本)
class RectangleShape : public Shape {
private:
double width; // 宽度
double height; // 高度

public:
// 构造函数
RectangleShape(double w, double h) : width(w), height(h) {}

// 重写绘制方法
void draw() const override {
std::cout << "绘制矩形" << std::endl;
}

// 重写获取面积方法
double getArea() const override {
return width * height;
}
};

// 5. 动物类 - 抽象类示例
class Animal {
public:
// 纯虚函数,发出声音
virtual void makeSound() const = 0;

// 普通虚函数,吃东西
virtual void eat() const {
std::cout << "动物在吃东西" << std::endl;
}

// 虚析构函数
virtual ~Animal() {}
};

// 狗类 - 继承自动物类
class Dog : public Animal {
public:
// 实现发出声音方法
void makeSound() const override {
std::cout << "汪汪汪!" << std::endl;
}
};

// 猫类 - 继承自动物类
class Cat : public Animal {
public:
// 实现发出声音方法
void makeSound() const override {
std::cout << "喵喵喵!" << std::endl;
}
};

// 6. 引擎类 - 用于组合示例
class Engine {
public:
// 启动引擎
void start() const {
std::cout << "引擎启动" << std::endl;
}
};

// 汽车类 - 包含引擎(组合)
class Car {
private:
Engine engine; // 组合:Car 拥有一个 Engine

public:
// 启动汽车
void start() const {
engine.start();
std::cout << "汽车启动" << std::endl;
}
};

// 7. 字符串类 - 移动语义示例
class MyString {
private:
char* data; // 字符数据

public:
// 构造函数
MyString(const char* str) {
if (str) {
data = new char[strlen(str) + 1];
strcpy(data, str);
} else {
data = nullptr;
}
std::cout << "构造函数被调用" << std::endl;
}

// 移动构造函数
MyString(MyString&& other) noexcept : data(other.data) {
other.data = nullptr;
std::cout << "移动构造函数被调用" << std::endl;
}

// 移动赋值运算符
MyString& operator=(MyString&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
other.data = nullptr;
std::cout << "移动赋值运算符被调用" << std::endl;
}
return *this;
}

// 析构函数
~MyString() {
delete[] data;
std::cout << "析构函数被调用" << std::endl;
}

// 获取数据
const char* getData() const {
return data;
}
};

// 8. 人类 - 智能指针示例
class Person {
private:
std::string name; // 姓名

public:
// 构造函数
Person(const std::string& n) : name(n) {
std::cout << "Person " << name << " 被创建" << std::endl;
}

// 析构函数
~Person() {
std::cout << "Person " << name << " 被销毁" << std::endl;
}

// 打招呼
void sayHello() const {
std::cout << "你好,我是 " << name << std::endl;
}
};

int main() {
std::cout << "=== 1. 矩形类 ===" << std::endl;
{
Rectangle rect1;
rect1.display();

Rectangle rect2(5.0, 3.0);
rect2.display();

Rectangle rect3 = rect2;
rect3.display();

rect3.setWidth(7.0);
rect3.setHeight(4.0);
rect3.display();
} // 此处三个矩形对象会被销毁

std::cout << "\n=== 2. 银行账户类 ===" << std::endl;
{
BankAccount acc1("123456", "John Doe", 1000.0);
BankAccount acc2("789012", "Jane Smith", 500.0);

acc1.display();
acc1.deposit(500.0);
acc1.withdraw(200.0);
acc1.display();

std::cout << "总账户数: " << BankAccount::getAccountCount() << std::endl;
} // 此处两个账户对象会被销毁

std::cout << "\n=== 3. 点类与运算符重载 ===" << std::endl;
{
Point p1(3, 4);
Point p2(1, 2);

Point p3 = p1 + p2;
Point p4 = p1 - p2;

std::cout << "p1: ";
p1.display();
std::cout << "p2: ";
p2.display();
std::cout << "p1 + p2: ";
p3.display();
std::cout << "p1 - p2: ";
p4.display();

Point p5(3, 4);
std::cout << "p1 == p5: " << (p1 == p5 ? "true" : "false") << std::endl;
}

std::cout << "\n=== 4. 继承与多态 ===" << std::endl;
{
Shape* shape1 = new Shape();
Shape* shape2 = new Circle(5.0);
Shape* shape3 = new RectangleShape(7.0, 4.0);

shape1->draw();
std::cout << "面积: " << shape1->getArea() << std::endl;

shape2->draw();
std::cout << "面积: " << shape2->getArea() << std::endl;

shape3->draw();
std::cout << "面积: " << shape3->getArea() << std::endl;

delete shape1;
delete shape2;
delete shape3;
}

std::cout << "\n=== 5. 抽象类与接口 ===" << std::endl;
{
Animal* dog = new Dog();
Animal* cat = new Cat();

dog->makeSound();
dog->eat();

cat->makeSound();
cat->eat();

delete dog;
delete cat;
}

std::cout << "\n=== 6. 组合与聚合 ===" << std::endl;
{
Car car;
car.start();
}

std::cout << "\n=== 7. 移动语义 ===" << std::endl;
{
MyString s1("Hello");
MyString s2 = std::move(s1); // 使用移动构造函数
MyString s3("World");
s3 = std::move(s2); // 使用移动赋值运算符
}

std::cout << "\n=== 8. 智能指针 ===" << std::endl;
{
// 使用 unique_ptr
std::unique_ptr<Person> p1(new Person("张三"));
p1->sayHello();

// 使用 shared_ptr
std::shared_ptr<Person> p2 = std::make_shared<Person>("李四");
std::shared_ptr<Person> p3 = p2; // 共享所有权

p2->sayHello();
p3->sayHello();
} // 此处智能指针会自动释放内存

return 0;
}