Compare commits

...

28 Commits

Author SHA1 Message Date
flykhan 4c986179b4 其他未完成 2023-08-14 17:20:39 +08:00
flykhan 9290e4c051 stl第一部分: string, vector, deque, stack 2023-08-04 09:28:07 +08:00
flykhan 82619cea98 modify readme 2023-08-03 09:47:09 +08:00
flykhan cfd8dd3992 day7: homework 修改第7题 2023-08-03 09:42:28 +08:00
flykhan 166515cf82 day7: homework 修改第7题 2023-08-03 09:30:34 +08:00
flykhan 8c46e7a977 day8: homework 2023-08-02 20:48:31 +08:00
flykhan 606fbc6ff1 day8: coding 2023-08-02 19:23:29 +08:00
flykhan 994963d919 day7 2023-08-02 19:22:52 +08:00
flykhan 15ae1803d7 day7: homework 2023-08-01 22:54:37 +08:00
flykhan c127a3a81b day7: homework-LinkedList 链表的实现 2023-08-01 22:21:52 +08:00
flykhan 5ab334d200 day7: homework 2023-08-01 21:46:18 +08:00
flykhan aae9aba049 day7: 类模版 2023-08-01 18:51:53 +08:00
flykhan 08a390b0b1 day6: homework 2023-08-01 09:07:49 +08:00
flykhan e5577ed3e5 另一种ArrayList类的实现 2023-07-28 09:20:37 +08:00
flykhan f5c016c6bb day4: static 静态成员, 类的单例设计模式, 对象的存储(this 指针与链式编程, const 修饰成员函数与类对象), 友元, 运算符重载 2023-07-28 08:57:54 +08:00
flykhan 7b786b9b92 day4: homework 2023-07-27 21:04:06 +08:00
flykhan be4a556f0b 友元练习: 电视机和遥控器 2023-07-27 16:28:53 +08:00
flykhan f956e9c5e2 数组类的封装: 添加 makefile 运行测试规则 2023-07-27 15:34:51 +08:00
flykhan 6e18cf2118 数组类的封装 2023-07-27 15:31:47 +08:00
flykhan eb4944efe7 day3: homework 2023-07-26 21:10:02 +08:00
flykhan 3320bf12d2 day3: 对象的构造与析构, 构造函数的分类与调用, 拷贝构造函数的调用时机, 构造函数的调用规则, 深拷贝和浅拷贝, 多个对象的构造和析构(初始化列表, 类对象作为成员), explicit 关键字(禁止隐式转换), 动态创建对象(malloc/realloc/calloc 在堆中创建空间, new 关键字), 扩展 new 和 delete 2023-07-26 18:10:36 +08:00
flykhan 220ea31d68 day2: const 和#define 的区别, 引用(reference) 【重要】, 内联函数, 函数的默认值参数, 函数的占位参数, 函数重载和extern c, 类与对象的概念, 面向对象程序设计案例 2023-07-25 20:05:25 +08:00
flykhan fd11f165fb day2: homework 2023-07-25 20:00:23 +08:00
flykhan 9f331e0c58 添加 free() 2023-07-25 09:09:28 +08:00
flykhan 2991bb5aeb modify readme 2023-07-24 21:05:39 +08:00
flykhan 4945f41af7 day1: C++简介, ::作用域, namespace 命名空间, using 声明, using 编译指令, 类型转换, struct 类型加强, bool 关键字, 三目运算符增强, const 增强 2023-07-24 21:05:15 +08:00
flykhan ca6f2f9fe6 day1: homework 2023-07-24 21:05:02 +08:00
flykhan 79430284ab add .vscode test 2023-07-24 16:30:08 +08:00
247 changed files with 11266 additions and 1 deletions
+3
View File
@@ -32,3 +32,6 @@
*.out
*.app
# 自定义忽略
test
.vscode
+19 -1
View File
@@ -1,3 +1,21 @@
# qfedu-cpp-level
千锋C++阶段
# 千锋 C++阶段
#### day1: C++简介, ::作用域, namespace 命名空间, using 声明, using 编译指令, 类型转换, struct 类型加强, bool 关键字, 三目运算符增强, const 增强
#### day2: const 和#define 的区别, 引用(reference) 【重要】, 内联函数, 函数的默认值参数, 函数的占位参数, 函数重载和 extern "c", 类与对象的概念, 面向对象程序设计案例
#### day3: 对象的构造与析构, 构造函数的分类与调用, 拷贝构造函数的调用时机, 构造函数的调用规则, 深拷贝和浅拷贝, 多个对象的构造和析构(初始化列表, 类对象作为成员), explicit 关键字(禁止隐式转换), 动态创建对象(malloc/realloc/calloc 在堆中创建空间, new 关键字), 扩展 new 和 delete,
#### day4: static 静态成员, 类的单例设计模式, 对象的存储(this 指针与链式编程, const 修饰成员函数与类对象), 友元, 运算符重载
#### day5: =运算符的重载, () 函数调用重载, `注意: &&和|| 无法重载`,
#### day6: 多继承(同属一个超级父类)产生的问题, 多态,抽象类, 虚函数(virtual)与纯虚函数, 接口类的多继承, override-overload-redefined 的区别, 函数模版, 普通函数与带泛型函数的区别
#### day7: 函数模板, 类模板, 类模板与友元一起使用的情况, 类型转换函数(static_cast, dynamic_cast, const_cast, reinterpret_cast)
#### day8: 异常处理, STL(容器、算法、迭代器)
#### day9: STL-> string, vector, deque, stack
+9
View File
@@ -0,0 +1,9 @@
#include <iostream>
using namespace std;
int main()
{
cout << "Hello, World!" << endl;
return 0;
}
+14
View File
@@ -0,0 +1,14 @@
// bool 类型
#include <iostream>
using namespace std;
int main()
{
bool flag = 2; // 非 0 即 true0 为 false
if (flag)
cout << "true" << endl;
else
cout << "false" << endl;
return 0;
}
+11
View File
@@ -0,0 +1,11 @@
// c 中三目运算表达式返回的是 变量的值
// c++ 中三目运算表达式返回的是 变量 (对照 d11.cpp)
#include <stdio.h>
int main()
{
int a = 10, b = 20;
(a > b ? a : b) = 100; // 不能这样写,因为 c 语言中三目运算表达式返回的是变量的值
printf("a = %d, b = %d\n", a, b);
return 0;
}
+14
View File
@@ -0,0 +1,14 @@
// c 中三目运算表达式返回的是 变量的值 (对照 d11.c)
// c++ 中三目运算表达式返回的是 变量
#include <iostream>
using namespace std;
int main()
{
int a = 10, b = 20;
(a > b ? a : b) = 100;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
return 0;
}
+37
View File
@@ -0,0 +1,37 @@
// const
// c++ 中 const 在定义时不会创建内存空间,取地址时会创建内存空间
// 或者把它定义为 extern 时,也会创建内存空间
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
/*
const int n = 10; // 不会创建内存空间,相当于宏定义
printf("n addr = %p\n", &n); // 取 const 变量的地址时会创建内存空间
return 0;
*/
/*
// C++ 中 const 的特性:在定义时不会创建内存空间,取地址时会创建内存空间
const int x = 10; // 在符号表中创建 x,即没有在栈中开辟空间
int *p = (int *)&x; // 在栈中开辟空间,p 指针指向,空间的值是 x 符号表中的数据
*p = 100; // 修改的是栈中的空间,而不是符号表中的数据
cout << "x = " << x << endl;
cout << "*p = " << *p << endl;
*/
// 如果 const 变量初始化为一个变量时,则会在栈中开辟空间
int x = 20; // 在栈中开辟空间,存储常量 20
const int X = x; // 在符号表中创建 X,并且赋值变量,此时在栈中开辟空间,存储常量 20
int *p = (int *)&X; // p 指向了 x 的地址,但是 x 是 const,所以 p 不能修改 x 的值
*p = 100; // 会修改栈中的空间,而不是符号表中的数据,因此 X 的值会改变
cout << "x = " << x << endl;
cout << "X = " << X << endl;
cout << "*p = " << *p << endl; // *p = 100
return 0;
}
+13
View File
@@ -0,0 +1,13 @@
#include <iostream>
using namespace std;
int x = 200;
int main()
{
int x = 100;
cout << "x = " << x << endl;
// ::x 表示全局的 x
cout << "全局的 x = " << ::x << endl;
return 0;
}
+57
View File
@@ -0,0 +1,57 @@
// 命名空间
#include <iostream>
using namespace std;
namespace A
{
// 声明变量成员,可以指定初始化
int x = 10;
}
namespace B
{
int x = 20;
}
namespace C
{
// 命名空间的嵌套
namespace AA
{
int x = 100;
}
namespace BB
{
int x = 200;
}
}
namespace D
{
int x = 1;
void show_x() // 定义函数
{
cout << "D namespace x: " << x << endl;
}
int add(int y); // 声明函数
}
int D::add(int y)
{
// 可以返回当前命名空间的所有成员
return x + y;
}
int main()
{
cout << "A x = " << A::x << endl;
cout << "B x = " << B::x << endl;
cout << "C-AA x = " << C::AA::x << endl;
cout << "C-BB x = " << C::BB::x << endl;
// 调用 D 的 show_x() 函数
D::show_x();
// 调用 D 的 add(int) 函数
cout << "D::add(100) = " << D::add(100) << endl;
return 0;
}
+16
View File
@@ -0,0 +1,16 @@
// 无名命名空间
// 无名命名空间的作用域为当前文件
#include <iostream>
using namespace std;
namespace
{
int x = 10;
}
int main(int argc, char const *argv[])
{
cout << "x = " << x << endl; // x 在当前文件中任意位置都可以访问
return 0;
}
+34
View File
@@ -0,0 +1,34 @@
// 命名空间的使用
#include <iostream>
using namespace std; // 当前位置向下,可以访问 std 命名空间中的所有成员
namespace A
{
int a = 10;
}
namespace B
{
int a = 20;
}
namespace C
{
int a = 30;
}
int main(int argc, char const *argv[])
{
using namespace A;
cout << "A::a = " << a << endl; // 10
// using namespace B;
using B::a; // 替换了当前位置的 a
cout << "B::a = " << a << endl; // 20
// using namespace C;
cout << "C::a = " << C::a << endl; // 30
return 0;
}
+23
View File
@@ -0,0 +1,23 @@
#include <iostream>
using namespace std;
// 函数的重载,和函数名、返回值类型、参数列表有关
// 函数名相同,参数列表不同(个数、类型、顺序),构成重载
namespace A
{
int add(int a, int b) { return a + b; }
float add(int a, float b) { return a * 2.0f + b; }
double add(int a, double b) { return a * 3.0 + b; }
int add(int a, int b, int c) { return a + b + c; }
}
int main()
{
// 目的:调用 A 命名空间中的 add 函数
using A::add;
// 调用函数时,编译器会根据参数列表的类型,自动匹配对应的函数
cout << "add(1, 1.5f) = " << add(1, 1.5f) << endl;
cout << "add(1, 1.5) = " << add(1, 1.5) << endl;
cout << "add(1, 3) = " << add(1, 3) << endl;
return 0;
}
+15
View File
@@ -0,0 +1,15 @@
#include <stdio.h>
// c 语言中可以使用无类型的函数参数
// C++ 中不允许使用无类型的函数参数 (对照 d7.cpp)
void show(x)
{
printf("x = %d\n", (int)x);
}
int main()
{
show(20);
show(15.0);
return 0;
}
+16
View File
@@ -0,0 +1,16 @@
#include <iostream>
using namespace std;
// c 语言中可以使用无类型的函数参数 (对照 d7.c)
// C++ 中不允许使用无类型的函数参数
void show(int x)
{
cout << "x = " << (int)x << endl;
}
int main()
{
show(20);
show(15.0);
return 0;
}
+27
View File
@@ -0,0 +1,27 @@
// C++ 中不同类型的变量之间赋值时,需要明确的使用强制类型转换
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
typedef enum COLOR
{
GREEN = 1,
RED = 5,
BLUE // 6
} color;
int main()
{
int a = 129;
char b = a; // 隐式类型转换(大类型转换为小类型)(不安全)
cout << "b = " << (int)b << endl; // -127
// C++ 中必须使用强制类型转换,明确数据类型
char *p = (char *)malloc(32); // malloc 返回值是 void *,需要强制类型转换
// char *p = malloc(32); // malloc 返回值是 void *,需要强制类型转换
strcpy(p, "hello world");
cout << "p = " << p << endl; // p 为指针,输出的是地址的内容
return 0;
}
+18
View File
@@ -0,0 +1,18 @@
// C++ 中使用 结构体 不需要加 struct
#include <iostream>
using namespace std;
struct S
{
int id;
char name[30];
};
int main()
{
// struct S s1 = {1, "张三"}; // C 语言中使用结构体需要加 struct
S s1 = {1, "张三"}; // C++ 中使用结构体不需要加 struct
cout << "s1.id = " << s1.id << "\ns1.name = " << s1.name << endl;
return 0;
}
+34
View File
@@ -0,0 +1,34 @@
#include <iostream>
using namespace std;
namespace Circle
{
float r;
float s();
}
float Circle::s()
{
return 3.14 * r * r;
}
namespace Range
{
int w, h;
int s();
}
int Range::s()
{
return w * h;
}
int main()
{
cout << "输入半径:";
cin >> Circle::r;
float s1 = Circle::s();
cout << "面积: " << s1;
return 0;
}
+44
View File
@@ -0,0 +1,44 @@
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
typedef struct file_node_s
{
char filename[32];
int filesize;
file_node_s *next;
} FileNode;
int main()
{
FileNode *head = NULL;
FileNode *fn1 = (FileNode *)malloc(sizeof(FileNode));
strcpy(fn1->filename, "数学");
fn1->filesize = 1000;
FileNode *fn2 = (FileNode *)malloc(sizeof(FileNode));
strcpy(fn2->filename, "语文");
fn2->filesize = 1200;
FileNode *fn3 = (FileNode *)malloc(sizeof(FileNode));
strcpy(fn3->filename, "英语");
fn3->filesize = 1150;
head = fn1;
fn1->next = fn3;
fn3->next = fn2;
fn2->next = NULL;
FileNode *p = head;
while (p != NULL)
{
cout << "文件名: " << p->filename << ", 文件大小: " << p->filesize << endl;
p = p->next;
}
free(fn1);
free(fn2);
free(fn3);
free(head);
return 0;
}
+24
View File
@@ -0,0 +1,24 @@
#include <iostream>
#include <cmath>
using namespace std;
const float PI = 3.14159;
double Area(double a, double b)
{
return PI * pow(a, 2) * b / 360;
}
double Area(double a)
{
return PI * pow(a, 2);
}
int main(int argc, char const *argv[])
{
double r, x;
cout << "请输入半径和角度: " << endl;
cin >> r >> x;
cout << "半径为 " << r << ", 角度为 " << x << " 的扇形面积为: " << Area(r, x) << endl;
cout << "半径为 " << r << ", 的圆的面积为: " << Area(r) << endl;
return 0;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

+289
View File
@@ -0,0 +1,289 @@
## 二、STL容器II
### 2.1 queue 容器
#### 2.1.1 queue概念
> Queue 是一种先进先出(First In First Out,FIFO)的数据结构,它有两个出口,queue
> 容器允许从一端新增元素,从另一端移除元素。
![image-20230804074147635](./readme.assets/image-20230804074147635.png)
#### 2.1.2 queue 没有迭代器
Queue 所有元素的进出都必须符合”先进先出”的条件,只有 queue 的顶端元素,才
有机会被外界取用。Queue 不提供遍历功能,也不提供迭代器。
#### 2.1.3 常用API
##### 2.1.3.1 构造函数
```c++
queue<T> queT; //queue 采用模板类实现,queue 对象的默认构造形式:
queue(const queue &que);//拷贝构造函数
```
##### 2.1.3.2 存取、插入和删除
```c++
void push(elem); //往队尾添加元素
void pop(); //从队头移除第一个元素
T back(); //返回最后一个元素
T front(); //返回第一个元素
```
##### 2.1.3.3 赋值与大小
```c++
queue& operator=(const queue &que);//重载等号操作符
empty();//判断队列是否为空
size();//返回队列的大小
```
### 2.2 list 容器
#### 2.2.1 list 概念
list(链表)是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。
每个结点包括两个部分:
```
1)存储数据元素的数据域,
2)存储下一个结点地址的指针域
```
list与vector的比较:
```
1) 相对于vector 的连续线性空间,list 就显得负责许多,每次插入或者删除一个元素,就是配置或者释放一个元素的空间。不浪费多余的空间,且插入与移除元素的操作是常数时间(稳定)。
2list和vector 是两个最常被使用的容器, 但list是由双向链表实现的。
3)list插入操作和删除操作都不会造成原有 list 迭代器的失效。 【重要特性】
```
<img src="./readme.assets/image-20230804075335829.png" width="400">
list特点:
```
1)采用动态存储分配,不会造成内存浪费和溢出
2)链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素
3)链表灵活,但是空间和时间额外耗费较大
```
#### 2.2.2 list 的迭代器
List 不能像 vector 一样以普通指针作为迭代器,因为其节点不能保证在同一块连续的内存空间上。。List 迭代器必须有能力指向 list 的节点,并有能力进行正确的递增、递减、取值、成员存取操作。**递增**时指向下一个节点,**递减**时指向上一个节点,**取值**时取的是节点的数据值,**成员取用**时取的是节点的成员。
另外,list 是一个双向链表,迭代器必须能够具备前移、后移的能力,所以 list 容器提供的是 Bidirectional Iterators.(双向的迭代器)。
List 有一个重要的性质,插入操作和删除操作都不会造成原有 list 迭代器的失效。
<font color=red>【注意】list的迭代器,不支持`+n`操作。</font>
#### 2.2.3 list 数据结构
> list 容器不仅是一个双向链表,而且还是一个循环的双向链表。
#### 2.2.4 常用API
##### 2.2.4.1 构造函数
```c++
list<T> lstT;//list 采用采用模板类实现,对象的默认构造形式:
list(beg,end);//构造函数将[beg, end)区间中的元素拷贝给本身。
list(n,elem);//构造函数将 n 个 elem 拷贝给本身。
list(const list &lst);//拷贝构造函数
```
##### 2.2.4.2 插入和删除
```c++
push_back(elem);//在容器尾部加入一个元素
pop_back();//删除容器中最后一个元素
push_front(elem);//在容器开头插入一个元素
pop_front();//从容器开头移除第一个元素
insert(pos,elem);//在 pos 位置插 elem 元素的拷贝,返回新数据的位置。
insert(pos,n,elem);//在 pos 位置插入 n 个 elem 数据,无返回值。
insert(pos,beg,end);//在 pos 位置插入[beg,end)区间的数据,无返回值。
clear();//移除容器的所有数据
erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos);//删除 pos 位置的数据,返回下一个数据的位置。
remove(elem);//删除容器中所有与 elem 值匹配的元素
```
##### 2.2.4.3 大小
```c++
size();//返回容器中元素的个数
empty();//判断容器是否为空
resize(num);//重新指定容器的长度为 num, 若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除
resize(num, elem);
```
##### 2.2.4.4 赋值
```c++
assign(beg, end); //将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem); //将 n 个 elem 拷贝赋值给本身。
list& operator=(const list &lst); //重载等号操作符
swap(lst); //将 lst 与本身的元素互换。
```
##### 2.2.4.5 读取
```
front();//返回第一个元素。
back();//返回最后一个元素
```
##### 2.2.4.6 反转和排序
```
reverse(); //反转链表
sort(); //list 排序
```
### 2.3 set/multiset 容器
#### 2.3.1 set概念
set 的特性是所有元素都会根据元素的键值自动被排序。
set 的元素即是键值又是实值, 不允许两个元素有相同的键值。
set 的 iterator 是一种 const_iterator 不允许修改set的键值。
set 拥有和 list 某些相同的性质,当对容器中的元素进行插入操作或者删除操作的
时候,操作之前的迭代器,在操作完成之后依然有效,被删除的那个元素的迭代器必然是一个例外。
#### 2.3.2 set数据结构
multiset 特性及用法和 set 完全相同,唯一的差别在于它允许键值重复。set 和multiset 的底层实现是红黑树,红黑树为平衡二叉树的一种。
二叉树就是任何节点最多只允许有两个字节点。分别是左子结点和右子节点:
<img src="./readme.assets/image-20230804083406386.png" width="300">
二叉搜索树,是指二叉树中的节点按照一定的规则进行排序,使得对二叉树中元素访问更加高效:
<img src="./readme.assets/image-20230804083459911.png" width=400>
二叉搜索树的放置规则是:
任何节点的元素值一定大于其左子树中的每一个节点的元素值,并且小于其右子树的值。因此从根节点一直向左走,一直到无路可走,即得到最小值,一直向右走,直至无路可走,可得到最大值。那么在二叉搜索树中找到最大元素和最小元素是非常简单的事情。
如上图所示:那么当一个二叉搜索树的左子树和右子树不平衡的时候,那么搜索依据上图表示,搜索 9 所花费的时间要比搜索 17 所花费的时间要多,由于我们的输入或者经过我们插入或者删除操作,二叉树失去平衡,造成搜索效率降低。
<img src="./readme.assets/image-20230804083751044.png" width=400>
#### 2.3.3 常用API
##### 2.3.3.1 构造函数
```c++
set<T> st;//set 默认构造函数:
mulitset<T> mst; //multiset 默认构造函数:
set(const set &st);//拷贝构造函数
```
##### 2.3.3.2 赋值和大小
```c++
set& operator=(const set &st);//重载等号操作符
swap(st);//交换两个集合容器
size();//返回容器中元素的数目
empty();//判断容器是否为空
```
##### 2.3.3.3 插入和删除
```
insert(elem); //在容器中插入元素。
clear(); //清除所有元素
erase(pos); //删除 pos 迭代器所指的元素,返回下一个元素的迭代器。
erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(elem); //删除容器中值为 elem 的元素。
```
##### 2.3.3.4 查找
```c++
find(key); //查找键 key 是否存在,若存在,返回该键的元素的迭代器;若不存在,返
回 set.end();
count(key);//查找键 key 的元素个数
lower_bound(keyElem);//返回第一个 key>=keyElem 元素的迭代器。
upper_bound(keyElem);//返回第一个 key>keyElem 元素的迭代器。
equal_range(keyElem);//返回容器中 key 与 keyElem 相等的上下限的两个迭代器。
```
##### 2.3.3.5 set 排序规则
> set自动排序, 但可以改变它的排序规则,默认从小到大。
自定义排序规则,可以使用struct或class, 声明 `bool operator(v1, v2)`仿函数重载。
#### 2.3.4 对组(pair)
对组(pair)将一对值组合成一个值,这一对值可以具有不同的数据类型,两个值可
以分别用 pair 的两个公有属性 first 和 second 访问。
```
类模板:template <class T1, class T2> struct pair
```
用法一:
```c++
pair<string, int> pair1(string("name"), 20);
cout << pair1.first << endl;
cout << pair1.second << endl;
```
用法二:
```c++
pair<string, int> pair2 = make_pair("name", 30);
cout << pair2.first << endl;
cout << pair2.second << endl;
```
用法三:
```c++
pair<string, int> pair3 = pair2;
cout << pair3.first << endl;
cout << pair3.second << endl;
```
### 2.4 map/multimap 容器
Map 的特性是所有元素都会根据元素的键值自动排序。
Map 所有的元素都是pair,同时拥有实值和键值,pair 的第一元素被视为键值,第二元素被视为实值,map 不允许两个元素有相同的键值。
multimap 和 map 的操作类似,唯一区别 multimap 键值可重复。
map 和 multimap 都是以红黑树为底层实现机制。
+33
View File
@@ -0,0 +1,33 @@
// 函数对象
// 仿函数: 一元,二元仿函数
#include <iostream>
using namespace std;
// 一元仿函数
class A
{
public:
A(int n) : n(n) {}
int n;
// 重载 operator() 运算符,只要调用 A 对象的 (int x) ,就会给对象的对应成员对象加一个 x
A &operator()(int i)
{
this->n += i;
return *this;
}
};
void print(A a, int n) // A a = A(30)
{
a(n);
cout << "a.n = " << a.n << endl;
}
int main()
{
// 打印 a 对象的值加额外的值的结果
print(A(20), 3); // A(20) 会创建一个匿名对象
return 0;
}
+59
View File
@@ -0,0 +1,59 @@
// 谓词
// gt 大于, ge 大于等于
// lt 小于, le 小于等于
// eq 等于, ne 小于等于
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
class GTFive // 一元谓词
{
public:
bool operator()(int n)
{
return n > 5;
}
};
class GT // 二元谓词
{
public:
bool operator()(const int &n1, const int &n2)
{
return n1 > n2;
}
};
void printGTF(GTFive gtf, int *p, int size)
{
for (int i = 0; i < size; i++)
{
if (gtf(p[i]))
cout << p[i] << " ";
}
cout << endl;
}
void print(int *p, int size, GT gt, int n)
{
for (int i = 0; i < size; i++)
{
if (gt(p[i], n))
cout << p[i] << " ";
}
cout << endl;
}
int main()
{
int ms[] = {1, 2, 4, 7, 9, 20};
cout << "大于 5 的元素" << endl;
printGTF(GTFive(), ms, 6);
cout << "大于 7 的元素" << endl;
print(ms, 6, GT(), 7);
return 0;
}
+39
View File
@@ -0,0 +1,39 @@
// 算术类函数对象
// 算术类函数对象
#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
// template <typename T>
void print(typename set<int>::const_iterator start,
typename set<int>::const_iterator end, plus<int> pl, int m)
{
for (; start != end; start++)
{
cout << pl(*start, m) << " ";
}
cout << endl;
}
void print(typename set<int>::const_iterator start,
typename set<int>::const_iterator end, multiplies<int> mul, int m)
{
for (; start != end; start++)
{
cout << mul(*start, m) << " ";
}
cout << endl;
}
int main()
{
int m[] = {1, 2, 3, 4, 8, 5, 1, 2};
// set 会自动过滤重复,并排序
set<int> s(m, m + sizeof(m) / sizeof(m[0]));
print(s.begin(), s.end(), plus<int>(), 1);
print(s.begin(), s.end(), multiplies<int>(), 3);
return 0;
}
+59
View File
@@ -0,0 +1,59 @@
#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
// template <typename T>
void print(typename set<int>::const_iterator start,
typename set<int>::const_iterator end, plus<int> pl, int m)
{
for (; start != end; start++)
{
cout << pl(*start, m) << " ";
}
cout << endl;
}
void print(typename set<int>::const_iterator start,
typename set<int>::const_iterator end, multiplies<int> mul, int m)
{
for (; start != end; start++)
{
cout << mul(*start, m) << " ";
}
cout << endl;
}
void show(int n)
{
cout << n << " ";
}
// 二元仿函数
class PrintPlus : public binary_function<int, int, void>
{
public:
void operator()(const int &n1, const int &n2) const
{
cout << n1 << "+" << n2 << " = " << n1 + n2 << endl;
}
};
int main()
{
int m[] = {1, 2, 3, 4, 8, 5, 1, 2};
// set 会自动过滤重复,并排序
set<int> s(m, m + sizeof(m) / sizeof(m[0]));
// print(s.begin(), s.end(), plus<int>(), 1);
// print(s.begin(), s.end(), multiplies<int>(), 3);
// for_each(s.begin(), s.end(), show);
// cout << endl;
// PrintPlus 测试
// for (int i = 0; i < 6; i++)
for_each(s.begin(), s.end(), bind1st(PrintPlus(), i));
return 0;
}
+25
View File
@@ -0,0 +1,25 @@
#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
class PrintGt5Adapter : public binary_function<int, int, void>
{
public:
void operator()(const int &n1, const int &n2) const
{
if (n1 > n2)
cout << n1 << " ";
}
};
int main()
{
int m[] = {1, 2, 3, 4, 8, 5, 1, 2};
set<int> s(m, m + sizeof(m) / sizeof(m[0]));
for_each(s.begin(), s.end(), bind2nd(PrintGt5Adapter(), 2));
return 0;
}
+43
View File
@@ -0,0 +1,43 @@
// 取反适配器
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 自定义一个适配器,只需要容器中元素即可。
class GT5 : public unary_function<int, bool>
{
public:
bool operator()(const int &n) const
{
return n > 5;
}
};
class GTN : public binary_function<int, int, bool>
{
public:
bool operator()(const int &n1, const int &n2) const
{
return n1 > n2;
}
};
int main()
{
int m[] = {1, 2, 2, 3, 5, 10};
vector<int> v;
v.assign(m, m + sizeof(m) / sizeof(m[0]));
// find_if(start, end, _callback) 返回查找到的第一个迭代器的位置
vector<int>::iterator ret = find_if(v.begin(), v.end(), not1(bind2nd(greater<int>(), 3)));
cout << *ret << endl;
ret = find_if(v.begin(), v.end(), GT5());
cout << *ret << endl;
ret = find_if(v.begin(), v.end(), bind2nd(GTN(), 3));
cout << *ret << endl;
return 0;
}
+26
View File
@@ -0,0 +1,26 @@
// 函数指针适配
// 使用 ptr_fun<>() 适配函数指针
// <> 中的第一个参数是函数指针的类型,第二个参数是函数指针的参数类型,第三个参数是函数指针的返回值类型
// bind1st() 和 bind2nd() 适配函数对象
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool gtn(int n1, int n2)
{
return n1 > n2;
}
int main()
{
int m[] = {1, 2, 2, 3, 5, 10};
vector<int> v;
v.assign(m, m + sizeof(m) / sizeof(m[0]));
vector<int>::iterator ret = find_if(v.begin(), v.end(), bind2nd(ptr_fun<int, int, bool>(gtn), 3));
cout << *ret << endl;
return 0;
}
+39
View File
@@ -0,0 +1,39 @@
// mem_fn 有两个重载版本:
// 用法1mem_fn(&MyClass::printMessage) 用于将成员函数转换为函数对象
// 用法2mem_fn(&MyClass::printMessage)(&obj, "hello world") 用于调用成员函数
// mem_fn 是一个函数模板,它接受一个成员函数指针或成员函数引用,并返回一个函数对象,该对象可以调用相应的成员函数。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Stu
{
private:
string name;
int age;
public:
Stu(const string &name, int age) : name(name), age(age) {}
public:
void show()
{
cout << "name is " << name << ", age is " << age << endl;
}
};
int main()
{
vector<Stu> vs;
vs.push_back(Stu("disen", 18));
vs.push_back(Stu("lucy", 20));
vs.push_back(Stu("jack", 15));
vs.push_back(Stu("mack", 19));
// 遍历容器中所有成员,成员函数作为仿函数时,则通过容器成员调用它的仿函数
for_each(vs.begin(), vs.end(), mem_fun_ref(&Stu::show));
return 0;
}
+30
View File
@@ -0,0 +1,30 @@
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
using namespace std::placeholders;
int main()
{
int m[] = {1, 2, 2, 3, 5, 10};
vector<int> v;
v.assign(m, m + sizeof(m) / sizeof(m[0]));
int target = 3;
// 使用 std::bind 适配 std::equal_to
vector<int>::iterator ret = adjacent_find(v.begin(), v.end(), bind(equal_to<int>(), _1, 3));
cout << *(++ret) << endl;
if (ret != v.end())
{
cout << "Found adjacent elements equal to " << target << "." << endl;
}
else
{
cout << "No adjacent elements equal to " << target << " found." << endl;
}
return 0;
}
+27
View File
@@ -0,0 +1,27 @@
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
template <typename T>
void print(const list<T> &lst)
{
for (typename list<T>::const_iterator it = lst.begin(); it != lst.end(); ++it)
cout << *it << ' ';
cout << endl;
}
int main()
{
list<int> lst1(6, 5); // 6 个 5
print(lst1);
string s1 = "abcdefg";
// 将 string 字符串转换为 list
list<char> lst2(s1.begin(), s1.end());
print(lst2);
return 0;
}
+36
View File
@@ -0,0 +1,36 @@
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
template <typename T>
void print(const list<T> &lst)
{
for (typename list<T>::const_iterator it = lst.begin(); it != lst.end(); ++it)
cout << *it << ' ';
cout << endl;
}
int main()
{
string s = "abcdefg";
// 将 string 字符串转换为 list
list<char> l(s.begin(), s.end());
int size = l.size(); // 获取大小
print(l);
// list 手写逆序
list<char>::iterator it = l.begin(); // 迭代器指向第一个元素
for (int i = 0; i < size; i++) // 逆序 size 次
{
it = l.insert(it, l.back()); // 将最后一个元素插入到第一个元素之前
it++; // 迭代器指向下一个元素
l.pop_back(); // 删除最后一个元素
}
print(l);
return 0;
}
+35
View File
@@ -0,0 +1,35 @@
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
template <typename T>
void print(const list<T> &lst)
{
for (typename list<T>::const_iterator it = lst.begin(); it != lst.end(); ++it)
cout << *it << ' ';
cout << endl;
}
int main()
{
string s = "abcdefg";
list<char> l(s.begin(), s.end());
// 删除 cde
// list<char>::iterator it = find(l.begin(), l.end(), 'c');
// l.erase(it, find(l.begin(), l.end(), 'e'));
list<char>::iterator it = l.begin(); // 迭代器指向第一个元素
for (int i = 0; i < 2; i++) // 迭代器指向第三个元素
it++;
list<char>::iterator it2 = it; // 迭代器指向第三个元素
for (int i = 0; i < 3; i++) // 迭代器指向第六个元素
it2++;
l.erase(it, it2); // 删除第三个到第五个元素
print(l); // a b f g
return 0;
}
+32
View File
@@ -0,0 +1,32 @@
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
template <typename T>
void print(const list<T> &lst)
{
for (typename list<T>::const_iterator it = lst.begin(); it != lst.end(); ++it)
cout << *it << ' ';
cout << endl;
}
int main()
{
string s = "abcdefg";
list<char> l(s.begin(), s.end());
print(l);
l.reverse(); // 逆序
print(l);
int m[] = {6, 4, 2, 0, 8, 6, 4};
list<int> l2(m, m + 7);
print(l2);
l2.sort(); // 排序
print(l2);
l2.reverse(); // 逆序
print(l2);
return 0;
}
+26
View File
@@ -0,0 +1,26 @@
#include <iostream>
#include <map>
using namespace std;
int main()
{
map<int, string> ms;
// 1. insert()函数
// map 在插入时会自动根据 map 的键来排序
ms.insert(pair<int, string>(1, "张三")); // pair<int, string>是map<int, string>::value_type的类型
ms.insert(pair<int, string>(4, "李四"));
ms.insert(make_pair(3, "王五")); // make_pair()函数可以自动推导出类型
ms.insert(map<int, string>::value_type(2, "赵六")); // value_type是map<int, string>的类型
ms[5] = "田七"; // 通过下标的方式插入数据
map<int, string>::iterator it = ms.begin();
for (; it != ms.end(); it++)
{
// cout << "sid = " << it->first << ",name = " << it->second << endl;
cout << "sid = " << (*it).first << ",name = " << (*it).second << endl;
}
return 0;
}
+61
View File
@@ -0,0 +1,61 @@
// 使用 map 来解决括号匹配
#include <iostream>
#include <map>
#include <stack>
#include <string>
using namespace std;
string left_c = "{[(";
map<char, char> map1;
bool valid(const char *p)
{
stack<char> stk;
int max_depth = 0;
while (*p)
{
const char &cp = *p;
// if (left_c.find(cp) != string::npos) // 如果当前拿到的是左括号
if (left_c.find(cp) != -1) // 如果当前拿到的是左括号
{
// 入栈
stk.push(*p);
}
else // 如果当前拿到的是右括号
{
// 弹栈
if (stk.empty())
return false;
const char &top = stk.top();
if (map1[cp] != top)
return false;
// 当前左右匹配的后续操作
// 求最大深度
if (max_depth < stk.size())
max_depth = stk.size();
// 弹栈前判断最大深度
stk.pop();
}
p++;
}
cout << "当前括号栈的最大深度为: " << max_depth << endl;
return stk.empty();
}
int main()
{
map1.insert(make_pair('}', '{'));
map1.insert(make_pair(']', '['));
map1.insert(make_pair(')', '('));
cout << valid("{[()]}[[[[[()]]]]]") << endl;
cout << valid("{[())}") << endl;
return 0;
}
+15
View File
@@ -0,0 +1,15 @@
#include <iostream>
#include <map>
using namespace std;
int main()
{
map<int, string> m;
m.insert(make_pair(1, "disen"));
m.insert(make_pair(2, "lucy"));
cout << m.size() << endl;
m.erase(1); // 删除键值为 1 的元素
cout << m.size() << endl;
return 0;
}
+26
View File
@@ -0,0 +1,26 @@
#include <iostream>
#include <map>
using namespace std;
int main()
{
map<int, string> m;
m.insert(make_pair(1, "disen"));
m.insert(make_pair(2, "lucy"));
m.insert(make_pair(3, "jack"));
map<int, string>::const_iterator it = m.find(3);
if (it == m.end())
{
cout << "未查找到" << endl;
}
else
{
const pair<int, string> &p = *it;
cout << p.first << ", " << p.second << endl;
}
return 0;
}
View File
+32
View File
@@ -0,0 +1,32 @@
#include <iostream>
#include <set>
using namespace std;
template <typename T>
void print(const set<T> &s)
{
for (typename set<T>::const_iterator it = s.begin(); it != s.end(); ++it)
cout << *it << ' ';
cout << endl;
}
template <typename T>
void print(const multiset<T> &s)
{
for (typename multiset<T>::const_iterator it = s.begin(); it != s.end(); ++it)
cout << *it << ' ';
cout << endl;
}
int main()
{
int m[] = {1, 2, 3, 2, 3, 4};
set<int> s(m, m + 6);
print(s); // set 会自动去重,输出 1 2 3 4
multiset<int> ms(m, m + 6);
print(ms); // multiset 不会自动去重,输出 1 2 2 3 3 4
return 0;
}
+50
View File
@@ -0,0 +1,50 @@
#include <iostream>
#include <set>
using namespace std;
template <typename T>
void print(const set<T> &s)
{
for (typename set<T>::const_iterator it = s.begin(); it != s.end(); ++it)
cout << *it << ' ';
cout << endl;
}
int main()
{
int m[] = {5, 12, 16, 21, 22, 27, 29, 30};
set<int> s(m, m + 8);
print(s); // set 键值自动排序,且不重复
// 查看大于等于 22 值的所有元素
cout << "查看大于等于 22 值的所有元素: " << endl;
set<int>::iterator it = s.lower_bound(22); // 返回第一个大于等于 22 的元素的迭代器
while (it != s.end())
{
cout << *it << ' ';
++it;
}
cout << endl;
// 查找小于等于 22 值的所有元素
cout << "查找小于等于 22 值的所有元素: " << endl;
// it = s.upper_bound(22); // 返回第一个大于 22 的元素的迭代器
// for (; it != s.begin();)
// {
// --it;
// cout << *it << ' ';
// }
// cout << endl;
// 查找小于等于 22 值的所有元素(另一种写法)
it = s.lower_bound(22);
while (it != s.begin())
{
--it;
cout << *it << ' ';
}
cout << endl;
return 0;
}
+36
View File
@@ -0,0 +1,36 @@
// 自定义排序
#include <iostream>
#include <set>
using namespace std;
// 自定义规则
template <typename T>
class MySort
{
public:
bool operator()(const T &a, const T &b)
{
return a > b; // 从小到大排序
}
};
int main()
{
// 使用 set 时,添加自定义排序规则
set<int, MySort<int> > s1;
s1.insert(20);
s1.insert(30);
s1.insert(1);
s1.insert(8);
set<int, MySort<int> >::iterator it = s1.begin(); // <int, MySort<int>> 可以省略
while (it != s1.end())
{
cout << *it << ' ';
++it;
}
cout << endl;
return 0;
}
+59
View File
@@ -0,0 +1,59 @@
// 自定义排序
#include <iostream>
#include <set>
using namespace std;
// 自定义规则
template <typename T>
class MySort
{
public:
bool operator()(const T &a, const T &b)
{
return a > b; // 从小到大排序
}
};
class Student
{
public:
string name;
int age;
float score;
public:
Student(const string &name, int age, float score)
{
this->name = name;
this->age = age;
this->score = score;
}
};
class MyStudentByAgeSort
{
public:
bool operator()(const Student &s1, const Student &s2)
{
return s1.age > s2.age;
}
};
class MyStudentByScoreSort
{
public:
bool operator()(const Student &s1, const Student &s2)
{
return s1.score > s2.score;
}
};
int main()
{
Student[] *stus = new Student[3]{Student("张三", 18, 100), Student("李四", 20, 90), Student("王五", 19, 95)};
set<Student, MyStudentByAgeSort> s2;
s2............................
return 0;
}
+12
View File
@@ -0,0 +1,12 @@
#include <iostream>
#include <set>
using namespace std;
int main()
{
// pair 是一个模板类,有两个模板参数,
// 用于存储两个数据,可以分别指定两个数据的类型
pair<int, string> p1(1, "张三");
return 0;
}
+40
View File
@@ -0,0 +1,40 @@
// 对组(pair)
// 将一对值组合成一个值,这一对值可以具有不同的数据类型,两个值可
// 以分别用 pair 的两个公有属性 first 和 second 访问。
// 类模板:template<class T1, class T2> class pair
// 用法一:
// pair<string, int> pair1(string("name"), 20);
// cout << pair1.first << endl;
// cout << pair1.second << endl;
// 用法二:
// pair<string, int> pair2 = make_pair("name", 30);
// cout << pair2.first << endl;
// cout << pair2.second << endl;
// 用法三:
// pair<string, int> pair3 = pair2; // 拷贝构造函数
// cout << pair3.first << endl;
// cout << pair3.second << endl;
// 如:
#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
int main()
{
pair<int, string> p1(1, "disen");
pair<int, string> p2 = make_pair(2, "lucy");
cout << "id = " << p1.first << ", name = " << p1.second << endl;
cout << "id = " << p2.first << ", name = " << p2.second << endl;
return 0;
}
+78
View File
@@ -0,0 +1,78 @@
// Classroom exercises: 课堂练习
// ce
// 类的定义和使用
#include <iostream>
#include <cstring>
using namespace std;
class Person
{
public:
void init(const char *iname, int iage);
void setName(const char sname[]);
void setAge(int sage);
const char *getname();
const int getAge();
const void show();
private:
char name[32];
int age;
};
void Person::init(const char *iname, int iage)
{
strcpy(this->name, iname);
if (iage > 0 && iage < 100)
this->age = iage;
else
{
this->age = 0;
cout << "年龄超出范围,拒绝赋值!" << endl;
}
}
void Person::setName(const char sname[])
{
strcpy(this->name, sname);
}
void Person::setAge(int sage)
{
if (sage > 0 && sage < 100)
this->age = sage;
else
{
cout << "年龄超出范围,拒绝赋值!" << endl;
}
}
const char *Person::getname()
{
return this->name;
}
const int Person::getAge()
{
return this->age;
}
const void Person::show()
{
cout << "name = " << this->name << ", age = " << this->age << endl;
}
int main()
{
Person p1;
p1.setAge(20);
p1.setName("flykhan");
p1.show();
Person p2;
p2.init("hello", 0);
p2.show();
return 0;
}
+30
View File
@@ -0,0 +1,30 @@
// 引用的使用
// 引用的本质是指针常量,所以引用的空间大小和指针相同,都是 8 个字节
// 引用的本质是指针常量,所以引用的指向不能改变,但是指向的值可以改变
// 引用的本质是指针常量,所以引用在定义时必须初始化,且不能再引用其他变量
// int a = 10;
// int &aa = a; // int * const aa = &a;
#include <iostream>
using namespace std;
int main()
{
// 定义引用时,必须给初始化值,另外,定义之后引用不能再引用其他变量
int a = 10;
int &b = a; // 对 a 的引用
b += 20; // 相当于 a += 20
cout << "a: " << a << " b: " << b << endl;
int &c = a;
cout << "a: " << a << " b: " << b << " c: " << c << endl;
int &d = b;
cout << "a: " << a << " b: " << b << " c: " << c << " d: " << d << endl;
int x = 100;
c = x;
cout << "c: " << c << endl;
return 0;
}
+30
View File
@@ -0,0 +1,30 @@
#include <iostream>
using namespace std;
void f(int a, int)
{
cout << "f(int, int )" << endl;
}
void f(double, int)
{
cout << "f(double, int)" << endl;
}
void f(int a)
{
cout << "f(int)" << endl;
}
void f(double a)
{
cout << "f(double)" << endl;
}
int main()
{
f(1);
f(1.0, 2);
return 0;
}
+6
View File
@@ -0,0 +1,6 @@
#include "area.h"
double S(double r)
{
return r * r * 3.1415926;
}
+15
View File
@@ -0,0 +1,15 @@
#ifndef __AREA_H__
#define __AREA_H__
// 条件编译
#if __cplusplus
extern "C"
{
#endif
double S(double r);
#if __cplusplus
}
#endif
#endif
+12
View File
@@ -0,0 +1,12 @@
#include <iostream>
#include "area.h"
using namespace std;
int main()
{
double r = 2.5;
double s = S(r);
cout << "S(2.5) = " << s << endl;
return 0;
}
+26
View File
@@ -0,0 +1,26 @@
#include <iostream>
using namespace std;
// 增强的结构体(c 中结构体中只有变量)
struct Person
{
int pid;
int age;
void show() // C++ 的结构体中可以加函数
{
// 可以访问同一结构体内的成员变量
cout << "pid = " << pid << ", age = " << age << endl;
}
};
int main()
{
Person p1 = {1001, 21};
p1.show();
Person p2 = {1002, 19};
p2.show();
return 0;
}
+44
View File
@@ -0,0 +1,44 @@
// 类
#include <iostream>
#include <cstring>
using namespace std;
namespace SA
{
class Student
{
public:
int sid = 14; // 默认值设定,需要 c++11 标准以上
char name[32] = "hello";
private:
float score = 90;
public:
void showScore(); // 声明类方法
void addScore(float n) { this->score = n; }
};
// 实现类中的方法(函数)
void Student::showScore()
{
cout << "sid = " << this->sid << ", name = " << this->name << ", score = " << this->score << endl;
}
};
using namespace SA;
int main()
{
Student s1;
strcpy(s1.name, "flykhan");
s1.sid = 1001;
s1.addScore(100);
s1.showScore();
Student s2;
s2.showScore();
return 0;
}
+81
View File
@@ -0,0 +1,81 @@
// 立方体类与应用
#include <iostream>
using namespace std;
class Cube
{
public:
void init(int l, int w, int h)
{
this->a = l;
this->b = w;
this->c = h;
}
int S(); // 面积
int V(); // 体积
void show();
bool isEqual(Cube &tmp);
private:
int a; // 长
int b; // 宽
int c; // 高
};
int Cube::S()
{
return 2 * (a * b + a * c + b * c);
}
int Cube::V()
{
return a * b * c;
}
void Cube::show()
{
cout << "S = " << S() << ", V = " << V() << endl;
}
bool Cube::isEqual(Cube &tmp)
{
// if (this->a == tmp.a && this->b == tmp.b && this->c == tmp.c)
if (this->S() == tmp.S() && this->V() == tmp.V())
return true;
else
return false;
}
bool equalCube(Cube &c1, Cube &c2)
{
if (c1.S() == c2.S() && c1.V() == c2.V())
return true;
return false;
}
const char *resBool(bool b) // bool 数字值转换人类可读
{
if (b != 0)
return "true";
return "false";
}
int main()
{
Cube c1, c2, c3;
c1.init(2, 3, 4);
cout << "c1: " << endl;
c1.show();
c2.init(3, 4, 5);
cout << "c2: " << endl;
c2.show();
c3.init(4, 2, 3);
cout << "Cube::isEqual(c2) = " << resBool(c1.isEqual(c2)) << endl;
cout << "equalCube(c1, c2) = " << resBool(equalCube(c1, c3)) << endl;
return 0;
}
+83
View File
@@ -0,0 +1,83 @@
// 点和圆的关系
#include <iostream>
#include <cmath>
using namespace std;
enum Pos_e
{
onCircle = 4, // 点在圆上
inCircle, // 点在圆内
outCircle // 点在圆外
};
class Point
{
public:
int x, y;
};
class AdvCircle
{
public:
int init(int x0, int y0, int r)
{
this->r = r;
o.x = x0;
o.y = y0;
}
Pos_e at(Point &point);
private:
int r;
Point o; // 圆心点
};
Pos_e AdvCircle::at(Point &point)
{
int distence = pow((point.x - this->o.x), 2) + pow((point.y - this->o.y), 2);
int rr = r * r;
if (distence == rr)
{
return onCircle;
}
else if (distence < rr)
{
return inCircle;
}
else
return outCircle;
}
string posToString(Pos_e pos)
{
switch (pos)
{
case onCircle:
return "在圆上";
break;
case inCircle:
return "在圆内";
break;
case outCircle:
return "在圆外";
break;
default:
break;
}
}
int main()
{
AdvCircle c1;
c1.init(0, 0, 2);
Point p1;
p1.x = 1;
p1.y = 1;
cout << "c1.at(p1) " << posToString(c1.at(p1)) << endl;
return 0;
}
+23
View File
@@ -0,0 +1,23 @@
// 引用相当于变量的别名
#include <iostream>
using namespace std;
int main()
{
int arr[5] = {1, 2, 3, 4, 5};
// 给 arr 设置一个别名(引用)
// 先定义 5 个元素数组类型的别名
typedef int ArrRef[5];
ArrRef &a = arr;
// 通过别名操作数组
for (int i = 0; i < 5; i++)
{
cout << a[i] << " ";
}
cout << endl;
return 0;
}
+21
View File
@@ -0,0 +1,21 @@
// 数组引用的方法二
#include <iostream>
using namespace std;
int main()
{
int arr[5] = {1, 2, 3, 4, 5};
// 直接定义 5 个元素数组类型的引用
int(&a)[5] = arr;
// 通过别名操作数组
for (int i = 0; i < 5; i++)
{
cout << a[i] << " ";
}
cout << endl;
return 0;
}
+23
View File
@@ -0,0 +1,23 @@
#include <iostream>
using namespace std;
// 引用传递: 会改变实参的值
// 值传递: 不会改变实参的值
void cumsum(int &total, int n) // total 是引用传递,n 是值传递
{
total += n;
}
int main()
{
int total = 0;
int n = 0;
while (cin >> n)
{
cumsum(total, n);
cout << "total = " << total << endl;
if (total > 100)
break;
}
}
+28
View File
@@ -0,0 +1,28 @@
#include <iostream>
#define N 10 // 定义常量
using namespace std;
typedef int TenArr[N];
TenArr &new_arr()
{
static int m[N] = {0}; // 全局静态区存储,程序结束后才释放
for (int i = 0; i < N; i++)
{
m[i] = i;
}
return m;
}
int main()
{
TenArr &p = new_arr();
int i = 0;
while (i < N)
{
cout << "p[" << i << "] = " << p[i++] << endl;
}
return 0;
}
+57
View File
@@ -0,0 +1,57 @@
#include <iostream>
#define N 7
using namespace std;
void sort(int (&arr)[N])
{
for (int i = 0; i <= N - 1; i++)
{
for (int j = 0; j <= N - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
arr[j] ^= arr[j + 1];
arr[j + 1] ^= arr[j];
arr[j] ^= arr[j + 1];
// int temp = arr[j];
// arr[j] = arr[j + 1];
// arr[j + 1] = temp;
}
}
}
}
void sort(int arr[], int size)
{
for (int i = 0; i < size - 1; i++)
{
for (int j = 0; j < size - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main()
{
int nums[] = {1, 5, 2, 0, 9, 10, 7};
int size = sizeof(nums) / sizeof(nums[0]);
sort(nums);
// sort(nums, size);
for (int i = 0; i < size; i++)
{
cout << nums[i] << "\t";
}
cout << endl;
return 0;
}
+29
View File
@@ -0,0 +1,29 @@
// 指针的引用
// 为指针取个别名,相当于'指针的指针'
#include <iostream>
#include <cstdlib>
using namespace std;
struct STU
{
int sid;
float score;
};
void set_score(STU *&q, int sid, float score)
{
q->sid = sid;
q->score = score;
}
int main()
{
STU *p = (STU *)malloc(sizeof(STU));
set_score(p, 1, 99);
cout << "sid = " << p->sid << ", score = " << p->score << endl;
return 0;
}
+30
View File
@@ -0,0 +1,30 @@
// 指针的引用
// 为指针取个别名,相当于'指针的指针'
#include <iostream>
#include <cstdlib>
using namespace std;
struct STU
{
int sid;
float score;
};
// 指针的指针
void set_score(STU **q, int sid, float score)
{
(*q)->sid = sid;
(*q)->score = score;
}
int main()
{
STU *p = (STU *)malloc(sizeof(STU));
set_score(&p, 2, 98);
cout << "sid = " << p->sid << ", score = " << p->score << endl;
return 0;
}
+28
View File
@@ -0,0 +1,28 @@
// 常量引用
// 相当于 常量指针常量
// 用法: const 数据类型 &变量名 = 其他变量或常量
// 注意:
// 一般的引用不能赋值常量(字面量),但是 const 引用可以赋值常量
#include <iostream>
using namespace std;
int main()
{
int x = 10;
const int &x1 = x;
// error: assignment of read - only reference x1
x1 -= 5; // const 修饰的引用不能修改内容
cout << "x = " << x << endl;
const int &x2 = 50;
cout << "x2 = " << x2 << endl;
// error: invalid initialization of non-const reference of type int& from an rvalue of type int
int &x3 = 'a'; // 常量不能赋值给非常量引用
cout << "x3 = " << x3 << endl;
return 0;
}
+26
View File
@@ -0,0 +1,26 @@
// 内联函数
// 函数前面添加了 inline 关键字,则此函数为内联函数
// 内联函数只能在当前文件中使用,相当于函数前面加 static
// 内联函数一般用于替换 有参的宏,有参宏经常会出错,而且参数是无数据类型
// 每一次使用内联函数时,都会像有参宏一样,展开一次(内联函数不入栈,运行效率高,编译时会提前处理)
#include <iostream>
using namespace std;
#define ADD(x, y) x + y
// 内联函数
inline int add(int a, int b)
{
return a + b;
}
int main()
{
int ret1 = ADD(10, 20) * 10;
cout << "ret = " << ret1 << endl;
int ret2 = add(10, 20) * 10;
cout << "ret = " << ret2 << endl;
return 0;
}
+30
View File
@@ -0,0 +1,30 @@
// 函数的默认参数
#include <iostream>
using namespace std;
bool isSs(int n = 10) // 判断 n 是否为质数
{
int i = 2;
for (; i < n / 2; i++)
{
if (n % i == 0)
return false; // 0 为假
}
return true; // 非 0 为真
}
double area(double r = 1.0) // 求面积
{
return 3.14 * r * r;
}
int main()
{
cout << "isSS(7) is " << isSs(7) << endl;
cout << "isSS() is " << isSs() << endl;
cout << "area() is " << area() << endl;
cout << "area(2) is " << area(2) << endl;
return 0;
}
+13
View File
@@ -0,0 +1,13 @@
// 找错
#include <iostream>
using namespace std;
int main()
{
const int n = 10;
const int &p = n;
// p++; // 错误,不能修改常量引用所引用的值
cout << "n=" << n << endl;
return 0;
}
+14
View File
@@ -0,0 +1,14 @@
#include <iostream>
using namespace std;
int func1(int a, int, int b = 20)
{
return a + b;
}
int main()
{
cout << func1(10, 30) << endl;
cout << func1(10, 10, 100) << endl;
}
+21
View File
@@ -0,0 +1,21 @@
// 1. 2. 创建一个名为 Rectangle 的类,具有成员变量 width 和 height,以及成员函数 double calculateArea() ,用于计算矩形的面积。
#include <iostream>
using namespace std;
class Rectangle
{
public:
double calculateArea()
{
return width * height;
}
int width, height;
};
int main()
{
return 0;
}
+20
View File
@@ -0,0 +1,20 @@
// 1. 2. 创建一个名为 Circle 的类,具有成员变量 radius 和 pi(圆周率),以及成员函数 double calculateArea() ,用于计算圆的面积。
#include <iostream>
using namespace std;
class Circle
{
public:
double radius, pi = 3.1415926;
double calculateArea()
{
return pi * radius * radius;
}
};
int main()
{
return 0;
}
+24
View File
@@ -0,0 +1,24 @@
// 1. 2. 创建一个名为 BankAccount 的类,具有成员变量 accountNumber 和 balance,以及成员函数 void deposit(double amount) 和 void withdraw(double amount) ,用于存款和取款操作。
#include <iostream>
using namespace std;
class BankAccount
{
public:
long accountNumber, balance;
void deposit(double amount)
{
this->balance += amount;
}
void withdraw(double amount)
{
this->balance -= amount;
}
};
int main()
{
return 0;
}
+21
View File
@@ -0,0 +1,21 @@
// 创建一个名为 Student 的类,具有成员变量 name 和 grade,以及成员函数 void study(char *course) ,用于表示某班级的某学生正在学习某一门课程。
#include <iostream>
using namespace std;
class Student
{
public:
char name[32]; // 学生姓名
char grade[32]; // 班级名
void study(char *course)
{
cout << this->grade << "班的" << this->name << "同学正在学习" << course << endl;
}
};
int main()
{
return 0;
}
+35
View File
@@ -0,0 +1,35 @@
// 创建一个名为 Car 的类,具有成员变量 brand 和 speed,以及成员函数 void accelerate() 和 void brake() ,用于加速和刹车操作。
#include <iostream>
#include <string>
using namespace std;
class Car
{
public:
string brand;
int speed;
void accelerate()
{
this->speed += 1;
cout << "加速 1 码" << endl;
}
void brake()
{
if (this->speed > 0)
{
this->speed -= 1;
cout << "减速中" << endl;
}
else
{
cout << "车已经停下了" << endl;
}
}
};
int main()
{
return 0;
}
+22
View File
@@ -0,0 +1,22 @@
// 1. 2. 创建一个名为 Employee 的类,具有成员变量 name、id 和 salary,以及成员函数 void displayInfo() ,用于显示员工的信息。
#include <iostream>
using namespace std;
class Employee
{
public:
string name;
int id;
int salary;
void displayinfo()
{
cout << "员工信息\nid: " << this->id << "\t姓名: " << this->name << "\t薪水: " << this->salary << endl;
}
};
int main()
{
return 0;
}
+58
View File
@@ -0,0 +1,58 @@
// 创建一个名为 Book 的类,具有成员变量 title、author 和 year,以及成员函数 void displayInfo() ,用于显示图书的信息。 创建Book类的数组,至少存放5本书,并设计全局函数,实现Book对象按year从大到小排序,并显示排序后信息。
#include <iostream>
using namespace std;
class Book
{
public:
string title, author;
int year;
// 使用 const 加 & 引用,避免不必要的拷贝
void init(const string &title, const string &author, int year)
{
this->title = title;
this->author = author;
this->year = year;
}
void displayinfo()
{
cout << "书名: " << this->title << " , 作者: " << this->author << " , 出版年份: " << this->year << endl;
}
};
void sortAndShow(Book book[], int n)
{
int i = 0;
for (; i < n; i++)
{
for (int j = 0; j < n - i - 1; j++)
{
if (book[j].year < book[j + 1].year)
{
Book tmp = book[j];
book[j] = book[j + 1];
book[j + 1] = tmp;
}
}
}
for (i = 0; i < n; i++)
{
book[i].displayinfo();
}
}
int main()
{
Book books[5];
books[0].init("数学", "张三", 1998);
books[1].init("语文", "李四", 2009);
books[2].init("英语", "王五", 1987);
books[3].init("物理", "赵六", 2008);
books[4].init("化学", "郑七", 1982);
sortAndShow(books, 5);
return 0;
}
+74
View File
@@ -0,0 +1,74 @@
// 对象的构造与析构
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
class Animal
{
public:
Animal();
Animal(const char *name, const char *food);
~Animal(); // 析构函数(对象回收时,清理资源)
public:
void eat();
void say(const char *msg);
private:
char *name, *food;
};
Animal::Animal()
{
name = (char *)malloc(32);
food = (char *)malloc(32);
strcpy(name, "小动物");
strcpy(food, "");
}
Animal::Animal(const char *name, const char *food)
{
this->name = (char *)malloc(32);
this->food = (char *)malloc(32);
strcpy(this->name, name);
strcpy(this->food, food);
}
Animal::~Animal()
{
cout << name << "空间回收" << endl;
// 回收在构造函数(初始化)中动态分配的空间
free(name);
free(food);
}
void Animal::eat()
{
cout << name << "吃: " << food << endl;
}
void Animal::say(const char *msg)
{
cout << name << "遇到主人: " << msg << endl;
}
int main()
{
// 尽量使用堆空间创建类的对象: 使用 类指针 和 new 关键字
Animal *anm1 = new Animal();
anm1->eat();
// 使用栈空间的情况
Animal anm2;
anm2.say("小浣熊");
// 使用括号
Animal anm3("小黄", "");
anm3.eat();
anm3.say("旺旺...");
return 0;
}
+60
View File
@@ -0,0 +1,60 @@
// 深拷贝和浅拷贝
// 深拷贝举例
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
class Person
{
private:
char *name;
int age;
public:
Person(const char *name, int age)
{
this->name = (char *)malloc(32);
strcpy(this->name, name);
this->age = age;
}
Person(const Person &obj) // 深拷贝,重写构造方法
{
this->name = (char *)malloc(32);
strcpy(this->name, obj.name);
this->age = obj.age;
}
~Person()
{
if (name != NULL)
{
free(name);
}
}
public:
void setName(char *name)
{
strcpy(this->name, name);
}
void show()
{
cout << this << " " << name << ", " << age << endl;
}
};
int main()
{
Person p1("disen", 20);
Person p2 = p1;
p2.setName("lucy");
Person p3 = Person(p2);
p3.setName("Jack");
p1.show();
p2.show();
p3.show();
return 0;
}
+27
View File
@@ -0,0 +1,27 @@
// 多个对象的构造和析构
// 初始化列表
#include <iostream>
using namespace std;
class A
{
private:
int x, y, z;
// char *name;
string name; // char * 建议替换为 string
public:
A(int x, int y, int z, const string &name) : x(x), y(y), z(z), name(name) {}
void show()
{
cout << x << ", " << y << ", " << z << ", " << name << endl;
}
};
int main()
{
A a1(10, 20, 4, "disen");
a1.show();
return 0;
}
+48
View File
@@ -0,0 +1,48 @@
// 多个对象的构造和析构
// 类对象作为成员
#include <iostream>
using namespace std;
class A
{
public:
A()
{
cout << "A()" << endl;
}
A(int x)
{
cout << "A(int x)" << endl;
}
~A()
{
cout << "~A()" << endl;
}
};
class B
{
public:
B() // 构造函数用于初始化成员数据,说明成员变量先创建
{
cout << "B()" << endl;
}
B(int x)
{
cout << "B(int x)" << endl;
}
~B() // A 的对象在 B 的空间中,A 对象在 B 空间释放之后就失效,失效也会释放空间(调用析构函数)
{
cout << "~B()" << endl;
}
private:
A a; // A 类的对象作为 B 类的成员
};
int main()
{
B b1;
return 0;
}
+50
View File
@@ -0,0 +1,50 @@
// 多个对象的构造和析构
// 类对象作为成员
// d12 的改造测试
#include <iostream>
using namespace std;
class A
{
public:
A()
{
cout << "A()" << endl;
}
A(int x)
{
cout << "A(int x)" << endl;
}
~A()
{
cout << "~A()" << endl;
}
};
class B
{
public:
B() // 构造函数用于初始化成员数据,说明成员变量先创建
{
cout << "B()" << endl;
}
// 成员名:(参数名)
B(int x) : a(x) // 指定 a 对象的构造函数进行数据初始化
{
cout << "B(int x)" << endl;
}
~B() // A 的对象在 B 的空间中,A 对象在 B 空间释放之后就失效,失效也会释放空间(调用析构函数)
{
cout << "~B()" << endl;
}
private:
A a; // A 类的对象作为 B 类的成员
};
int main()
{
B b1(1);
return 0;
}
+43
View File
@@ -0,0 +1,43 @@
// explicit 关键字(禁止隐式转换)
#include <iostream>
using namespace std;
class Person
{
private:
int age;
string name;
public:
Person(const char *name, int age = 18)
{
this->name = name;
this->age = age;
}
// explicit 使得不存在从 "int" 转换到 "Person" 的适当构造函数
explicit Person(int age) // 进制 Person p = 值
{
this->age = age;
this->name = "disen";
}
public:
void show()
{
cout << name << ", " << age << endl;
}
};
int main()
{
Person p1 = "jack";
Person p2 = Person("doken", 9);
Person p3 = Person(1);
// Person p4 = 2; // 不存在从 "int" 转换到 "Person" 的适当构造函数
p1.show();
p2.show();
p3.show();
return 0;
}
+51
View File
@@ -0,0 +1,51 @@
// 动态创建对象(malloc / realloc / calloc 在堆中创建空间, new 关键字)
#include <iostream>
#include <cstdlib>
using namespace std;
class A
{
private:
int x;
public:
A(int x)
{
this->x = x;
cout << "A(int)" << endl;
}
~A()
{
cout << "~A()" << endl;
}
public:
void init(int x)
{
this->x = x;
cout << "init(int)" << endl;
}
void clean()
{
cout << "clean()" << endl;
}
};
int main()
{
// 1) 使用 malloc 方式创建
// cout << "A size is " << sizeof(A) << endl;
// A *a1 = (A *)malloc(sizeof(A));
// // a1->A(20); // 不允许显式调用构造函数
// a1->init(20); // 初始化数据
// a1->clean(); // 释放数据的空间
// a1->~A(); // 析构函数可以显式调用
// free(a1);
// 2) new 方式创建,delete释放
A *a1 = new A(1);
delete a1; // 用完之后直接 delete 释放空间
return 0;
}
+23
View File
@@ -0,0 +1,23 @@
// 扩展 new 和 delete
// 数组的 new 和 delete
#include <iostream>
using namespace std;
int main()
{
// 使用拓展的 new 创建类对象数组
int *p = new int[6]{1, 2, 3, 4, 5, 6};
for (int i = 0; i < 10; i++)
{
cout << *(p + i) << endl;
}
delete[] p; // 释放数组空间
cout << "--------------------" << endl;
for (int i = 0; i < 10; i++)
{
cout << *(p + i) << endl;
}
return 0;
}
+43
View File
@@ -0,0 +1,43 @@
#include <iostream>
#include <cstdlib>
using namespace std;
class A
{
private:
string name;
public:
A()
{
cout << "A()" << endl;
name = "no name";
}
A(const string &name)
{
cout << "A(const string &name)" << endl;
this->name = name;
cout << "name: " << name << endl;
}
~A()
{
cout << name << "~A()" << endl;
}
};
int main()
{
// A *p = new A[5];
// delete[] p;
// A *p2 = new A[4]{A("a"), A("b"), A("c"), A("d")};
// delete[] p2; // 释放数组中成员对象时,从高(地址)到低(地址)依次释放
A *a = new A("abc");
free(a); // 只是放指针指向的堆空间,不会调用对象的析构函数
char *a2 = (char *)malloc(sizeof(A));
delete a2; // 可以删除简单的 void* 指针
return 0;
}
+35
View File
@@ -0,0 +1,35 @@
// 构造函数的分类与调用
// 拷贝构造函数
#include <iostream>
using namespace std;
class A
{
public:
int x;
public:
A() {}
A(A &other) // 拷贝构造函数
{
this->x = other.x;
}
};
int main()
{
A a1; // 调用无参的构造函数进行初始化 a1 对象
a1.x = 10;
cout << "a1 x = " << a1.x << endl;
A a2(a1); // 使用拷贝构造
cout << "a2 x = " << a2.x << endl;
A *a3 = new A(); // 使用指针和new,在堆空间创建对象
// a3->x = 20;
cout << "a3 x = " << a3->x << endl;
return 0;
}
+44
View File
@@ -0,0 +1,44 @@
// 构造函数的分类与调用
#include <iostream>
using namespace std;
class B
{
private:
int n;
public:
// B() { cout << "B()" << endl; }
B(int n)
{
cout << "B(int n)" << endl;
this->n = n;
}
B(const B &other)
{
cout << "B(B &other)" << endl;
this->n = other.n;
}
public:
void showN()
{
cout << "n = " << n << endl;
}
};
int main()
{
B b1 = 20; // 隐式调用 B(int n), B(20), 只创建一个对象
B b2 = B(30); // 显式调用 B(int n)
B b3 = b2; // 隐式调用 B(B &other)
B &b4 = b3; // 不会创建空间,只是一个别名
B b5(b4); // 显式调用 B(B &other)
return 0;
}
+56
View File
@@ -0,0 +1,56 @@
// 构造函数的分类与调用
#include <iostream>
#include <bitset>
using namespace std;
class C
{
private:
int x, y;
public:
C(int x)
{
this->x = x;
}
C(int x, int y)
{
this->x = x;
this->y = y;
}
C(const C &other)
{
this->x = other.x;
this->y = other.y;
}
void show()
{
cout << "x = " << x << ", y = " << y << endl;
}
~C()
{
cout << this << "释放资源" << endl;
}
};
int main()
{
cout << "C(0,1) 之前" << endl;
C(0, 1); // 匿名创建的类对象,创建完后就直接释放了
cout << "C(0,1) 之后" << endl;
C c1(1, 2);
c1.show();
C c2 = (1, 5); // 使用单参数构造函数 C(int x), 然后将其改为 ", 运算" 后面的值
// C c2 = 1;
c2.show();
C c3 = C(3, 4);
c3.show();
C c4(c3);
c4.show();
C &c5 = c4;
c5.show();
return 0;
}
+54
View File
@@ -0,0 +1,54 @@
// 创建类对象的指针
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
class A
{
public:
char *msg;
public:
A()
{
this->msg = (char *)malloc(30);
strcpy(this->msg, "haha");
}
A(const char *msg)
{
this->msg = (char *)malloc(30);
strcpy(this->msg, msg);
}
~A()
{
cout << this << "release msg : " << this->msg << endl;
free(this->msg);
// free(this);
}
};
int main()
{
A *a1 = new A;
cout << "a1->msg: " << a1->msg << endl;
A *a2 = new A("disen 666");
cout << "a2->msg: " << a2->msg << endl;
// 【注意】指针释放空间时, 不会自动执行对象的析构函数
// 可以通过手动调用 对象的析构方法 或使用 delete
a1->~A();
free(a1);
// a2->~A();
// delete a1;
delete a2;
A a3;
// 注意: delete 只能删除 new 出来的对象,即对象的指针
// A &a4 = a3;
// delete &a4;
return 0;
}
+57
View File
@@ -0,0 +1,57 @@
// 拷贝构造函数的调用时机
// 编译器优化,不会调用拷贝构造函数,而是直接创建一个返回值的引用
#include <iostream>
using namespace std;
class A
{
public:
int x = 0;
public:
A()
{
cout << this << " A()" << endl;
}
A(const A &other)
{
this->x = other.x;
cout << this << " A(const A &other)" << endl;
}
~A()
{
cout << this << " ~A()" << endl;
}
};
void test1(A a) // ?是否调用拷贝构造函数
{
cout << "test1(A a) a.x = " << a.x << endl;
// 当函数结束时,a 释放,会调用析构函数
}
A test2()
{
A a1; // 局部的类对象, 没有执行拷贝构造函数
a1.x = 1;
cout << "test2() a1.x = " << a1.x << endl;
return a1; // 释放局部对象 a1
}
void test3()
{
A a2 = test2(); // 返回 A 类的对象,没有调用拷贝构造函数,只是创建了一个 test2() 返回值的引用
cout << "test3() a2.x = " << a2.x << endl;
}
int main()
{
A a0;
// test1(a0); // 作为值传递,调用拷贝构造函数
test3();
cout << "over" << endl;
return 0;
}
+60
View File
@@ -0,0 +1,60 @@
// 拷贝构造函数的调用时机
// 编译器优化,不会调用拷贝构造函数,而是直接创建一个返回值的引用
#include <iostream>
using namespace std;
class A
{
public:
int x = 0;
public:
A()
{
cout << this << " A()" << endl;
}
A(const A &other)
{
this->x = other.x;
cout << this << " A(const A &other)" << endl;
}
~A()
{
cout << this << " ~A()" << endl;
}
};
void test1(A &a) // ?是否调用拷贝构造函数
// void test1(A a) // ?是否调用拷贝构造函数
{
cout << "test1(A a) a.x = " << a.x << endl;
// 当函数结束时,a 释放,会调用析构函数
}
A test2() // 不要声明为 A &test2(), 因为返回对象时,会释放局部对象,导致返回的引用指向一个已经释放的对象
{
A a1; // 局部的类对象, 没有执行拷贝构造函数
a1.x = 1;
cout << "test2() a1.x = " << a1.x << endl;
return a1; // 释放局部对象 a1
}
void test3()
{
cout << "tsss = " << endl;
A a2 = test2(); // 返回 A 类的对象,没有调用拷贝构造函数,只是创建了一个 test2() 返回值的引用
cout << "test3() a2.x = " << a2.x << endl;
}
int main()
{
A a0;
test1(a0); // 作为值传递,调用拷贝构造函数
// test3();
cout << "over" << endl;
return 0;
}
+30
View File
@@ -0,0 +1,30 @@
// 构造函数的调用规则
#include <iostream>
using namespace std;
class A
{
public:
int x, y;
void show()
{
cout << this << " x = " << x << ", y = " << y << endl;
}
};
int main()
{
A a1;
// A a2 = a1; // 自动调用拷贝构造函数 A(const A&obj)
a1.x = 20;
A a2 = a1; // 自动调用拷贝构造函数 A(const A&obj)
a1.y = 30;
// A a2 = a1; // 自动调用拷贝构造函数 A(const A&obj)
a1.show(); // 20,30 浅拷贝
a2.show(); //
return 0;
}
+51
View File
@@ -0,0 +1,51 @@
// 深拷贝和浅拷贝
// 浅拷贝举例
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
class Person
{
private:
char *name;
int age;
public:
Person(const char *name, int age)
{
this->name = (char *)malloc(32);
this->age = age;
}
void release_name_pointer()
{
free(name);
}
public:
void setName(char *name)
{
strcpy(this->name, name);
}
void show()
{
cout << name << ", " << age << endl;
}
};
int main()
{
Person p1("disen", 20);
Person p2 = p1;
Person p3 = Person(p2);
p3.setName("Jack");
p1.show();
p2.show();
p3.show();
// p1.release_name_pointer();
p2.release_name_pointer();
return 0;
}
+34
View File
@@ -0,0 +1,34 @@
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
class SLink
{
private:
char *title;
public:
SLink() {}
SLink(const char *title)
{
this->title = (char *)malloc(50);
strcpy(this->title, title);
}
~SLink();
void show()
{
cout << title << endl;
}
};
SLink::~SLink() {}
int main()
{
SLink s1;
SLink s2("disen 补课中");
s2.show();
return 0;
}
+27
View File
@@ -0,0 +1,27 @@
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
class Color
{
private:
int r, g, b;
public:
explicit Color(int r, int g = 0, int b = 0) : r(r), g(g), b(b)
{
}
void show()
{
cout << r << "," << g << "," << b << endl;
}
};
int main()
{
Color c = Color(2, 3, 4);
c.show();
return 0;
}
+32
View File
@@ -0,0 +1,32 @@
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
class Point
{
private:
int x, y;
public:
Point(int x, int y);
void show()
{
cout << x << "," << y << endl;
}
};
Point::Point(int x, int y)
{
this->x = x;
this->y = y;
}
int main()
{
Point *p1 = new Point[3]{Point(1, 2), Point(2, 3), Point(3, 4)};
p1[2].show();
delete[] p1;
return 0;
}
+52
View File
@@ -0,0 +1,52 @@
// 设计一个学生类,包括学号、姓名、成绩,并设计接口函数用来输出这些学生数据并计算平均分。并编写main函数进行测试:
// 输出如:
// 学号 姓名 成绩 1 张XX 98 2 王XX 90 3 XXX 89 平均成绩: XX
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <iomanip>
using namespace std;
class Student
{
private:
int sid;
string name;
float score;
public:
Student(int sid, const string &name, float score) : sid(sid), name(name), score(score)
{
}
~Student() {}
public:
static void avgAndShow(Student *stus, int n);
};
void Student::avgAndShow(Student *stus, int n)
{
float avg = 0.0f;
cout << "学号\t"
<< "姓名\t"
<< "成绩" << endl;
for (int i = 0; i < n; i++)
{
cout << stus[i].sid << "\t" << stus[i].name << "\t" << stus[i].score << endl;
avg += stus[i].score / n;
}
cout << "平均成绩: " << setprecision(3) << avg << endl;
}
int main()
{
Student *stus = new Student[3]{
Student(1, "张XX", 98),
Student(2, "王XX", 90),
Student(3, "XXX", 89)};
Student::avgAndShow(stus, 3);
return 0;
}
+148
View File
@@ -0,0 +1,148 @@
// 创建一个名为 LinkedList 的类,实现链表的基本操作,包括插入节点、删除节点和反转链表等。
// 【提示】单向链表
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
class Node
{
public:
int data;
Node *next;
public:
Node(int value)
{
this->data = value;
this->next = NULL;
}
};
class LinkedList
{
private:
Node *head;
public:
LinkedList()
{
head = NULL; // 初始头结点
}
public:
Node *insertNode(int insValue);
Node *deleteNode(int delValue);
Node *reverseLinkedList();
void print();
};
Node *LinkedList::insertNode(int insValue)
{
Node *newNode = new Node(insValue);
if (NULL == head)
head = newNode;
Node *p = head;
while (p->next != NULL)
{
p = p->next;
}
p->next = newNode;
return head;
}
Node *LinkedList::deleteNode(int delValue)
{
if (NULL == head)
{
cout << "不存在链表,删除失败" << endl;
return head;
}
if (head->data == delValue) // 当删除的节点是头节点时
{
Node *temp = head;
head = head->next;
delete temp;
return head;
}
Node *p = head;
while (p->next != NULL)
{
if (p->next->data == delValue)
{
Node *temp = p->next;
p->next = temp->next;
delete temp;
}
p = p->next;
}
if (p != NULL && p->data == delValue) // 处理最后一个节点的情况
{
delete p;
p = NULL;
}
return head;
}
Node *LinkedList::reverseLinkedList()
{
Node *p = head;
Node *new_head = NULL;
Node *p_next = NULL;
while (p != NULL)
{
p_next = p->next;
p->next = new_head;
new_head = p;
p = p_next;
}
head = new_head; // 新头指针
return head;
}
void LinkedList::print()
{
Node *p = head;
while (p != NULL)
{
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
int main()
{
LinkedList list;
// 插入节点
list.insertNode(1);
list.insertNode(3);
list.insertNode(8);
list.insertNode(2);
// 测试打印
cout << "原始链表: ";
list.print();
cout << endl;
// 删除节点
list.deleteNode(3);
cout << "删除3后的链表: ";
list.print();
cout << endl;
// 反转链表
list.reverseLinkedList();
cout << "反序链表后: ";
list.print();
cout << endl;
return 0;
}

Some files were not shown because too many files have changed in this diff Show More