docs(book): 添加现代 C++教程及相关代码

- 新增现代 C++ 教程的 Preface 章节,包括英文和中文版本
- 添加 C++ Primer 练习代码
- 新增 Learn C++ 教程的 C++ 开发简介章节
- 添加头文件解析文档
- 更新 mkdocs.yml,包含新教程的目录结构
- 修改项目设置,使用 Python 3.10环境
This commit is contained in:
sairate 2025-07-08 09:52:45 +08:00
parent 4108f6c42d
commit fa9377e4ae
81 changed files with 43783 additions and 6 deletions

View File

@ -3,7 +3,9 @@
<component name="MaterialThemeProjectNewConfig"> <component name="MaterialThemeProjectNewConfig">
<option name="metadata"> <option name="metadata">
<MTProjectMetadataState> <MTProjectMetadataState>
<option name="userId" value="-3282f873:197ddb2289e:-7e4d" /> <option name="migrated" value="true" />
<option name="pristineConfig" value="false" />
<option name="userId" value="21c1c7ee:193388d497c:-7ff9" />
</MTProjectMetadataState> </MTProjectMetadataState>
</option> </option>
</component> </component>

View File

@ -0,0 +1,68 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的注释"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 注释"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 在代码中的加一些说明和解释,这些说明和解释就叫注释。\n",
"\n",
"② 注释能方便自己和其他程序员阅读代码。\n",
"\n",
"③ C++的注释,有两种格式:\n",
"\n",
"1. 单行注释: // 描述信息 \n",
" - note通常放在一行代码的上方或者一条语句的末尾对该行代码说明。\n",
"2. 多行注释: /* 描述信息 */ \n",
" - note编译器在编译代码时会忽略注释的内容即不会执行。"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,14 @@
# C++的注释
# 1. 注释
① 在代码中的加一些说明和解释,这些说明和解释就叫注释。
② 注释能方便自己和其他程序员阅读代码。
③ C++的注释,有两种格式:
1. 单行注释: // 描述信息
- note通常放在一行代码的上方或者一条语句的末尾对该行代码说明。
2. 多行注释: /* 描述信息 */
- note编译器在编译代码时会忽略注释的内容即不会执行。

View File

@ -0,0 +1,91 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的main函数"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. main函数"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① main函数是一个程序的入口\n",
"\n",
"② 每个程序都必须有这么一个函数,并且有且只有一个。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"//下面11行代码的含义就是在屏幕中输出一个 Hello World\n",
"\n",
"#include<iostream>\n",
"using namespace std;\n",
"\n",
"int main() {\n",
"\n",
" cout << \"hello C++\" << endl; //屏幕显示“hello C++”\n",
" system(\"pause\"); //按任意键继续,退出程序\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - hello C++ \n",
" - 请按任意键继续. . ."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,28 @@
# C++的main函数
# 1. main函数
① main函数是一个程序的入口
② 每个程序都必须有这么一个函数,并且有且只有一个。
```python
//下面11行代码的含义就是在屏幕中输出一个 Hello World
#include<iostream>
using namespace std;
int main() {
cout << "hello C++" << endl; //屏幕显示hello C++
system("pause"); //按任意键继续,退出程序
return 0;
}
```
运行结果:
- hello C++
- 请按任意键继续. . .

View File

@ -0,0 +1,91 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的打印"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 打印"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① cout << \"XXXX\" << endl; 会使得屏幕打印双引号里面的字符串。\n",
"\n",
"② system(\"pause\"); 会使得屏幕的打印界面暂停到该语句这里,按任意键后才会继续运行。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"//下面11行代码的含义就是在屏幕中输出一个 Hello World\n",
"\n",
"#include<iostream>\n",
"using namespace std;\n",
"\n",
"int main() {\n",
"\n",
" cout << \"hello C++\" << endl; //屏幕显示“hello C++”\n",
" system(\"pause\"); //按任意键继续,退出程序\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - hello C++\n",
" - 请按任意键继续. . ."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,28 @@
# C++的打印
# 1. 打印
① cout << "XXXX" << endl; 会使得屏幕打印双引号里面的字符串
② system("pause"); 会使得屏幕的打印界面暂停到该语句这里,按任意键后才会继续运行。
```python
//下面11行代码的含义就是在屏幕中输出一个 Hello World
#include<iostream>
using namespace std;
int main() {
cout << "hello C++" << endl; //屏幕显示hello C++
system("pause"); //按任意键继续,退出程序
return 0;
}
```
运行结果:
- hello C++
- 请按任意键继续. . .

View File

@ -0,0 +1,156 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的常量"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 常量"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 常量,用于记录程序中不可更改的数据。\n",
"\n",
"② C++定义常量两种方式,如下所示:\n",
"\n",
"1. #define 宏常量:#define 常量名 常量值 \n",
" - note通常在文件上方定义表示一个常量。\n",
"2. const修饰的变量 const 数据类型 常量名 = 常量值 \n",
" - note通常在变量定义前加关键字const修饰该变量为常量不可修改。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.1 #define 常量名 常量值"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"#define Day 7 \n",
"\n",
"int main()\n",
"{\n",
"\n",
" /*\n",
" Day = 14; //错误Day是常量一旦修改就会报错\n",
" cout << \"一周总共有:\" << Day << \"天\" << endl;\n",
" */\n",
"\n",
" cout << \"一周总共有:\" << Day << \"天\" << endl;\n",
"\n",
" // 输出语句cout << \"提示语\" << 变量 << endl; \n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 一周总共有7天 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.2 const 数据类型 常量名 = 常量值"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int main()\n",
"{\n",
" /*\n",
" const int month = 12;\n",
" month = 24; //错误const修饰的变量也称为常量\n",
" */\n",
"\n",
" int month = 12;\n",
" month = 24; //正确,这样可以修改变量的值\n",
"\n",
" cout << \"一年总共有:\" << month << \"个月\" << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 一年总共有24个月 \n",
" - 请按任意键继续. . ."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,74 @@
# C++的常量
# 1. 常量
① 常量,用于记录程序中不可更改的数据。
② C++定义常量两种方式,如下所示:
1. #define 宏常量:#define 常量名 常量值
- note通常在文件上方定义表示一个常量。
2. const修饰的变量 const 数据类型 常量名 = 常量值
- note通常在变量定义前加关键字const修饰该变量为常量不可修改。
## 1.1 #define 常量名 常量值
```python
#include <iostream>
using namespace std;
#define Day 7
int main()
{
/*
Day = 14; //错误Day是常量一旦修改就会报错
cout << "一周总共有:" << Day << "" << endl;
*/
cout << "一周总共有:" << Day << "" << endl;
// 输出语句cout << "提示语" << 变量 << endl;
system("pause");
return 0;
}
```
运行结果:
- 一周总共有7天
- 请按任意键继续. . .
## 1.2 const 数据类型 常量名 = 常量值
```python
#include <iostream>
using namespace std;
int main()
{
/*
const int month = 12;
month = 24; //错误const修饰的变量也称为常量
*/
int month = 12;
month = 24; //正确,这样可以修改变量的值
cout << "一年总共有:" << month << "个月" << endl;
system("pause");
return 0;
}
```
运行结果:
- 一年总共有24个月
- 请按任意键继续. . .

View File

@ -0,0 +1,100 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的变量"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 变量"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 变量的作用就是就是给一段指定的内存空间起名,方便操作这段内存。\n",
"\n",
"② 语法:数据类型 变量名 = 初始值;\n",
"\n",
"③ 变量存在的意义:方便我们管理内存空间。\n",
"\n",
"④ 每一段内存都有一个地址编号。\n",
"\n",
"⑤ C++规定在创建一个常量或变量时,必须要指出相应的数据类型,否则无法给变量分配内存。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int main()\n",
"{\n",
"\n",
" //变量创建的语法:数据类型 变量名 = 变量初始值\n",
" int a = 10; \n",
"\n",
" cout << \"a = \" << a << endl; // 输出语句 cout << \"提示语\" << 变量 << endl; \n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - a = 10\n",
" - 请按任意键继续. . ."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,37 @@
# C++的变量
# 1. 变量
① 变量的作用就是就是给一段指定的内存空间起名,方便操作这段内存。
② 语法:数据类型 变量名 = 初始值;
③ 变量存在的意义:方便我们管理内存空间。
④ 每一段内存都有一个地址编号。
⑤ C++规定在创建一个常量或变量时,必须要指出相应的数据类型,否则无法给变量分配内存。
```python
#include <iostream>
using namespace std;
int main()
{
//变量创建的语法:数据类型 变量名 = 变量初始值
int a = 10;
cout << "a = " << a << endl; // 输出语句 cout << "提示语" << 变量 << endl;
system("pause");
return 0;
}
```
运行结果:
- a = 10
- 请按任意键继续. . .

View File

@ -0,0 +1,143 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的关键字"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 关键字"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 关键字是C++中预先保留的单词(标识符)。\n",
"\n",
"② 在定义变量或者常量的时候,不要用关键字。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.1 int关键字"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int main()\n",
"{\n",
"\n",
" // int int = 10; // 错误第二个int是关键字不可以作为变量的名称\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.2 sizeof关键字"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① sizeof关键字可以统计数据类型所占内存大小。\n",
"\n",
"② sizeof关键字语法sizeof ( 数据类型 / 变量 )"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int main()\n",
"{\n",
"\n",
" cout << \"short 类型所占内存空间为:\" << sizeof(short) << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - short 类型所占内存空间为2 \n",
" - 请按任意键继续. . ."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,56 @@
# C++的关键字
# 1. 关键字
① 关键字是C++中预先保留的单词(标识符)。
② 在定义变量或者常量的时候,不要用关键字。
## 1.1 int关键字
```python
#include <iostream>
using namespace std;
int main()
{
// int int = 10; // 错误第二个int是关键字不可以作为变量的名称
system("pause");
return 0;
}
```
运行结果:
- 请按任意键继续. . .
## 1.2 sizeof关键字
① sizeof关键字可以统计数据类型所占内存大小。
② sizeof关键字语法sizeof ( 数据类型 / 变量 )
```python
#include <iostream>
using namespace std;
int main()
{
cout << "short 类型所占内存空间为:" << sizeof(short) << endl;
system("pause");
return 0;
}
```
运行结果:
- short 类型所占内存空间为2
- 请按任意键继续. . .

View File

@ -0,0 +1,116 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的标识符"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 标识符"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 标识符就是 C++ 给变量、常量的命名。\n",
"\n",
"② 标识符有一套自己的命名规则:\n",
"\n",
"1. 标识符不能使关键字。\n",
"2. 标识符只能由字母、数字、下划线组成。\n",
"3. 第一个字符必须为字母或下划线。\n",
"4. 标识符中字母区分大小写。\n",
"\n",
"③ 建议:给标识符命名时,争取做到见名知意,方便自己和他人的阅读。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int main()\n",
"{\n",
" //1、标识符不可以是关键字\n",
" //int int = 10; //报错\n",
" \n",
" //2、标识符由字母、数字、下划线构成\n",
" int abc = 10;\n",
" int _abc = 20;\n",
" int _123abc = 40;\n",
" \n",
" //3、标识符第一个字符只能是字母或下划线\n",
" //int 123abc = 50; //报错\n",
"\n",
" //4、标识符区分大小写\n",
" int aaa = 100;\n",
" //cout << AAA << endl; //报错AAA和aaa不是同一个名称\n",
"\n",
" //建议:给变量起名的时候,最好能够做到见名知意\n",
" int num1 = 10;\n",
" int num2 = 20;\n",
" int sum = num1 + num2; //建议用num1、num2、sum表示加法而不是用a、b、c来表示\n",
" cout << sum << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 30\n",
" - 请按任意键继续. . ."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,53 @@
# C++的标识符
# 1. 标识符
① 标识符就是 C++ 给变量、常量的命名。
② 标识符有一套自己的命名规则:
1. 标识符不能使关键字。
2. 标识符只能由字母、数字、下划线组成。
3. 第一个字符必须为字母或下划线。
4. 标识符中字母区分大小写。
③ 建议:给标识符命名时,争取做到见名知意,方便自己和他人的阅读。
```python
#include <iostream>
using namespace std;
int main()
{
//1、标识符不可以是关键字
//int int = 10; //报错
//2、标识符由字母、数字、下划线构成
int abc = 10;
int _abc = 20;
int _123abc = 40;
//3、标识符第一个字符只能是字母或下划线
//int 123abc = 50; //报错
//4、标识符区分大小写
int aaa = 100;
//cout << AAA << endl; //报错AAA和aaa不是同一个名称
//建议:给变量起名的时候,最好能够做到见名知意
int num1 = 10;
int num2 = 20;
int sum = num1 + num2; //建议用num1、num2、sum表示加法而不是用a、b、c来表示
cout << sum << endl;
system("pause");
return 0;
}
```
运行结果:
- 30
- 请按任意键继续. . .

View File

@ -0,0 +1,447 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的数据类型"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 数据类型"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.1 整形"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 作用:整型变量表示的是整数类型的数据。\n",
"\n",
"② C++中能够表示整形的类型有以下几种方式,区别在于所占内存空间不同。\n",
"\n",
"③ 数据类型 占用空间 取值范围\n",
"\n",
"1. short(短整型) 2字节 -2^15-2^15-1\n",
"2. int整型 4字节 -2^31-2^31-1\n",
"3. long(长整型) Windows为4字节Linux为4字节(32位)8字节(64位) -2^31-2^31-1\n",
"4. long long(长长整型) 8字节 -2^63-2^63-1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int main()\n",
"{\n",
" //1、短整型(-32768~32767)\n",
" short num1 = 10;\n",
" short num5 = 32768; //溢出了,打印出来是-23768\n",
" short num6 = 32770; //溢出了,打印出来是-32766\n",
"\n",
" //2、整型\n",
" int num2 = 10;\n",
"\n",
" //3、长整型\n",
" long num3 = 10;\n",
"\n",
" //4、长长整型\n",
" long long num4 = 10;\n",
"\n",
" cout << \"num1 = \" << num1 << endl;\n",
" cout << \"num2 = \" << num2 << endl;\n",
" cout << \"num3 = \" << num3 << endl;\n",
" cout << \"num4 = \" << num4 << endl;\n",
" cout << \"num5 = \" << num5 << endl;\n",
" cout << \"num6 = \" << num6 << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - num1 = 10 \n",
" - num2 = 10 \n",
" - num3 = 10 \n",
" - num4 = 10 \n",
" - num5 = -32768 \n",
" - num6 = -32766 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.2 实型(浮点型)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 作用:用于表示小数。\n",
"\n",
"② 浮点型变量分为下面两种,两个的区别在于表示有效数字范围不同。\n",
"\n",
"1. 单精度float\n",
"2. 双精度double\n",
"\n",
"③ 数据类型 占用字节 有效数字范围\n",
"\n",
"1. float 4字节 7位有效数字\n",
"2. double 8字节 15-16位有效数字"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1.2.1 单精度、双精度"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int main()\n",
"{\n",
" //1、单精度 float\n",
" //2、双精度 double\n",
" //默认情况下无论单精度还是双精度都只会显示6位有效数字\n",
" float f1 = 3.1415926; //默认为双精度前面加float相当于把双精度转换为单精度\n",
" float f2 = 3.1415926f; //后面加一个f直接创建的是单精度\n",
"\n",
" cout << \"f1 = \" << f1 << endl;\n",
"\n",
" double d1 = 3.1415926;\n",
"\n",
" cout << \"d1 = \" << d1 << endl;\n",
"\n",
" cout << \"float 占用内存空间为\" << sizeof(float) << endl;\n",
" cout << \"double 占用内层空间为\" << sizeof(double) << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - f1 = 3.14159 \n",
" - d1 = 3.14159 \n",
" - float 占用内存空间为4 \n",
" - double 占用内层空间为8 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1.2.2 科学计数法"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int main()\n",
"{\n",
" //科学计数法\n",
" float f3 = 3e2; // 3 * (10 ^ 2)\n",
" cout << \"f3 = \" << f3 << endl;\n",
"\n",
" float f4 = 3e-2; // 3 * (0.1 ^ 2)\n",
" cout << \"f4 = \" << f4 << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - f3 = 300 \n",
" - f4 = 0.03 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.3 字符型"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 字符型变量用于显示单个字符。\n",
"\n",
"② 语法char ch = 'a';\n",
"\n",
"③ 在显示字符型变量时,用单引号字符括起来,不要用双引号。\n",
"\n",
"④ 单引号内只能有一个字符,不可以是字符串。\n",
"\n",
"⑤ C和C++中字符型变量只占用1个字节。\n",
"\n",
"⑥ 字符型变量并不是把字符本身放到内存中存储而是将对应的ASCII编码放入到存储单元。\n",
"\n",
"⑦ ASCII码大致由以下两部分组成\n",
"\n",
"1. ASCII非打印控制字符ASCII表上的数字0-31分配给了控制字符用于控制像打印机等一些外围设备。\n",
"2. ASCII打印字符数字21-126分配给了能在键盘上找到的字符当查看或打印文档时就会出现。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int main()\n",
"{\n",
"\n",
" //1、字符型变量创建方式\n",
" char ch = 'a';\n",
" cout << ch << endl;\n",
"\n",
" //2、字符型变量所占内存大小\n",
" cout << \"char字符型变量所占内存\" << sizeof(char) << endl;\n",
"\n",
" //3、字符型变量常见错误\n",
" char ch2 = 'b'; //创建字符型变量时候,要用单引号\n",
" //char ch3 = \"b\"; //错误,创建字符型变量时候,不能用双引号\n",
" //char ch4 = 'abcdef'; //错误,创建字符型变量时候,单引号内只能有一个字符\n",
"\n",
" //4、字符型变量对应ASCII编码\n",
" cout << (int)ch << endl; // (int)ch 为字符'a'的ASCIII码值\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - a \n",
" - char字符型变量所占内存1 \n",
" - 97 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.4 字符串型"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 用于表示一串字符。\n",
"\n",
"② 字符串型有两种风格\n",
"\n",
"③ C风格字符串char 变量名[] = \"字符串值\"\n",
"\n",
"④ C++风格字符串string 变量名 = \"字符串值\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"#include <string> //用C++风格字符串时候,要包含这个头文件\n",
"\n",
"int main()\n",
"{\n",
"\n",
" //1、C风格字符串\n",
" //char 字符 = 这是一个字符\n",
" //char 字符[] = 这是一个字符串\n",
" //表示字符串时,等号后面,要用双引号\n",
"\n",
" char str[] = \"hello world\";\n",
" cout << str << endl;\n",
"\n",
" //2、C++风格字符串\n",
" string str2 = \"hello world\";\n",
" cout << str2 << endl;\n",
" \n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - hello world \n",
" - hello world \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.5 布尔类型 bool"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 布尔数据类型代表真或假的值。\n",
"\n",
"② bool类型只有两个值\n",
"\n",
"1. true -- 真 (本质是1)\n",
"2. false -- 假(本质是0)\n",
"\n",
"③ bool类型占1个字节大小"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int main()\n",
"{\n",
"\n",
" //1、创建bool数据类型\n",
"\n",
" bool flag1 = true; //true代表真\n",
" cout << flag1 << endl;\n",
" \n",
" bool flag2 = false; //flag 代表假\n",
" cout << flag2 << endl;\n",
" \n",
" //本质上 1代表真 0代表假\n",
"\n",
" //2、查看bool类型所占空间\n",
" cout << \"bool所占内存空间\" << sizeof(flag1) << endl;\n",
" cout << \"bool所占内存空间\" << sizeof(flag2) << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 1 \n",
" - 0 \n",
" - bool所占内存空间1 \n",
" - bool所占内存空间1 \n",
" - 请按任意键继续. . ."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,284 @@
# C++的数据类型
# 1. 数据类型
## 1.1 整形
① 作用:整型变量表示的是整数类型的数据。
② C++中能够表示整形的类型有以下几种方式,区别在于所占内存空间不同。
③ 数据类型 占用空间 取值范围
1. short(短整型) 2字节 -2^15-2^15-1
2. int整型 4字节 -2^31-2^31-1
3. long(长整型) Windows为4字节Linux为4字节(32位)8字节(64位) -2^31-2^31-1
4. long long(长长整型) 8字节 -2^63-2^63-1
```python
#include <iostream>
using namespace std;
int main()
{
//1、短整型(-32768~32767)
short num1 = 10;
short num5 = 32768; //溢出了,打印出来是-23768
short num6 = 32770; //溢出了,打印出来是-32766
//2、整型
int num2 = 10;
//3、长整型
long num3 = 10;
//4、长长整型
long long num4 = 10;
cout << "num1 = " << num1 << endl;
cout << "num2 = " << num2 << endl;
cout << "num3 = " << num3 << endl;
cout << "num4 = " << num4 << endl;
cout << "num5 = " << num5 << endl;
cout << "num6 = " << num6 << endl;
system("pause");
return 0;
}
```
运行结果:
- num1 = 10
- num2 = 10
- num3 = 10
- num4 = 10
- num5 = -32768
- num6 = -32766
- 请按任意键继续. . .
## 1.2 实型(浮点型)
① 作用:用于表示小数。
② 浮点型变量分为下面两种,两个的区别在于表示有效数字范围不同。
1. 单精度float
2. 双精度double
③ 数据类型 占用字节 有效数字范围
1. float 4字节 7位有效数字
2. double 8字节 15-16位有效数字
### 1.2.1 单精度、双精度
```python
#include <iostream>
using namespace std;
int main()
{
//1、单精度 float
//2、双精度 double
//默认情况下无论单精度还是双精度都只会显示6位有效数字
float f1 = 3.1415926; //默认为双精度前面加float相当于把双精度转换为单精度
float f2 = 3.1415926f; //后面加一个f直接创建的是单精度
cout << "f1 = " << f1 << endl;
double d1 = 3.1415926;
cout << "d1 = " << d1 << endl;
cout << "float 占用内存空间为" << sizeof(float) << endl;
cout << "double 占用内层空间为" << sizeof(double) << endl;
system("pause");
return 0;
}
```
运行结果:
- f1 = 3.14159
- d1 = 3.14159
- float 占用内存空间为4
- double 占用内层空间为8
- 请按任意键继续. . .
### 1.2.2 科学计数法
```python
#include <iostream>
using namespace std;
int main()
{
//科学计数法
float f3 = 3e2; // 3 * (10 ^ 2)
cout << "f3 = " << f3 << endl;
float f4 = 3e-2; // 3 * (0.1 ^ 2)
cout << "f4 = " << f4 << endl;
system("pause");
return 0;
}
```
运行结果:
- f3 = 300
- f4 = 0.03
- 请按任意键继续. . .
## 1.3 字符型
① 字符型变量用于显示单个字符。
② 语法char ch = 'a';
③ 在显示字符型变量时,用单引号字符括起来,不要用双引号。
④ 单引号内只能有一个字符,不可以是字符串。
⑤ C和C++中字符型变量只占用1个字节。
⑥ 字符型变量并不是把字符本身放到内存中存储而是将对应的ASCII编码放入到存储单元。
⑦ ASCII码大致由以下两部分组成
1. ASCII非打印控制字符ASCII表上的数字0-31分配给了控制字符用于控制像打印机等一些外围设备。
2. ASCII打印字符数字21-126分配给了能在键盘上找到的字符当查看或打印文档时就会出现。
```python
#include <iostream>
using namespace std;
int main()
{
//1、字符型变量创建方式
char ch = 'a';
cout << ch << endl;
//2、字符型变量所占内存大小
cout << "char字符型变量所占内存" << sizeof(char) << endl;
//3、字符型变量常见错误
char ch2 = 'b'; //创建字符型变量时候,要用单引号
//char ch3 = "b"; //错误,创建字符型变量时候,不能用双引号
//char ch4 = 'abcdef'; //错误,创建字符型变量时候,单引号内只能有一个字符
//4、字符型变量对应ASCII编码
cout << (int)ch << endl; // (int)ch 为字符'a'的ASCIII码值
system("pause");
return 0;
}
```
运行结果:
- a
- char字符型变量所占内存1
- 97
- 请按任意键继续. . .
## 1.4 字符串型
① 用于表示一串字符。
② 字符串型有两种风格
③ C风格字符串char 变量名[] = "字符串值"
④ C++风格字符串string 变量名 = "字符串值"
```python
#include <iostream>
using namespace std;
#include <string> //用C++风格字符串时候,要包含这个头文件
int main()
{
//1、C风格字符串
//char 字符 = 这是一个字符
//char 字符[] = 这是一个字符串
//表示字符串时,等号后面,要用双引号
char str[] = "hello world";
cout << str << endl;
//2、C++风格字符串
string str2 = "hello world";
cout << str2 << endl;
system("pause");
return 0;
}
```
运行结果:
- hello world
- hello world
- 请按任意键继续. . .
## 1.5 布尔类型 bool
① 布尔数据类型代表真或假的值。
② bool类型只有两个值
1. true -- 真 (本质是1)
2. false -- 假(本质是0)
③ bool类型占1个字节大小
```python
#include <iostream>
using namespace std;
int main()
{
//1、创建bool数据类型
bool flag1 = true; //true代表真
cout << flag1 << endl;
bool flag2 = false; //flag 代表假
cout << flag2 << endl;
//本质上 1代表真 0代表假
//2、查看bool类型所占空间
cout << "bool所占内存空间" << sizeof(flag1) << endl;
cout << "bool所占内存空间" << sizeof(flag2) << endl;
system("pause");
return 0;
}
```
运行结果:
- 1
- 0
- bool所占内存空间1
- bool所占内存空间1
- 请按任意键继续. . .

View File

@ -0,0 +1,106 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的转义字符"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 转义字符"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 用于表示一些不能显示出来的ASCII字符。\n",
"\n",
"② 我们常用的转义字符有:\\n、\\\\、\\t。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int main()\n",
"{\n",
"\n",
" //换行符 \\n\n",
"\n",
" cout << \"hello world\\n\";\n",
"\n",
" //反斜杠 \\\\ 要输出反斜杠\\时,要在前面加上一个反斜杠\n",
"\n",
" cout << \"\\\\\" << endl;\n",
"\n",
" //水平制表符\\t 可以整齐的输出数据\n",
" cout << \"aaaa\\thellowworld\" << endl;\n",
" cout << \"aa\\thellowworld\" << endl;\n",
" cout << \"aaaaaa\\thellowworld\" << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果:\n",
" - hello world\n",
" - \\\n",
" - aaaa hellowworld\n",
" - aa hellowworld\n",
" - aaaaaa hellowworld\n",
" - 请按任意键继续. . ."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,43 @@
# C++的转义字符
# 1. 转义字符
① 用于表示一些不能显示出来的ASCII字符。
② 我们常用的转义字符有:\n、\\、\t。
```python
#include <iostream>
using namespace std;
int main()
{
//换行符 \n
cout << "hello world\n";
//反斜杠 \\ 要输出反斜杠\时,要在前面加上一个反斜杠
cout << "\\" << endl;
//水平制表符\t 可以整齐的输出数据
cout << "aaaa\thellowworld" << endl;
cout << "aa\thellowworld" << endl;
cout << "aaaaaa\thellowworld" << endl;
system("pause");
return 0;
}
```
运行结果:
- hello world
- \
- aaaa hellowworld
- aa hellowworld
- aaaaaa hellowworld
- 请按任意键继续. . .

View File

@ -0,0 +1,135 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的数据输入"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 数据输入"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 数据的输入,作用:用于从键盘获取数据。\n",
"\n",
"② 数据的输入关键字cin\n",
"\n",
"③ 数据饿输入语法cin >> 变量"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"#include <string> //包含string的头文件\n",
"int main()\n",
"{\n",
"\n",
" //1、创建bool数据类型\n",
" int a = 0;\n",
" cout << \"请给整型变量 a 赋值:\" << endl;\n",
" cin >> a;\n",
" cout << \"整型变量a = \" << a << endl;\n",
"\n",
" //2、浮点型\n",
" float f = 3.14f;\n",
" cout << \"请给浮点型变量 f 赋值:\" << endl;\n",
" cin >> f;\n",
" cout << \"浮点型变量 f = \" << f << endl;\n",
"\n",
" //3、字符型\n",
" char ch ; //仅仅声明了,没有初始化\n",
" cout << \"请给字符型变量 ch 赋值:\" << endl;\n",
" cin >> ch;\n",
" cout << \"字符型变量 ch = \" << ch << endl;\n",
"\n",
" //4、字符型\n",
" string str = \"hello\";\n",
" cout << \"请给字符串 str 赋值:\" << endl;\n",
" cin >> str;\n",
" cout << \"字符型变量 str = \" << str << endl;\n",
"\n",
" //4、布尔型\n",
" bool flag = false;\n",
" cout << \"请给布尔类型 flag 赋值:\" << endl;\n",
" cin >> flag; //布尔类型 只要是非0的值都代表真\n",
" cout << \"布尔类型 flag = \" << flag << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 请给整型变量 a 赋值:\n",
" - 23\n",
" - 整型变量a = 23\n",
" - 请给浮点型变量 f 赋值:\n",
" - 23.4\n",
" - 浮点型变量 f = 23.4\n",
" - 请给字符型变量 ch 赋值:\n",
" - w\n",
" - 字符型变量 ch = w\n",
" - 请给字符串 str 赋值:\n",
" - asfg\n",
" - 字符型变量 str = asfg\n",
" - 请给布尔类型 flag 赋值:\n",
" - 4562\n",
" - 布尔类型 flag = 1\n",
" - 请按任意键继续. . ."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,72 @@
# C++的数据输入
# 1. 数据输入
① 数据的输入,作用:用于从键盘获取数据。
② 数据的输入关键字cin
③ 数据饿输入语法cin >> 变量
```python
#include <iostream>
using namespace std;
#include <string> //包含string的头文件
int main()
{
//1、创建bool数据类型
int a = 0;
cout << "请给整型变量 a 赋值:" << endl;
cin >> a;
cout << "整型变量a = " << a << endl;
//2、浮点型
float f = 3.14f;
cout << "请给浮点型变量 f 赋值:" << endl;
cin >> f;
cout << "浮点型变量 f = " << f << endl;
//3、字符型
char ch ; //仅仅声明了,没有初始化
cout << "请给字符型变量 ch 赋值:" << endl;
cin >> ch;
cout << "字符型变量 ch = " << ch << endl;
//4、字符型
string str = "hello";
cout << "请给字符串 str 赋值:" << endl;
cin >> str;
cout << "字符型变量 str = " << str << endl;
//4、布尔型
bool flag = false;
cout << "请给布尔类型 flag 赋值:" << endl;
cin >> flag; //布尔类型 只要是非0的值都代表真
cout << "布尔类型 flag = " << flag << endl;
system("pause");
return 0;
}
```
运行结果:
- 请给整型变量 a 赋值:
- 23
- 整型变量a = 23
- 请给浮点型变量 f 赋值:
- 23.4
- 浮点型变量 f = 23.4
- 请给字符型变量 ch 赋值:
- w
- 字符型变量 ch = w
- 请给字符串 str 赋值:
- asfg
- 字符型变量 str = asfg
- 请给布尔类型 flag 赋值:
- 4562
- 布尔类型 flag = 1
- 请按任意键继续. . .

View File

@ -0,0 +1,481 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的运算符"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 运算符"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 运算符作用:用于执行代码的运算。\n",
"\n",
"② 运算符类型主要有四种:\n",
"\n",
"1. 算术运算符:用于处理四则运算。 \n",
"2. 赋值运算符:用于将表达式的值赋给变量 \n",
"3. 比较运算符:用于表达式的比较,并返回一个真值或假值。 \n",
"4. 逻辑运算法:用于表达式的值返回真值或假值。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 2. 算术运算符"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.1 加减乘除运算"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int main()\n",
"{\n",
"\n",
" int a1 = 10;\n",
" int b1 = 3;\n",
"\n",
" cout << a1 + b1 << endl;\n",
" cout << a1 - b1 << endl;\n",
" cout << a1 * b1 << endl;\n",
" cout << a1 / b1 << endl; //两个整数相除,结果依然是整数,将小数部分去除\n",
"\n",
" int a2 = 10;\n",
" int b2 = 20;\n",
"\n",
" cout << a2 / b2 << endl;\n",
"\n",
" int a3 = 10;\n",
" int b3 = 0;\n",
"\n",
" //cout << a3 / b3 << endl; //两个数相除除数不可以为0\n",
"\n",
" //两个小数可以相除\n",
" double d1 = 0.51; //如果d1为0.5运算结果为整数2\n",
" double d2 = 0.25;\n",
" \n",
" cout << d1 / d2 << endl; //运算结果也可以是小数\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 13 \n",
" - 7 \n",
" - 30 \n",
" - 3 \n",
" - 0 \n",
" - 2.04 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.2 取模运算"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int main()\n",
"{\n",
" //取摸运算本质 就是求余数\n",
" int a1 = 10;\n",
" int b1 = 3;\n",
"\n",
" cout << a1 % b1 << endl;\n",
"\n",
" /*两个数相除除数不可以为0所以也做不了取模运算\n",
" int a2 = 10;\n",
" int b2 = 0;\n",
"\n",
" cout << a2 % b2 << endl; //\n",
" */\n",
"\n",
" /*两个小数是不可以做取模运算的\n",
" double d1 = 3.14;\n",
" double d2 = 1.1;\n",
"\n",
" cout << d1 % d2 << endl;\n",
" */\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 1 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.3 递增递减运算"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int main()\n",
"{\n",
" //1、前置递增\n",
"\n",
" int a = 10;\n",
" ++a;\n",
" cout << \"a=\" << a << endl;\n",
"\n",
" //2、后置递增\n",
"\n",
" int b = 15;\n",
" b++;\n",
" cout << \"b=\" << b << endl;\n",
"\n",
" //3、前置和后置的区别\n",
" //前置递增,先让变量+1 然后进行表达式运算\n",
" int a2 = 10;\n",
" int b2 = ++a2 * 10;\n",
" cout << \"a2= \" << a2 << endl;\n",
" cout << \"b2= \" << b2 << endl;\n",
"\n",
" //后置递增,先进行表达式运算,后让变量+1\n",
" int a3 = 10;\n",
" int b3 = a3++ * 10;\n",
" cout << \"a3= \" << a3 << endl;\n",
" cout << \"b3= \" << b3 << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - a=11 \n",
" - b=16 \n",
" - a2= 11 \n",
" - b2= 110 \n",
" - a3= 11 \n",
" - b3= 100 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 3. 赋值运算符"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int main()\n",
"{\n",
"\n",
" // = 赋值\n",
" int a = 10;\n",
" a = 100;\n",
" cout << \"a= \" << a << endl;\n",
"\n",
" // += 加等于\n",
" int b = 10;\n",
" b = 10;\n",
" b += 2;\n",
" cout << \"b= \" << b << endl;\n",
"\n",
" // -= 减等于\n",
" int c = 10;\n",
" c = 10;\n",
" c -= 2;\n",
" cout << \"c= \" << c << endl;\n",
"\n",
" // *= 乘等于\n",
" int d = 10;\n",
" d = 10;\n",
" d *= 2;\n",
" cout << \"d= \" << d << endl;\n",
"\n",
" // /= 除等于\n",
" int e = 10;\n",
" e = 10;\n",
" e /= 2;\n",
" cout << \"e= \" << e << endl;\n",
" \n",
" // %= 模等于\n",
" int f = 10;\n",
" f = 10;\n",
" f %= 2;\n",
" cout << \"f= \" << f << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - a= 100 \n",
" - b= 12 \n",
" - c= 8 \n",
" - d= 20 \n",
" - e= 5 \n",
" - f= 0 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 4. 比较运算符"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 作用:用于表达式的比较,并返回一个真值或假值。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int main()\n",
"{\n",
" //比较运算符\n",
" \n",
" // ==\n",
" int a = 10;\n",
" int b = 20;\n",
" cout << (a == b) << endl;\n",
"\n",
" // !=\n",
" cout << (a != b) << endl;\n",
"\n",
" // >\n",
" cout << (a > b) << endl;\n",
"\n",
" // <\n",
" cout << (a < b) << endl;\n",
"\n",
" // >=\n",
" cout << (a >= b) << endl;\n",
" \n",
" // <=\n",
" cout << (a <= b) << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 0 \n",
" - 1 \n",
" - 0 \n",
" - 1 \n",
" - 0 \n",
" - 1 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 5. 逻辑运算符"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 作用:用于根据表达式的值返回真值或假值。\n",
"\n",
"1. !a 表示非如果a为假则!a为真如果a为真则!a为假。\n",
"2. a&&b 表示与如果a和b都为真则结果为真否则为假。\n",
"3. a||b 表示或如果a和b有一个为真则结果为真二者都为假时结果为假。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int main()\n",
"{\n",
" //逻辑运算符\n",
"\n",
" // !=\n",
" int a = 10;\n",
" int b = 30;\n",
"\n",
" cout << (!a) << endl; //在C++中除了0都为真\n",
" cout << (!!a) << endl;\n",
"\n",
" // &&\n",
" a = 10;\n",
" b = 30;\n",
"\n",
" cout << (a && b) << endl;\n",
"\n",
" a = 0;\n",
" b = 10;\n",
" cout << (a && b) << endl;\n",
"\n",
" // ||\n",
" a = 10;\n",
" b = 30;\n",
" cout << (a || b) << endl;\n",
"\n",
" a = 0;\n",
" b = 10;\n",
" cout << (a || b) << endl;\n",
"\n",
" a = 0;\n",
" b = 0;\n",
" cout << (a || b) << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 0 \n",
" - 1 \n",
" - 1 \n",
" - 0 \n",
" - 1 \n",
" - 1 \n",
" - 0 \n",
" - 请按任意键继续. . ."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,328 @@
# C++的运算符
# 1. 运算符
① 运算符作用:用于执行代码的运算。
② 运算符类型主要有四种:
1. 算术运算符:用于处理四则运算。
2. 赋值运算符:用于将表达式的值赋给变量
3. 比较运算符:用于表达式的比较,并返回一个真值或假值。
4. 逻辑运算法:用于表达式的值返回真值或假值。
# 2. 算术运算符
## 2.1 加减乘除运算
```python
#include <iostream>
using namespace std;
int main()
{
int a1 = 10;
int b1 = 3;
cout << a1 + b1 << endl;
cout << a1 - b1 << endl;
cout << a1 * b1 << endl;
cout << a1 / b1 << endl; //两个整数相除结果依然是整数将小数部分去除
int a2 = 10;
int b2 = 20;
cout << a2 / b2 << endl;
int a3 = 10;
int b3 = 0;
//cout << a3 / b3 << endl; //两个数相除除数不可以为0
//两个小数可以相除
double d1 = 0.51; //如果d1为0.5运算结果为整数2
double d2 = 0.25;
cout << d1 / d2 << endl; //运算结果也可以是小数
system("pause");
return 0;
}
```
运行结果:
- 13
- 7
- 30
- 3
- 0
- 2.04
- 请按任意键继续. . .
## 2.2 取模运算
```python
#include <iostream>
using namespace std;
int main()
{
//取摸运算本质 就是求余数
int a1 = 10;
int b1 = 3;
cout << a1 % b1 << endl;
/*两个数相除除数不可以为0所以也做不了取模运算
int a2 = 10;
int b2 = 0;
cout << a2 % b2 << endl; //
*/
/*两个小数是不可以做取模运算的
double d1 = 3.14;
double d2 = 1.1;
cout << d1 % d2 << endl;
*/
system("pause");
return 0;
}
```
运行结果:
- 1
- 请按任意键继续. . .
## 2.3 递增递减运算
```python
#include <iostream>
using namespace std;
int main()
{
//1、前置递增
int a = 10;
++a;
cout << "a=" << a << endl;
//2、后置递增
int b = 15;
b++;
cout << "b=" << b << endl;
//3、前置和后置的区别
//前置递增,先让变量+1 然后进行表达式运算
int a2 = 10;
int b2 = ++a2 * 10;
cout << "a2= " << a2 << endl;
cout << "b2= " << b2 << endl;
//后置递增,先进行表达式运算,后让变量+1
int a3 = 10;
int b3 = a3++ * 10;
cout << "a3= " << a3 << endl;
cout << "b3= " << b3 << endl;
system("pause");
return 0;
}
```
运行结果:
- a=11
- b=16
- a2= 11
- b2= 110
- a3= 11
- b3= 100
- 请按任意键继续. . .
# 3. 赋值运算符
```python
#include <iostream>
using namespace std;
int main()
{
// = 赋值
int a = 10;
a = 100;
cout << "a= " << a << endl;
// += 加等于
int b = 10;
b = 10;
b += 2;
cout << "b= " << b << endl;
// -= 减等于
int c = 10;
c = 10;
c -= 2;
cout << "c= " << c << endl;
// *= 乘等于
int d = 10;
d = 10;
d *= 2;
cout << "d= " << d << endl;
// /= 除等于
int e = 10;
e = 10;
e /= 2;
cout << "e= " << e << endl;
// %= 模等于
int f = 10;
f = 10;
f %= 2;
cout << "f= " << f << endl;
system("pause");
return 0;
}
```
运行结果:
- a= 100
- b= 12
- c= 8
- d= 20
- e= 5
- f= 0
- 请按任意键继续. . .
# 4. 比较运算符
① 作用:用于表达式的比较,并返回一个真值或假值。
```python
#include <iostream>
using namespace std;
int main()
{
//比较运算符
// ==
int a = 10;
int b = 20;
cout << (a == b) << endl;
// !=
cout << (a != b) << endl;
// >
cout << (a > b) << endl;
// <
cout << (a < b) << endl;
// >=
cout << (a >= b) << endl;
// <=
cout << (a <= b) << endl;
system("pause");
return 0;
}
```
运行结果:
- 0
- 1
- 0
- 1
- 0
- 1
- 请按任意键继续. . .
# 5. 逻辑运算符
① 作用:用于根据表达式的值返回真值或假值。
1. !a 表示非如果a为假则!a为真如果a为真则!a为假。
2. a&&b 表示与如果a和b都为真则结果为真否则为假。
3. a||b 表示或如果a和b有一个为真则结果为真二者都为假时结果为假。
```python
#include <iostream>
using namespace std;
int main()
{
//逻辑运算符
// !=
int a = 10;
int b = 30;
cout << (!a) << endl; //在C++中除了0都为真
cout << (!!a) << endl;
// &&
a = 10;
b = 30;
cout << (a && b) << endl;
a = 0;
b = 10;
cout << (a && b) << endl;
// ||
a = 10;
b = 30;
cout << (a || b) << endl;
a = 0;
b = 10;
cout << (a || b) << endl;
a = 0;
b = 0;
cout << (a || b) << endl;
system("pause");
return 0;
}
```
运行结果:
- 0
- 1
- 1
- 0
- 1
- 1
- 0
- 请按任意键继续. . .

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,533 @@
# C++的数组
# 1. 数组特点
① 所谓数组,就是一个集合,里面存放了相同类型的数据元素。
1. 特点1数组中每个元素都是相同的数据类型。
2. 特点2数组是由连续的内存位置组成的。
# 2. 一维数组
## 2.1 定义方式
① 一维数组定义:
1. 数组类型 数组名 [ 数组长度 ]
2. 数组类型 数组名 [ 数组长度 ] = { 值1值2.... }
3. 数组类型 数组名 [ ] = { 值1值2..... }
② 数组名的命名规范与变量名命名规范一致,不要和变量重名。
③ 数组中下标是从0开始索引。
```python
#include <iostream>
using namespace std;
int main()
{
//1、数组类型 数组名 [ 数组长度 ]
int arr[5];
//数组元素的下标是从0开始索引的
//给数组中的元素进行赋值
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
arr[3] = 40;
arr[4] = 50;
//访问数据元素
cout << arr[0] << endl;
cout << arr[1] << endl;
cout << arr[2] << endl;
cout << arr[3] << endl;
cout << arr[4] << endl;
//2、数据类型 数组名 [ 数组长度 ] = { 值1值2... }
//如果在初始化数据的时候没有完全填写完会用0来填补剩余数据
int arr2[5] = { 10,20,30 };
/*
方式一:
cout << arr2[0] << endl;
cout << arr2[1] << endl;
cout << arr2[2] << endl;
cout << arr2[3] << endl;
cout << arr2[4] << endl;
*/
// 方式二:利用循环输出数组中的元素
for (int i = 0; i < 5; i++)
{
cout << arr2[i] << endl;
}
//3、数据类型 数组名 [ ] = { 值1值2.... }
int arr3[] = { 90,80,70,60,50,40,30,20,10 }; //以后自定义变量,不要 int arr3 = 100这样避免以后调用arr3到底是调用变量还是数组产生模糊。
for (int i = 0; i < 9; i++)
{
cout << arr3[i] << endl;
}
system("pause");
return 0;
}
```
运行结果:
- 10
- 20
- 30
- 40
- 50
- 10
- 20
- 30
- 0
- 0
- 90
- 80
- 70
- 60
- 50
- 40
- 30
- 20
- 10
- 请按任意键继续. . .
## 2.2 数组名
① 一维数组名的用途:
1. 可以统计整个数组在内存中的长度。
2. 可以获取数组在内存中的首地址。
```python
#include <iostream>
using namespace std;
int main()
{
//数组名用途
//1、可以通过数组名统计整个数组占用内存大小
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
cout << "整个数组占用内存空间为:" << sizeof(arr) << endl;
cout << "每个元素占用内存空间为:" << sizeof(arr[0]) << endl;
cout << "数组中元素的个数为:" << sizeof(arr)/sizeof(arr[0]) << endl;
//2、可以通过数组名查看数组首地址
cout << "数组首地址为:" << (int)arr << endl;
cout << "数组中第一个元素地址为:" << (int)&arr[0] << endl; //int使得将十六位地址通过int转换为10位地址&表示取址符号取一个元素的首地址
cout << "数组中第二个元素地址为:" << (int)&arr[1] << endl; //第二个元素和第一个元素差四个字节
//数组名是常量,值为数组首地址,不可以进行赋值操作
//arr = 100; 不可以这样赋值修改
system("pause");
return 0;
}
```
运行结果:
- 整个数组占用内存空间为40
- 每个元素占用内存空间为4
- 数组中元素的个数为10
- 数组首地址为12582108
- 数组中第一个元素地址为12582108
- 数组中第二个元素地址为12582112
- 请按任意键继续. . .
## 2.3 五只小猪称体重
案例描述在一个数组中记录了五只小猪的体重int arr[5]={300,350,200,400,250},找出并打印最重的小猪体重。
```python
#include <iostream>
using namespace std;
int main()
{
//1、创建5只小猪体重的数组
int arr[5] = { 300,350,200,400,250 };
//2、从数组中找到最大值
int max = 0; //先认定一个最大值为0
for (int i = 0; i < 5; i++)
{
//cout << arr[i] << endl;
if (arr[i] > max)
{
max = arr[i];
}
}
//3、打印最大值
cout << max << endl;
system("pause");
return 0;
}
```
运行结果:
- 400
- 请按任意键继续. . .
## 2.4 数组元素逆置
案例描述请声明一个5个元素的数组并且将元素逆置。(如原数组元素为1,3,2,5,4逆置后输出的结果为4,5,2,3,1)。
```python
#include <iostream>
using namespace std;
int main()
{
//实现数组元素逆置
//1、创建数组
int arr[5] = { 1,3,2,5,4 };
cout << "数组逆置前" << endl;
for (int i = 0; i < 5; i++)
{
cout << arr[i] << endl;
}
//2、实现逆置
//2.1 记录起始下标位置
//2.2 记录结束下标位置
//2.3 起始下标与结束下标的元素互换
//2.4 起始位置++ 结束位置--
//2.5 循环执行2.1操作,直到起始位置 >= 结束位置
int start = 0; //起始下标
int end = sizeof(arr) / sizeof(arr[0]) - 1; //结束下标,先计算除法
while (start < end)
{
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
//下标更新
start++;
end--;
}
//3、打印逆置后的数组
cout << "数组逆置后" << endl;
for (int i = 0; i < 5; i++)
{
cout << arr[i] << endl;
}
system("pause");
return 0;
}
```
运行结果:
- 数组逆置前
- 1
- 3
- 2
- 5
- 4
- 数组逆置后
- 4
- 5
- 2
- 3
- 1
- 请按任意键继续. . .
## 2.5 冒泡排序
① 冒泡排序作用:最常用的排序算法,对数组内元素进行排序。
1. 比较相邻的元素,如果第一个比第二个大,就交换他们两个。
2. 对每一对相邻元素做同样的go牛牛公主执行完毕后找到第一个最大值。
3. 重复以上的步骤,每次比较次数-1.直到不需要比较。
② 示例:将数组(4,2,8,0,5,7,1,3,9)进行排序。
```python
#include <iostream>
using namespace std;
int main()
{
int arr[9] = { 4,2,8,0,5,7,1,3,9 };
cout << "排序前" << endl;
for (int i = 0; i < 9; i++)
{
cout << arr[i] << " ";
}
cout << endl;
//开始冒泡排序
for (int i = 0; i < 9 - 1; i++)
{
//内层循环对比 次数=元素个数=当前轮数-1
for (int j = 0; j < 9 - 1 - i; j++) //最后一位数已经是最大数了不需要排序了
{
//如果第一个数字,比第二个数字大,交换两个数字
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j+1];
arr[j + 1] = temp;
}
}
}
//排序后结果
cout << "排序后" << endl;
for (int i = 0; i < 9; i++)
{
cout << arr[i] << " ";
}
cout << endl;
system("pause");
return 0;
}
```
运行结果:
- 排序前
- 4 2 8 0 5 7 1 3 9
- 排序后
- 0 1 2 3 4 5 7 8 9
- 请按任意键继续. . .
运行结果:
# 3. 二维数组
## 3.1 定义方式
① 二维数组就是在一维数组上,多加一个维度。
![image.png](13_C++的数组_files/image.png)
② 二维数组定义的四种方式:
1. 数据类型 数组名 [ 行数 ][ 列数 ];
2. 数据类型 数组名 [ 行数 ][ 列数 ] = { { 数据1数据2} , { 数据3数据4 } }
3. 数据类型 数组名 [ 行数 ][ 列数 ] = { 数据1数据2数据3数据4 };
4. 数据类型 数组名 [ ][ 列数 ] = { 数据1数据2数据3数据4 };
③ 以上4种定义方式利用第二种更加直观提高代码的可读性。
④ 定义二维数组的时候,如果初始化了数据,可以省略行数。
```python
#include <iostream>
using namespace std;
int main()
{
//1、数据类型 数组名 [ 行数 ][ 列数 ];
int arr[2][3];
arr[0][0] = 1;
arr[0][1] = 2;
arr[0][2] = 3;
arr[1][0] = 4;
arr[1][1] = 5;
arr[1][2] = 6;
//外层循环打印行数,内层循环打印列数
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr[i][j] << endl;
}
}
//2、数据类型 数组名 [ 行数 ][ 列数 ] = { { 数据1数据2} , { 数据3数据4 } }
int arr2[2][3] =
{
{1,2,3},
{4,5,6}
};
for (int i = 0; i<2;i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr2[i][j] << " "; //打印一个元素后打印一个空格
}
cout << endl; //换行语句
}
//3、数据类型 数组名 [ 行数 ][ 列数 ] = { 数据1数据2数据3数据4 };
int arr3[2][3] = { 1,2,3,4,5,6 }; //可以省去行数,但是列数不能再省略了
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr2[i][j] << " ";
}
cout << endl;
}
//4、数据类型 数组名 [ ][ 列数 ] = { 数据1数据2数据3数据4 };
int arr4[][3] = { 1,2,3,4,5,6 }; //可以省去行数,但是列数不可以省略
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << arr2[i][j] << " ";
}
cout << endl;
}
system("pause");
return 0;
}
```
运行结果:
- 1
- 2
- 3
- 4
- 5
- 6
- 1 2 3
- 4 5 6
- 1 2 3
- 4 5 6
- 1 2 3
- 4 5 6
- 请按任意键继续. . .
## 3.2 数组名
① 查看二维数组所占内存空间。
② 获取二维数组首地址。
```python
#include <iostream>
using namespace std;
int main()
{
//二维数组名称用途
//1、可以查看占用内存空间大小
int arr[2][3] =
{
{1,2,3},
{4,5,6}
};
cout << "二维数组占用内存空间为: " << sizeof(arr) << endl;
cout << "二维数组第一行占用内存为:" << sizeof(arr[0]) << endl;
cout << "二维数组第一个元素占用内存为:" << sizeof(arr[0][0]) << endl;
cout << "二维数组行数为:" << sizeof(arr)/sizeof(arr[0]) << endl;
cout << "二维数组列数为:" << sizeof(arr[0])/sizeof(arr[0][0]) << endl;
//2、可以查看二维数组的首地址
cout << "二维数组首地址为:" << (int)arr << endl;
cout << "二维数组第一行首地址为:" << (int)arr << endl;
cout << "二维数组第一行首地址为:" << (int)arr[0] << endl;
cout << "二维数组第二行首地址为:" << (int)arr[1] << endl;
cout << "二维数组第一个元素首地址为:" << (int)&arr[0][0] << endl;
cout << "二维数组第二个元素首地址为:" << (int)&arr[0][1] << endl; //每个元素地址相差4个字节
system("pause");
return 0;
}
```
运行结果:
- 二维数组占用内存空间为: 24
- 二维数组第一行占用内存为12
- 二维数组第一个元素占用内存为4
- 二维数组行数为2
- 二维数组列数为3
- 二维数组首地址为3733652
- 二维数组第一行首地址为3733652
- 二维数组第一行首地址为3733652
- 二维数组第二行首地址为3733664
- 二维数组第一个元素首地址为3733652
- 二维数组第二个元素首地址为3733656
- 请按任意键继续. . .
## 3.3 考试成绩
案例描述:有三名同学(张三,李四,王五),在一次考试中的成绩分别如下表,请分别输出三名同学的成绩。
| 姓名 | 语文 | 数学 | 英语 |
| :------:| :------: | :------: | :------: |
| 张三 | 100 | 100 | 100 |
| 李四 | 90 | 50 | 100 |
| 王五 | 60 | 70 | 80 |
```python
#include <iostream>
using namespace std;
int main()
{
//二维数组案例-考试成绩统计
//1、创建二维数组
int scores[3][3] =
{
{100,100,100},
{90,50,100},
{60,70,80}
};
//2、统计每个人的总和分数
for (int i = 0; i < 3; i++)
{
int sum = 0; //统计分数总和不变
for (int j = 0; j < 3; j++)
{
sum += scores[i][j];
//cout << scores[i][j] << " ";
}
cout << "第" << i + 1 << "个人的总分为" << sum << endl;
}
system("pause");
return 0;
}
```
运行结果:
- 第1个人的总分为300
- 第2个人的总分为240
- 第3个人的总分为210
- 请按任意键继续. . .

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 KiB

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,610 @@
# C++的函数
# 1. 函数
## 1.1 函数概述
① 函数作用:将一段经常使用的代码封装起来,减少重复代码。
② 一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能。
## 1.2 函数定义
① 函数的定义主要有5个部分
1. 返回值类型:一个函数可以返回一个值。
2. 函数名:给函数起个名称。
3. 参数列表:使用该函数时,传入的数据。
4. 函数体语句:花括号内的代码,函数内需要执行的语句。
5. return表达式和返回值类型挂钩函数执行完后返回相应的数据。
② 语法格式如下所示:
```python
返回值类型 函数名 (参数列表)
{
函数体语句
return 表达式
}
```
```python
#include <iostream>
using namespace std;
//函数的定义
//语法:返回值类型 函数名 (参数列表) { 函数体语句 return表达式 }
//加法函数,实现两个整型相加,并且将相加的结果进行返回
int add(int num1, int num2)
{
int sum = num1 + num2;
return sum;
}
int main()
{
system("pause"); //按任意键继续
return 0;
}
```
## 1.3 函数调用
① 功能:使用定义好的函数
② 语法:函数名(参数)
③ 函数定义里小括号内称为形参,函数调用时传入的参数称为实参
```python
#include <iostream>
using namespace std;
//函数的定义
//语法:
//返回值类型 函数名 (参数列表) { 函数体语句 return表达式 }
//定义加法函数
//函数定义的时候num1和num2并不是真实数据
//它们只是一个形式上的参数,简称形参
int add(int num1, int num2)
{
int sum = num1 + num2;
return sum;
}
int main()
{
//main函数中调用add函数
int a = 10;
int b = 20;
//函数调用语法:函数名称:(参数)
//a和b称为 实际参数,简称实参
//当调用函数的时候,实参的值会传递给形参
int c = add(a, b);
cout << "c = " << c << endl;
system("pause"); //按任意键继续
return 0;
}
```
运行结果:
- c = 30
- 请按任意键继续. . .
## 1.4 函数值传递
① 所谓值传递,就是函数调用时实参将数值传入给形参。
② 值传递时,如果形参发生改变,并不影响实参。
③ 在下面代码例子中实参传进去时新参会产生新的内存空间赋值对num1、num2的操作并不会改变实参a、b的值。
![image.png](14_C++的函数_files/image.png)
```python
#include <iostream>
using namespace std;
//值传递
//定义函数,实现两个数字进行交换函数
//如果函数不需要返回值声明的时候可以写void
void swap(int num1, int num2)
{
cout << "交换前:" << endl;
cout << "num1= " << num1 << endl;
cout << "num2= " << num2 << endl;
int temp = num1;
num1 = num2;
num2 = temp;
cout << "交换后:" << endl;
cout << "num1= " << num1 << endl;
cout << "num2= " << num2 << endl;
return; //前面写了void所以不需要返回值。返回值不需要的时候也可以不写return。
}
int main()
{
//main函数中调用add函数
int a = 10;
int b = 20;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
//当我们把值传递的时候,函数的形参发生发生改变,并不会影响实参
swap(a, b);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
system("pause"); //按任意键继续
return 0;
}
```
运行结果:
- a = 10
- b = 20
- 交换前:
- num1= 10
- num2= 20
- 交换后:
- num1= 20
- num2= 10
- a = 10
- b = 20
## 1.5 函数常见样式
① 常见的函数样式有四种
1. 无参无返
2. 有参无返
3. 无参有返
4. 有参有返
```python
#include <iostream>
using namespace std;
//函数常见样式
//1、无参无返
void test01()
{
cout << "this is test01" << endl;
}
//2、有参无返
void test02(int a)
{
cout << "this is test 02 a = " << a << endl;
}
//3、无参有返
int test03()
{
cout << "this is test 03 " << endl;
return 1000;
}
//4、有参有返
int test04(int a )
{
cout << "this is test 04 a = " << a << endl;
return a;
}
int main()
{
//无参无返函数调用
test01();
//有参无返函数调用
test02(100);
//无参有返函数调用
int num1 = test03();
cout << "num1 = " << num1 << endl;
//有参有返函数调用
int num2 = test04(10000);
cout << "num2 = " << num2 << endl;
system("pause"); //按任意键继续
return 0;
}
```
运行结果:
- this is test01
- this is test 02 a = 100
- this is test 03
- num1 = 1000
- this is test 04 a = 10000
- num2 = 10000
## 1.6 函数声明
① 作用:告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。
② 函数的声明可以多次,但是函数的定义只能有一次。
```python
#include <iostream>
using namespace std;
//函数的声明
//比较函数,实现两个整型数字进行比较,返回较大的值。
//提前告诉编译器函数的存在,可以利用函数的声明
//函数的声明
//声明可以写多次,但是定义只能有一次
int max(int a, int b);
int max(int a, int b);
int max(int a, int b);
int main()
{
int a = 10;
int b = 20;
cout << max(a, b) << endl;
system("pause"); //按任意键继续
return 0;
}
//函数定义在main函数之后必须要在main函数之前写函数的声明
int max(int a, int b)
{
return a > b ? a : b;
}
```
运行结果:
- 20
## 1.7 函数分文件编写
① 作用:让代码结构更加清晰。
② 函数分文件编写一般有4个步骤
1. 创建后缀名为.h的头文件。
2. 创建后缀名为.cpp的源文件。
3. 在头文件中写函数的声明。
4. 在源文件中写函数的定义。
### 1.7.1 swap.h头文件
```python
//这个是swap.h头文件
#include <iostream>
using namespace std;
//函数的声明
void swap(int a, int b);
```
### 1.7.2 swap.pp源文件
```python
//这个是swap.pp源文件
#include "swap.h"
//函数的定义
void swap(int a, int b)
{
int temp = a;
a = b;
b = temp;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
}
```
### 1.7.3 主文件 .cpp文件
```python
//主文件,调用函数分文件
#include <iostream>
using namespace std;
#include "swap.h" //包含要调用的函数的头文件,双引号表示我们自己写的头文件
int main()
{
int a = 10;
int b = 20;
cout << max(a, b) << endl;
system("pause"); //按任意键继续
return 0;
}
```
## 1.8 函数默认参数
① 在C++中,函数的形参列表中的形参是可以有默认值的。
② 语法:返回值类型 函数名 (参数 = 默认值) {}
```python
#include <iostream>
using namespace std;
//函数默认参数
//如果我们自己传入数据,就用自己的数据,如果没有,那么永默认值
//语法:返回值类型 函数名(形参 = 默认值)
int func01(int a,int b,int c)
{
return a + b + c;
}
//注意事项
//1、如果某个位置以及有了默认参数那么从这个位置往后从左到右都必须有默认值
int func02(int a, int b = 40, int c = 50)
{
return a + b + c;
}
//2、如果函数声明有默认参数函数实现就不能有默认参数
//例如,函数定义为 int func03(int a = 20, int b = 20){return a + b;}而函数声明为int func03(int a = 10, int b = 10);那么编译器不知道按照哪个默认参数来运行
//声明和实现只能有一个有默认参数
int func03(int a = 10, int b = 10);
//这个是函数的实现
int func03(int a , int b)
{
return a + b;
}
int main()
{
cout << func01(10, 20, 30) << endl;
cout << func02(10) << endl;
cout << func02(10, 20) << endl;
cout << func02(10, 20,30) << endl;
cout << func03() << endl;
system("pause");
return 0;
}
```
运行结果:
- 60
- 100
- 80
- 60
- 20
- 请按任意键继续. . .
## 1.9 函数占位参数
① C++中函数的形参列表里可以有占位参数,用来做占位,调用函数时必须填补该位置。
② 语法:返回值类型 函数名 (数据类型) {}
```python
#include <iostream>
using namespace std;
//占位参数
//返回值类型 函数名(数据类型){}
//目前,占位参数还用不到,后面会用到
void func01(int a,int)
{
cout << "this is func01" << endl; //函数内部无法调用第二个参数无法像a+b这样调用第二个参数
}
//占位参数,还可以有默认参数
void func02(int a, int = 10)
{
cout << "this is func02" << endl;
}
int main()
{
func01(10, 20);
func02(10); //有默认参数,可以只输入一个参数
system("pause");
return 0;
}
```
运行结果:
- this is func01
- this is func02
- 请按任意键继续. . .
# 2. 函数重载
## 2.1 函数重载条件
① 作用:函数名可以相同,提高复用性。
② 函数重载满足条件:
1. 同一个作用域下。
2. 函数名称相同。
3. 函数参数类型不同 或者 个数不同 或者 顺序不同。
③ 函数的返回值不可以作为函数重载的条件。
```python
#include <iostream>
using namespace std;
//函数重载
//可以让函数名相同,提高复用性
//函数重载的满足条件
//1、同一作用域下
//2、函数名称相同
//3、函数参数类型不同或者个数不同或者顺序不同
void func()
{
cout << "func 的调用" << endl;
}
void func(int a)
{
cout << "func (int a) 的调用" << endl;
}
void func(double a)
{
cout << "func (double a) 的调用" << endl;
}
void func(double a, int b)
{
cout << "func (double a, int b) 的调用" << endl;
}
void func(int a, double b)
{
cout << "func (int a, double b) 的调用" << endl;
}
/*
注意事项
函数的返回值不可以作为函数重载的条件
int func(int a, double b)
//调用func(3.14,3)时编译器不知道是调用int func(int a, double b){}还是调用void func(int a, double b){}
{
cout << "func (int a, double b) 的调用" << endl;
}
*/
int main()
{
func(); // 根据传入参数的个数不同,调用不同的函数
func(10);
func(3.14); // 根据传入参数的类型不同,调用不同的函数
func(3,3.14); // 根据传入参数的顺序不同,调用不同的函数
func(3.14,3); // 根据传入参数的顺序不同,调用不同的函数
system("pause");
return 0;
}
```
运行结果:
- func 的调用
- func (int a) 的调用
- func (double a) 的调用
- func (int a, double b) 的调用
- func (double a, int b) 的调用
- 请按任意键继续. . .
## 2.2 函数重载注意事项
① 引用作为重载条件。
② 函数重载碰到函数默认参数。
```python
#include <iostream>
using namespace std;
//函数重载的注意事项
//1、引用作为重载的条件
void fun(int& a) // int &a = 10; 不合法所以fun(10);无法调用
{
cout << "func(int &a)调用" << endl;
}
// const int &a = 10; 合法
void fun(const int& a) //语法是可以的const引用和普通引用属于类型不同fun(10)可以调用
{
cout << "func(const int &a)调用" << endl;
}
//2、函数重载碰到默认参数
void func2(int a,int b = 20)
{
cout << "func2(int a,int b = 20) 的调用" << endl;
}
void func2(int a)
{
cout << "func2(int a) 的调用" << endl;
}
int main()
{
int a = 10;
//变量可读可写所以调用变量时是调用可读可写的引用函数const int a = 10的fun(a);调用func(const int &a)调用
fun(a);
fun(10);
//既可以调用void func2(int a,int b = 20)也可以调用void func2(int a)
//func2(10); //当函数重载碰到默认参数,出现二义性,报错,尽量避免这种情况
func2(10,20); //不会出现二义性
system("pause");
return 0;
}
```
运行结果:
- func(int &a)调用
- func(const int &a)调用
- func2(int a,int b = 20) 的调用
- 请按任意键继续. . .

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,385 @@
# C++的指针
# 1. 指针
## 1.1 指针概念
① 指针的作用:可以通过指针间接访问内存。
1. 内存编号是从0开始记录的一般用十六进制数字表示。
2. 可以利用指针变量保存地址。
## 1.2 指针变量定义和使用
① 指针变量定义语法:数据类型 + 变量名;
```python
#include <iostream>
using namespace std;
int main()
{
//1、定义指针
int a = 10;
//指针定义的语法:数据类型 * 指针变量
int * p; //创建p为指针变量
//让指针记录变量a的地址
p = &a; // &为取址符号
cout << "a的地址为" << &a << endl;
cout << "指针p为" << p << endl; // 指针p存储的值 和变量a的地址是一样的
//2、使用指针
//可以通过解引用的方式来找到指针指向的内存
//指针前加 * 代表解引用,找到指针指向的内存中的数据
*p = 1000; //通过*p访问内存并修改内存的值
cout << "a= " << a << endl;
cout << "*p" << *p << endl;
system("pause"); //按任意键继续
return 0;
}
```
运行结果:
- a的地址为00FBFC78
- 指针p为00FBFC78
- a= 1000
- *p1000
- 请按任意键继续. . .
## 1.3 指针所占内存空间
① 在32位操作系统下不管什么类型的指针都占4个字节的内存。
② 在64位操作系统下不管什么类型的指针都占8个字节的内存但是实际开发环境一般都是32位操作系统下。
```python
#include <iostream>
using namespace std;
int main()
{
//指针所占内存空间
int a = 10;
/*
int * p; //p变量是 int * 数据类
p = &a;
等价于:
int * p = &a;
*/
int * p = &a;
cout << "sizeof(int * )= " << sizeof(p) << endl;
cout << "sizeof(int * )= " << sizeof(int(*)) << endl;
cout << "sizeof(float * )= " << sizeof(float(*)) << endl;
cout << "sizeof(double * )= " << sizeof(double(*)) << endl;
cout << "sizeof(char * )= " << sizeof(char(*)) << endl;
system("pause"); //按任意键继续
return 0;
}
```
运行结果:
- sizeof(int * )= 4
- sizeof(int * )= 4
- sizeof(float * )= 4
- sizeof(double * )= 4
- sizeof(char * )= 4
- 请按任意键继续. . .
## 1.4 空指针
① 指针变量指向内存中编号为0的空间。
② 用途:初始化指针变量。
③ 空指针指向的内存是不可以访问的。
```python
#include <iostream>
using namespace std;
int main()
{
//空指针
//1、空指针用于给指针变量进行初始化
int* p = NULL;
//2、空指针是不可以进行访问的
//0~255之间的内存编号是系统占用的因此不可以访问。
*p = 100; //对空指针解引用,然后操作它,这样是报错的
system("pause"); //按任意键继续
return 0;
}
```
## 1.5 野指针
① 野指针:指针变量指向非法的内存空间。
② 野指针和空指针都不是我们申请的空间,所以不要访问。
③ 例如创建了一个整型变量a是申请了一个整型变量的空间由于是申请的空间所以可以通过指针访问它。
```python
#include <iostream>
using namespace std;
int main()
{
//野指针
int* p = (int*)0x1100; // 0x1100是一个十六进制数int*使得十六进制数强行转换为地址。
// 拿指针随便指向并没有申请这个内存的访问权限的内存。
cout << *p << endl; // 报错地址并没有申请你还要去访问它就会报错
system("pause");
return 0;
}
```
## 1.6 const修饰指针
① 看const右侧紧跟着的是指针还是常量是指针就是常量指针是常量就是指针常量。
② 如果 const后面跟的是指针(*),就不能做 *p=20 操作,即不能修改指针指向的值。
③ 如果const 后面跟的常量(p),就不能做 p = &b 操作,即不能修改指针的指向。
```python
#include <iostream>
using namespace std;
int main()
{
int a = 10;
int b = 10;
//1、const修饰指针 常量指针
const int* p = &a; // const(常量) *(指针) → 常量指针
// *p = 20; 错误,常量指针 → 指针指向的值不可以改,指针的指向可以改
p = &b; // 正确
//2、const修饰指针 指针常量
int* const p2 = &a; // *(指针)const(常量) → 指针常量
*p2 = 100; //正确的
p2 = &b; //错误,指针的指向不可以改,指针指向的 值可以改
//3、const修饰指针和常量
const int* const p3 = &a;
*p3 = 100; //错误
p3 = &b; //错误
system("pause");
return 0;
}
```
## 1.7 指针和数组
① 利用指针访问数组中元素。
```python
#include <iostream>
using namespace std;
int main()
{
//指针和数组
//利用指针访问数组中的元素
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
cout << "第一个元素为:" << arr[0] << endl;
int* p = arr; //数组名arr就是数组的首地址
cout << "利用指针访问第一个元素:" << *p << endl;
p++;
cout << "利用指针访问第二个元素:" << *p << endl;
cout << "利用指针遍历数组:" << endl;
int* p2 = arr;
for (int i = 0; i < 10; i++)
{
//cout << arr[i] << endl;
cout << *p2 << endl;
p2++;
}
system("pause");
return 0;
}
```
运行结果:
- 第一个元素为1
- 利用指针访问第一个元素1
- 利用指针访问第二个元素2
- 利用指针遍历数组:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 请按任意键继续. . .
## 1.8 指针和函数
① 利用指针作函数的参数,可以修改实参的值。
② 地址传递可以改变实参的数据,值传递不可以改变实参的值。
③ 如果不想修改实参,就用值传递,如果想修改实参,就用地址传递。
④ 代码例子中temp的值会传递给 *p2 地址中的值所以a、b实参的值改变了。
![image.png](15_C++的指针_files/image.png)
```python
#include <iostream>
using namespace std;
void swap(int* p1, int* p2)
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
int main()
{
//指针和函数
int a = 10;
int b = 20;
swap(&a, &b);
//如果是地址传递,可以修改实参,原来 a = 10b = 20地址传递后 a = 20b = 10.
cout << "a =" << a << endl;
cout << "b =" << b << endl;
//如果是值传递,不可以修改实参,原来 a = 10b = 20值传递后 a = 10b = 20.
system("pause");
return 0;
}
```
运行结果:
- a =20
- b =10
- 请按任意键继续. . .
## 1.9 指针配合数组和函数案例
案例描述:封装一个函数,利用冒泡排序,实现对整型数字的升序排列。
例如: int arr[10] = {4,3,6,9,1,2,10,8,7,5}
```python
#include <iostream>
using namespace std;
//冒泡排序函数
void bubbleSort(int * arr, int len)
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - i - 1; j++)
{
//如果j>j+1的值交换数字
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
//打印数组
void printArray(int* arr, int len)
{
for (int i = 0; i < len; i++)
{
cout << arr[i] << endl;
}
}
int main()
{
//1、先创建数组
int arr[10] = { 4,3,6,1,2,9,10,8,7,5 };
//数组长度
int len = sizeof(arr) / sizeof(arr[0]);
//2、创建函数实现冒泡排序
bubbleSort(arr, len);
//3、打印排序后的数组
printArray(arr, len);
system("pause");
return 0;
}
```
运行结果:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 请按任意键继续. . .

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@ -0,0 +1,897 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的结构体"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 结构体"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 结构体属于用户自定义的数据类型,允许用户存储不同的数据类型。\n",
"\n",
"② 语法struct 结构体名 { 结构体成员列表 }\n",
"\n",
"③ 通过结构体创建变量的方式有三种:\n",
"\n",
"1. struct 结构体名 变量名\n",
"2. struct 结构体名 变量名 = { 成员1值成员2值 }\n",
"3. 定义结构体时顺便创建变量\n",
"\n",
"④ 结构体变量利用点.访问成员"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"#include <string>\n",
"//自定义数据类型,一些类型的集合组成一个类型\n",
"//语法 struct 类型名称 { 成员列表 }\n",
"//结构体定义的时候struct关键字不能省略\n",
"//1、创建学生数据类型学生包括(姓名,年龄,分数)\n",
"struct Student\n",
"{\n",
" //成员列表\n",
"\n",
" //姓名\n",
" string name;\n",
" //年龄\n",
" int age;\n",
" //分数\n",
" int score;\n",
"};\n",
"\n",
"int main()\n",
"{\n",
" //2.1 struct Student s1 s1类似结构体的实例值类似变量赋值int a = 10 → 属性 变量 变量值\n",
" //结构体创建的时候struct 关键字可以省略;上面结构体定义的时候 struct 可以省略\n",
" struct Student s1;\n",
" //给s1属性赋值通过点.访问结构体变量中的属性\n",
" s1.name = \"张三\";\n",
" s1.age = 18;\n",
" s1.score = 100;\n",
"\n",
" cout << \"姓名:\" << s1.name << \"年龄:\" << s1.age << \"分数:\" << s1.score << endl;\n",
"\n",
" //2.2 struct Student s2 = { ... }\n",
" struct Student s2 = { \"李四\",19,80 };\n",
" cout << \"姓名:\" << s2.name << \"年龄:\" << s2.age << \"分数:\" << s2.score << endl;\n",
" \n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 姓名:张三年龄:18分数100 \n",
" - 姓名:李四年龄:19分数80 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"#include <string>\n",
"//自定义数据类型,一些类型的集合组成一个类型\n",
"struct Student\n",
"{\n",
" //成员列表\n",
"\n",
" //姓名\n",
" string name;\n",
" //年龄\n",
" int age;\n",
" //分数\n",
" int score;\n",
"}s3; //2.3 创建结构体的时候,顺便创建个结构体变量\n",
"\n",
"int main()\n",
"{\n",
" //2.3 \n",
" s3.name = \"王五\";\n",
" s3.age = 20;\n",
" s3.score = 60;\n",
"\n",
" cout << \"姓名:\" << s3.name << \"年龄:\" << s3.age << \"分数:\" << s3.score << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 姓名:王五年龄:20分数60 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.1 结构体定义和使用"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 作用:将自定义的结构体放入到数组中方便维护。\n",
"\n",
"② 语法struct 结构体名 数组名[元素个数] = { {},{},...,{} }"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"#include <string>\n",
"//自定义数据类型,一些类型的集合组成一个类型\n",
"struct Student\n",
"{\n",
" //成员列表\n",
"\n",
" //姓名\n",
" string name;\n",
" //年龄\n",
" int age;\n",
" //分数\n",
" int score;\n",
"}; \n",
"\n",
"int main()\n",
"{\n",
" //2、创建结构体数组\n",
" struct Student stuArray[3] =\n",
" {\n",
" {\"张三\",18,100},\n",
" {\"李四\",28,99},\n",
" {\"王五\",38,66}\n",
" };\n",
"\n",
" //3、给结构体数组中的元素赋值\n",
" stuArray[2].name = \"赵六\";\n",
" stuArray[2].age = 80;\n",
" stuArray[2].score = 60;\n",
"\n",
" //4、遍历结构体数组\n",
" for (int i = 0; i < 3; i++)\n",
" {\n",
" cout << \"姓名:\" << stuArray[i].name << \"年龄:\" << stuArray[i].age << \"分数:\" << stuArray[i].score << endl;\n",
" }\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 姓名张三年龄18分数100 \n",
" - 姓名李四年龄28分数99 \n",
" - 姓名赵六年龄80分数60\n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.2 结构体数组"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 作用:将自定义的结构体放入到数组中方便维护。\n",
"\n",
"② 语法struct 结构体名 数组名[元素个数] = { {},{},...,{} }"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"#include <string>\n",
"//自定义数据类型,一些类型的集合组成一个类型\n",
"struct Student\n",
"{\n",
" //成员列表\n",
"\n",
" //姓名\n",
" string name;\n",
" //年龄\n",
" int age;\n",
" //分数\n",
" int score;\n",
"};\n",
"\n",
"int main()\n",
"{\n",
" //2、创建结构体数组\n",
" struct Student stuArray[3] =\n",
" {\n",
" {\"张三\",18,100},\n",
" {\"李四\",28,99},\n",
" {\"王五\",38,66}\n",
" };\n",
"\n",
" //3、给结构体数组中的元素赋值\n",
" stuArray[2].name = \"赵六\";\n",
" stuArray[2].age = 80;\n",
" stuArray[2].score = 60;\n",
"\n",
" //4、遍历结构体数组\n",
" for (int i = 0; i < 3; i++)\n",
" {\n",
" cout << \"姓名:\" << stuArray[i].name << \"年龄:\" << stuArray[i].age << \"分数:\" << stuArray[i].score << endl;\n",
" }\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 姓名张三年龄18分数100 \n",
" - 姓名李四年龄28分数99 \n",
" - 姓名赵六年龄80分数60 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.3 结构体指针"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 作用:通过指针访问结构体中的成员。\n",
"\n",
"② 利用操作符 · > 可以通过结构体指针访问结构体属性。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"#include <string>\n",
"\n",
"//结构体指针\n",
"\n",
"//定义学生结构体\n",
"struct Student\n",
"{\n",
" string name; //姓名\n",
" int age; //年龄\n",
" int score; //分数\n",
"};\n",
"\n",
"int main()\n",
"{\n",
" // 1、创建学生结构体变量这里的 struct 可以省略\n",
" struct Student s = { \"张三\",18,100 };\n",
"\n",
" //2、通过指针指向结构体变量\n",
" struct Student* p = &s; //对s取地址 tudent * p 类似 int * p这里的 struct 可以省略\n",
"\n",
" //3、通过指针访问结构体变量中的数据\n",
" //通过结构体指针 访问结构体中的属性,需要利用'->'\n",
" cout << \"姓名:\" << p->name << \"年龄:\" << p->age << \"分数:\" << p->score << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
"- 姓名张三年龄18分数100 \n",
"- 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.4 结构体嵌套结构体"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 结构体中的成员可以是另一个结构体。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"#include <string>\n",
"\n",
"//因为老师的结构体里有学生的结构体,所以学生结构体要在老师结构体前面先定义\n",
"//定义学生结构体\n",
"struct student\n",
"{\n",
" string name; //姓名\n",
" int age; //年龄\n",
" int score; //分数\n",
"}; \n",
"\n",
"//定义老师结构体\n",
"struct teacher\n",
"{\n",
" int id; //教师编号\n",
" string name; //教师姓名\n",
" int age; //年龄\n",
" struct student stu; //学生结构体\n",
"};\n",
"\n",
"int main()\n",
"{\n",
" //结构体嵌套结构体\n",
" //创建老师\n",
" teacher t;\n",
" t.id = 10000;\n",
" t.name = \"老王\";\n",
" t.age = 50;\n",
" t.stu.name = \"小王\";\n",
" t.stu.age = 20;\n",
" t.stu.score = 60;\n",
"\n",
" cout << \"老师姓名:\" << t.name << \"老师编号:\" << t.id << \"老师年龄:\" << t.age\n",
" << \"老师辅导的学生姓名:\" << t.stu.name << \"学生年龄:\" << t.stu.age \n",
" << \"学生考试分数:\" << t.stu.score << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 老师姓名:老王 老师编号10000 老师年龄50 老师辅导的学生姓名:小王 学生年龄20 学生考试分数60\n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.5 结构体做函数参数"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 作用:将结构体作为参数向函数中传递,传递方式有两种。\n",
"\n",
"② 传递方式有两种:\n",
"\n",
"1. 值传递\n",
"2. 地址传递"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"#include <string>\n",
"\n",
"//定义学生结构体\n",
"struct student\n",
"{\n",
" string name; //姓名\n",
" int age; //年龄\n",
" int score; //分数\n",
"};\n",
"\n",
"//定义老师结构体\n",
"struct teacher\n",
"{\n",
" int id; //教师编号\n",
" string name; //教师姓名\n",
" int age; //年龄\n",
" struct student stu; //学生结构体\n",
"};\n",
"\n",
"//打印学生信息的函数\n",
"//1、值传递\n",
"void printStudent1(struct student s)\n",
"{\n",
" cout << \"子函数 值传递前 姓名:\" << s.name << \"年龄:\" << s.age << \"分数:\" << s.score << endl;\n",
"\n",
" s.age = 100;\n",
"}\n",
"\n",
"//2、地址传递\n",
"void printStudent2(struct student* p)\n",
"{\n",
" cout << \"子函数 地址传递前 姓名:\" << p->name << \"年龄:\" << p->age << \"分数:\" << p->score << endl;\n",
"\n",
" p->score = 90;\n",
"}\n",
"\n",
"int main()\n",
"{\n",
" //结构体做函数参数\n",
" //将学生传入到一个参数中,打印学生身上的所有信息\n",
"\n",
" //创建结构体变量\n",
" struct student s;\n",
" s.name = \"张三\";\n",
" s.age = 20;\n",
" s.score = 85;\n",
"\n",
" cout << \"main函数 传递前 姓名:\" << s.name << \"年龄:\" << s.age << \"分数:\" << s.score << endl;\n",
"\n",
" printStudent1(s);\n",
"\n",
" cout << \"子函数 值传递后 姓名:\" << s.name << \"年龄:\" << s.age << \"分数:\" << s.score << endl;\n",
"\n",
" printStudent2(&s);\n",
"\n",
" cout << \"子函数 地址传递后 姓名:\" << s.name << \"年龄:\" << s.age << \"分数:\" << s.score << endl;\n",
"\n",
"\n",
" cout << \"main函数 传递后 姓名:\" << s.name << \"年龄:\" << s.age << \"分数:\" << s.score << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - main函数 传递前 姓名张三年龄20分数85 \n",
" - 子函数 值传递前 姓名张三年龄20分数85 \n",
" - 子函数 值传递后 姓名张三年龄20分数85 \n",
" - 子函数 地址传递前 姓名张三年龄20分数85 \n",
" - 子函数 地址传递后 姓名张三年龄20分数90 \n",
" - main函数 传递后 姓名张三年龄20分数90 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.6 结构体中const使用"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 作用const来防止误操作。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"#include <string>\n",
"\n",
"//const 的使用场景\n",
"\n",
"struct student\n",
"{\n",
" //姓名\n",
" string name;\n",
" //年龄\n",
" int age;\n",
" //分数\n",
" int score;\n",
"};\n",
"\n",
"//将函数中形参设置为指针,用地址传递,而不是值传递,可以减少内存空间,而且不会复制新的副本\n",
"//值传递需要复制新的副本,如果有成千上万个学生调用结构体,会复制成千上个副本\n",
"void printStudents(const student* s)\n",
"{\n",
" s->age = 150; //报错因为假如const之后一旦有修改的操作就会报错可以防止我们的误操作。\n",
" cout << \"姓名:\" << s->name << \"年龄:\" << s->age << \"分数:\" << s->score << endl;\n",
"}\n",
"\n",
"\n",
"int main()\n",
"{\n",
" //创建结构体变量\n",
" struct student s = { \"张三\",15,70 };\n",
"\n",
" //通过函数打印结构体变量信息\n",
" printStudents(&s);\n",
"\n",
" cout << \"main中张三年龄为\" << s.age << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.7 结构体案例(一)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"案例描述学校正在做毕设项目每名老师带领5个学生总共有3名老师需求如下设计学生和老师的结构体其中在老师的结构体中有老师姓名和一个存放5名学生的数组作为成员学生的成员有姓名、考试分数、创建数组存放3名老师通过函数给每个老师及所带的学生赋值。最终打印出老师数据以及老师所带的学生数据。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"#include <string>\n",
"#include <Ctime>\n",
"\n",
"//学生结构体定义\n",
"struct Student\n",
"{\n",
" //姓名\n",
" string sName;\n",
" //学生数组\n",
" int score;\n",
"};\n",
"\n",
"//老师结构体\n",
"struct Teacher\n",
"{\n",
" //姓名\n",
" string tName;\n",
" //学生数组\n",
" struct Student sArray[5];\n",
"};\n",
"\n",
"//给老师和学生赋值的函数\n",
"void allocateSpace(struct Teacher tArray[], int len) //接收数组的两种方式:一用指针,二用数组名 struct Teacher tArray[]\n",
"{\n",
" string nameSeed = \"ABCDE\";\n",
" //给老师开始赋值\n",
" for (int i = 0; i < len; i++)\n",
" {\n",
" tArray[i].tName = \"Teacher_\";\n",
" tArray[i].tName += nameSeed[i];\n",
"\n",
" //通过循环给每名老师所带的学生赋值\n",
" for (int j = 0; j < 5; j++)\n",
" {\n",
" tArray[i].sArray[j].sName = \"Student_\";\n",
" tArray[i].sArray[j].sName += nameSeed[j];\n",
"\n",
" int random = rand() % 61 + 40; // 40 ~ 100\n",
" tArray[i].sArray[j].score = random; //\n",
"\n",
" }\n",
" }\n",
"}\n",
"\n",
"//打印所有信息\n",
"void printInfo(struct Teacher tArray[], int len)\n",
"{\n",
" for (int i = 0;i<len;i++)\n",
" {\n",
" cout << \"老师姓名:\" << tArray[i].tName << endl;\n",
" \n",
" for (int j = 0; j < 5; j++)\n",
" {\n",
" cout << \"\\t学生姓名\" << tArray[i].sArray[j].sName \n",
" << \" 考试分数:\" << tArray[i].sArray[j].score << endl;\n",
" }\n",
" }\n",
"}\n",
"\n",
"int main()\n",
"{\n",
" //随机数种子\n",
" srand((unsigned int)time(NULL));\n",
"\n",
" //1、创建3名老师的数组\n",
" struct Teacher tArray[3];\n",
"\n",
" //2、通过函数给3名老师的信息赋值并给老师带的学生信息赋值\n",
" int len = sizeof(tArray) / sizeof(tArray[0]);\n",
" allocateSpace(tArray, len);\n",
"\n",
" //3、打印所有老师及所带的学生信息\n",
" printInfo(tArray, len);\n",
"\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"运行结果: \n",
"老师姓名Teacher_A\n",
" 学生姓名Student_A 考试分数81\n",
" 学生姓名Student_B 考试分数85\n",
" 学生姓名Student_C 考试分数91\n",
" 学生姓名Student_D 考试分数66\n",
" 学生姓名Student_E 考试分数55\n",
"老师姓名Teacher_B\n",
" 学生姓名Student_A 考试分数87\n",
" 学生姓名Student_B 考试分数50\n",
" 学生姓名Student_C 考试分数57\n",
" 学生姓名Student_D 考试分数40\n",
" 学生姓名Student_E 考试分数43\n",
"老师姓名Teacher_C\n",
" 学生姓名Student_A 考试分数72\n",
" 学生姓名Student_B 考试分数64\n",
" 学生姓名Student_C 考试分数80\n",
" 学生姓名Student_D 考试分数92\n",
" 学生姓名Student_E 考试分数58\n",
"请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.8 结构体案例(二)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"案例描述设计一个英雄的结构体包括成员姓名年龄性别创建结构体数组数组中存放5名英雄。通过冒泡排序算法将数组中英雄按照年龄进行升序排序最终打印排序后的结果。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"五名英雄信息如下: \n",
" - {\"刘备\",23,\"男\"} \n",
" - {\"关羽\",22,\"男\"} \n",
" - {\"张飞\",20,\"男\"} \n",
" - {\"赵云\",21,\"女\"} \n",
" - {\"貂蝉\",19,\"女\"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"//1、设计英雄结构体\n",
"struct Hero\n",
"{\n",
" //姓名\n",
" string name;\n",
" //年龄\n",
" int age;\n",
" //性别\n",
" string sex;\n",
"};\n",
"\n",
"//冒泡排序,实现年龄升序排列\n",
"void bubbleSort(struct Hero heroArray[], int len)\n",
"{\n",
" for (int i = 0; i < len - 1; i++)\n",
" {\n",
" for (int j = 0; j < len - i - 1; j++)\n",
" {\n",
" //如果j下标的年龄大于j+1下标的元素的年龄交换两个元素\n",
" if (heroArray[j].age > heroArray[j + 1].age)\n",
" {\n",
" struct Hero temp = heroArray[j]; //创建一个临时结构体变量\n",
" heroArray[j] = heroArray[j + 1];\n",
" heroArray[j + 1] = temp;\n",
" }\n",
" }\n",
" }\n",
"}\n",
"\n",
"void printHero(struct Hero heroArray[], int len)\n",
"{\n",
" for (int i = 0; i < len; i++)\n",
" {\n",
" cout << \"姓名:\" << heroArray[i].name << \" 年龄:\" << heroArray[i].age\n",
" << \" 性别:\" << heroArray[i].sex << endl;\n",
" }\n",
"}\n",
"\n",
"int main()\n",
"{\n",
"\n",
" //2、创建数组存放5名英雄\n",
" struct Hero heroArray[5] =\n",
" {\n",
" {\"刘备\",23,\"男\"},\n",
" {\"关羽\",22,\"男\"},\n",
" {\"张飞\",20,\"男\"},\n",
" {\"赵云\",21,\"女\"},\n",
" {\"貂蝉\",19,\"女\"},\n",
" };\n",
"\n",
" int len = sizeof(heroArray) / sizeof(heroArray[0]);\n",
" cout << \"排序前的打印结果\" << endl;\n",
" for (int i = 0; i < len; i++)\n",
" {\n",
" cout << \"姓名:\" << heroArray[i].name << \" 年龄:\" << heroArray[i].age\n",
" << \" 性别:\" << heroArray[i].sex << endl;\n",
" }\n",
"\n",
" //3、对数组进行排序按照年龄进行升序排序\n",
" bubbleSort(heroArray, len);\n",
"\n",
" //4、将排序后结果打印输出\n",
" cout << \"排序后的打印结果\" << endl;\n",
" printHero(heroArray,len);\n",
"\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 排序前的打印结果 \n",
" - 姓名:刘备 年龄23 性别:男 \n",
" - 姓名:关羽 年龄22 性别:男 \n",
" - 姓名:张飞 年龄20 性别:男 \n",
" - 姓名:赵云 年龄21 性别:女 \n",
" - 姓名:貂蝉 年龄19 性别:女 \n",
" - 排序后的打印结果 \n",
" - 姓名:貂蝉 年龄19 性别:女 \n",
" - 姓名:张飞 年龄20 性别:男 \n",
" - 姓名:赵云 年龄21 性别:女 \n",
" - 姓名:关羽 年龄22 性别:男 \n",
" - 姓名:刘备 年龄23 性别:男 \n",
" - 请按任意键继续. . ."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,674 @@
# C++的结构体
# 1. 结构体
① 结构体属于用户自定义的数据类型,允许用户存储不同的数据类型。
② 语法struct 结构体名 { 结构体成员列表 }
③ 通过结构体创建变量的方式有三种:
1. struct 结构体名 变量名
2. struct 结构体名 变量名 = { 成员1值成员2值 }
3. 定义结构体时顺便创建变量
④ 结构体变量利用点.访问成员
```python
#include <iostream>
using namespace std;
#include <string>
//自定义数据类型,一些类型的集合组成一个类型
//语法 struct 类型名称 { 成员列表 }
//结构体定义的时候struct关键字不能省略
//1、创建学生数据类型学生包括(姓名,年龄,分数)
struct Student
{
//成员列表
//姓名
string name;
//年龄
int age;
//分数
int score;
};
int main()
{
//2.1 struct Student s1 s1类似结构体的实例值类似变量赋值int a = 10 → 属性 变量 变量值
//结构体创建的时候struct 关键字可以省略;上面结构体定义的时候 struct 可以省略
struct Student s1;
//给s1属性赋值通过点.访问结构体变量中的属性
s1.name = "张三";
s1.age = 18;
s1.score = 100;
cout << "姓名:" << s1.name << "年龄:" << s1.age << "分数" << s1.score << endl;
//2.2 struct Student s2 = { ... }
struct Student s2 = { "李四",19,80 };
cout << "姓名:" << s2.name << "年龄:" << s2.age << "分数" << s2.score << endl;
system("pause");
return 0;
}
```
运行结果:
- 姓名:张三年龄:18分数100
- 姓名:李四年龄:19分数80
- 请按任意键继续. . .
```python
#include <iostream>
using namespace std;
#include <string>
//自定义数据类型,一些类型的集合组成一个类型
struct Student
{
//成员列表
//姓名
string name;
//年龄
int age;
//分数
int score;
}s3; //2.3 创建结构体的时候,顺便创建个结构体变量
int main()
{
//2.3
s3.name = "王五";
s3.age = 20;
s3.score = 60;
cout << "姓名:" << s3.name << "年龄:" << s3.age << "分数" << s3.score << endl;
system("pause");
return 0;
}
```
运行结果:
- 姓名:王五年龄:20分数60
- 请按任意键继续. . .
## 1.1 结构体定义和使用
① 作用:将自定义的结构体放入到数组中方便维护。
② 语法struct 结构体名 数组名[元素个数] = { {},{},...,{} }
```python
#include <iostream>
using namespace std;
#include <string>
//自定义数据类型,一些类型的集合组成一个类型
struct Student
{
//成员列表
//姓名
string name;
//年龄
int age;
//分数
int score;
};
int main()
{
//2、创建结构体数组
struct Student stuArray[3] =
{
{"张三",18,100},
{"李四",28,99},
{"王五",38,66}
};
//3、给结构体数组中的元素赋值
stuArray[2].name = "赵六";
stuArray[2].age = 80;
stuArray[2].score = 60;
//4、遍历结构体数组
for (int i = 0; i < 3; i++)
{
cout << "姓名:" << stuArray[i].name << "年龄" << stuArray[i].age << "分数" << stuArray[i].score << endl;
}
system("pause");
return 0;
}
```
运行结果:
- 姓名张三年龄18分数100
- 姓名李四年龄28分数99
- 姓名赵六年龄80分数60
- 请按任意键继续. . .
## 1.2 结构体数组
① 作用:将自定义的结构体放入到数组中方便维护。
② 语法struct 结构体名 数组名[元素个数] = { {},{},...,{} }
```python
#include <iostream>
using namespace std;
#include <string>
//自定义数据类型,一些类型的集合组成一个类型
struct Student
{
//成员列表
//姓名
string name;
//年龄
int age;
//分数
int score;
};
int main()
{
//2、创建结构体数组
struct Student stuArray[3] =
{
{"张三",18,100},
{"李四",28,99},
{"王五",38,66}
};
//3、给结构体数组中的元素赋值
stuArray[2].name = "赵六";
stuArray[2].age = 80;
stuArray[2].score = 60;
//4、遍历结构体数组
for (int i = 0; i < 3; i++)
{
cout << "姓名:" << stuArray[i].name << "年龄" << stuArray[i].age << "分数" << stuArray[i].score << endl;
}
system("pause");
return 0;
}
```
运行结果:
- 姓名张三年龄18分数100
- 姓名李四年龄28分数99
- 姓名赵六年龄80分数60
- 请按任意键继续. . .
## 1.3 结构体指针
① 作用:通过指针访问结构体中的成员。
② 利用操作符 · > 可以通过结构体指针访问结构体属性。
```python
#include <iostream>
using namespace std;
#include <string>
//结构体指针
//定义学生结构体
struct Student
{
string name; //姓名
int age; //年龄
int score; //分数
};
int main()
{
// 1、创建学生结构体变量这里的 struct 可以省略
struct Student s = { "张三",18,100 };
//2、通过指针指向结构体变量
struct Student* p = &s; //对s取地址 tudent * p 类似 int * p这里的 struct 可以省略
//3、通过指针访问结构体变量中的数据
//通过结构体指针 访问结构体中的属性,需要利用'->'
cout << "姓名:" << p->name << "年龄:" << p->age << "分数:" << p->score << endl;
system("pause");
return 0;
}
```
运行结果:
- 姓名张三年龄18分数100
- 请按任意键继续. . .
## 1.4 结构体嵌套结构体
① 结构体中的成员可以是另一个结构体。
```python
#include <iostream>
using namespace std;
#include <string>
//因为老师的结构体里有学生的结构体,所以学生结构体要在老师结构体前面先定义
//定义学生结构体
struct student
{
string name; //姓名
int age; //年龄
int score; //分数
};
//定义老师结构体
struct teacher
{
int id; //教师编号
string name; //教师姓名
int age; //年龄
struct student stu; //学生结构体
};
int main()
{
//结构体嵌套结构体
//创建老师
teacher t;
t.id = 10000;
t.name = "老王";
t.age = 50;
t.stu.name = "小王";
t.stu.age = 20;
t.stu.score = 60;
cout << "老师姓名:" << t.name << "老师编号" << t.id << "老师年龄" << t.age
<< "老师辅导的学生姓名:" << t.stu.name << "学生年龄" << t.stu.age
<< "学生考试分数:" << t.stu.score << endl;
system("pause");
return 0;
}
```
运行结果:
- 老师姓名:老王 老师编号10000 老师年龄50 老师辅导的学生姓名:小王 学生年龄20 学生考试分数60
- 请按任意键继续. . .
## 1.5 结构体做函数参数
① 作用:将结构体作为参数向函数中传递,传递方式有两种。
② 传递方式有两种:
1. 值传递
2. 地址传递
```python
#include <iostream>
using namespace std;
#include <string>
//定义学生结构体
struct student
{
string name; //姓名
int age; //年龄
int score; //分数
};
//定义老师结构体
struct teacher
{
int id; //教师编号
string name; //教师姓名
int age; //年龄
struct student stu; //学生结构体
};
//打印学生信息的函数
//1、值传递
void printStudent1(struct student s)
{
cout << "子函数 值传递前 姓名:" << s.name << "年龄" << s.age << "分数" << s.score << endl;
s.age = 100;
}
//2、地址传递
void printStudent2(struct student* p)
{
cout << "子函数 地址传递前 姓名:" << p->name << "年龄:" << p->age << "分数:" << p->score << endl;
p->score = 90;
}
int main()
{
//结构体做函数参数
//将学生传入到一个参数中,打印学生身上的所有信息
//创建结构体变量
struct student s;
s.name = "张三";
s.age = 20;
s.score = 85;
cout << "main函数 传递前 姓名:" << s.name << "年龄" << s.age << "分数" << s.score << endl;
printStudent1(s);
cout << "子函数 值传递后 姓名:" << s.name << "年龄" << s.age << "分数" << s.score << endl;
printStudent2(&s);
cout << "子函数 地址传递后 姓名:" << s.name << "年龄" << s.age << "分数" << s.score << endl;
cout << "main函数 传递后 姓名:" << s.name << "年龄" << s.age << "分数" << s.score << endl;
system("pause");
return 0;
}
```
运行结果:
- main函数 传递前 姓名张三年龄20分数85
- 子函数 值传递前 姓名张三年龄20分数85
- 子函数 值传递后 姓名张三年龄20分数85
- 子函数 地址传递前 姓名张三年龄20分数85
- 子函数 地址传递后 姓名张三年龄20分数90
- main函数 传递后 姓名张三年龄20分数90
- 请按任意键继续. . .
## 1.6 结构体中const使用
① 作用const来防止误操作。
```python
#include <iostream>
using namespace std;
#include <string>
//const 的使用场景
struct student
{
//姓名
string name;
//年龄
int age;
//分数
int score;
};
//将函数中形参设置为指针,用地址传递,而不是值传递,可以减少内存空间,而且不会复制新的副本
//值传递需要复制新的副本,如果有成千上万个学生调用结构体,会复制成千上个副本
void printStudents(const student* s)
{
s->age = 150; //报错因为假如const之后一旦有修改的操作就会报错可以防止我们的误操作。
cout << "姓名:" << s->name << "年龄:" << s->age << "分数:" << s->score << endl;
}
int main()
{
//创建结构体变量
struct student s = { "张三",15,70 };
//通过函数打印结构体变量信息
printStudents(&s);
cout << "main中张三年龄为" << s.age << endl;
system("pause");
return 0;
}
```
## 1.7 结构体案例(一)
案例描述学校正在做毕设项目每名老师带领5个学生总共有3名老师需求如下设计学生和老师的结构体其中在老师的结构体中有老师姓名和一个存放5名学生的数组作为成员学生的成员有姓名、考试分数、创建数组存放3名老师通过函数给每个老师及所带的学生赋值。最终打印出老师数据以及老师所带的学生数据。
```python
#include <iostream>
using namespace std;
#include <string>
#include <Ctime>
//学生结构体定义
struct Student
{
//姓名
string sName;
//学生数组
int score;
};
//老师结构体
struct Teacher
{
//姓名
string tName;
//学生数组
struct Student sArray[5];
};
//给老师和学生赋值的函数
void allocateSpace(struct Teacher tArray[], int len) //接收数组的两种方式:一用指针,二用数组名 struct Teacher tArray[]
{
string nameSeed = "ABCDE";
//给老师开始赋值
for (int i = 0; i < len; i++)
{
tArray[i].tName = "Teacher_";
tArray[i].tName += nameSeed[i];
//通过循环给每名老师所带的学生赋值
for (int j = 0; j < 5; j++)
{
tArray[i].sArray[j].sName = "Student_";
tArray[i].sArray[j].sName += nameSeed[j];
int random = rand() % 61 + 40; // 40 ~ 100
tArray[i].sArray[j].score = random; //
}
}
}
//打印所有信息
void printInfo(struct Teacher tArray[], int len)
{
for (int i = 0;i<len;i++)
{
cout << "老师姓名:" << tArray[i].tName << endl;
for (int j = 0; j < 5; j++)
{
cout << "\t学生姓名" << tArray[i].sArray[j].sName
<< " 考试分数:" << tArray[i].sArray[j].score << endl;
}
}
}
int main()
{
//随机数种子
srand((unsigned int)time(NULL));
//1、创建3名老师的数组
struct Teacher tArray[3];
//2、通过函数给3名老师的信息赋值并给老师带的学生信息赋值
int len = sizeof(tArray) / sizeof(tArray[0]);
allocateSpace(tArray, len);
//3、打印所有老师及所带的学生信息
printInfo(tArray, len);
system("pause");
return 0;
}
```
```python
运行结果:
老师姓名Teacher_A
学生姓名Student_A 考试分数81
学生姓名Student_B 考试分数85
学生姓名Student_C 考试分数91
学生姓名Student_D 考试分数66
学生姓名Student_E 考试分数55
老师姓名Teacher_B
学生姓名Student_A 考试分数87
学生姓名Student_B 考试分数50
学生姓名Student_C 考试分数57
学生姓名Student_D 考试分数40
学生姓名Student_E 考试分数43
老师姓名Teacher_C
学生姓名Student_A 考试分数72
学生姓名Student_B 考试分数64
学生姓名Student_C 考试分数80
学生姓名Student_D 考试分数92
学生姓名Student_E 考试分数58
请按任意键继续. . .
```
## 1.8 结构体案例(二)
案例描述设计一个英雄的结构体包括成员姓名年龄性别创建结构体数组数组中存放5名英雄。通过冒泡排序算法将数组中英雄按照年龄进行升序排序最终打印排序后的结果。
五名英雄信息如下:
- {"刘备",23,"男"}
- {"关羽",22,"男"}
- {"张飞",20,"男"}
- {"赵云",21,"女"}
- {"貂蝉",19,"女"}
```python
#include <iostream>
using namespace std;
//1、设计英雄结构体
struct Hero
{
//姓名
string name;
//年龄
int age;
//性别
string sex;
};
//冒泡排序,实现年龄升序排列
void bubbleSort(struct Hero heroArray[], int len)
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - i - 1; j++)
{
//如果j下标的年龄大于j+1下标的元素的年龄交换两个元素
if (heroArray[j].age > heroArray[j + 1].age)
{
struct Hero temp = heroArray[j]; //创建一个临时结构体变量
heroArray[j] = heroArray[j + 1];
heroArray[j + 1] = temp;
}
}
}
}
void printHero(struct Hero heroArray[], int len)
{
for (int i = 0; i < len; i++)
{
cout << "姓名:" << heroArray[i].name << " 年龄" << heroArray[i].age
<< " 性别:" << heroArray[i].sex << endl;
}
}
int main()
{
//2、创建数组存放5名英雄
struct Hero heroArray[5] =
{
{"刘备",23,"男"},
{"关羽",22,"男"},
{"张飞",20,"男"},
{"赵云",21,"女"},
{"貂蝉",19,"女"},
};
int len = sizeof(heroArray) / sizeof(heroArray[0]);
cout << "排序前的打印结果" << endl;
for (int i = 0; i < len; i++)
{
cout << "姓名:" << heroArray[i].name << " 年龄" << heroArray[i].age
<< " 性别:" << heroArray[i].sex << endl;
}
//3、对数组进行排序按照年龄进行升序排序
bubbleSort(heroArray, len);
//4、将排序后结果打印输出
cout << "排序后的打印结果" << endl;
printHero(heroArray,len);
system("pause");
return 0;
}
```
运行结果:
- 排序前的打印结果
- 姓名:刘备 年龄23 性别:男
- 姓名:关羽 年龄22 性别:男
- 姓名:张飞 年龄20 性别:男
- 姓名:赵云 年龄21 性别:女
- 姓名:貂蝉 年龄19 性别:女
- 排序后的打印结果
- 姓名:貂蝉 年龄19 性别:女
- 姓名:张飞 年龄20 性别:男
- 姓名:赵云 年龄21 性别:女
- 姓名:关羽 年龄22 性别:男
- 姓名:刘备 年龄23 性别:男
- 请按任意键继续. . .

View File

@ -0,0 +1,429 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的内存模型"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 内存分区"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① C++在程序执行时将内存大方向划分为4个区域。\n",
"\n",
"1. 代码区:存放函数体的二进制代码,由操作系统进行管理的。\n",
"2. 全局区:存放全局变量和静态变量以及常量。\n",
"3. 栈区:由编译器自动分配释放,存放函数的参数值、局部变量等。\n",
"4. 堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收。\n",
"\n",
"② 内存四区的意义:不同区域存放的数据,赋予不同的生命周期,给我们更大的灵活编程。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 在程序编译后生成了exe可执行程序未执行该程序前分为两个区域代码区、全局区。\n",
"\n",
"② 所有的写的代码(注释、变量、语句等)都会放到代码区中。\n",
"\n",
"③ 栈区中的数据由编译器决定数据的生成和死亡。\n",
"\n",
"④ 堆区中的数据由程序员决定数据的生存和死亡。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 2. 内存四区"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.1 代码区"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 代码区:\n",
"\n",
"1. 存放CPU执行的机器指令。\n",
"2. 代码区是共享的,共享的目的是对于频繁被执行的程序,只需要内存中有一份代码即可。\n",
"3. 代码区是只读的,使其只读的原因是防止程序员意外地修改了它的指令。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.2 全局区"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 全局区:\n",
"\n",
"1. 全局变量和静态变量存放在此,局部常量不放在全局区。\n",
"2. 全局区还包含了常量区,字符串常量和其他常量也存放在此。\n",
"3. 该区域的数据在程序结束后由操作系统释放。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"//全局变量\n",
"int g_a = 10;\n",
"int g_b = 20;\n",
"\n",
"//const修饰的全局常量\n",
"const int c_g_a = 50;\n",
"const int c_g_b = 60;\n",
"\n",
"int main()\n",
"{\n",
" //全局区\n",
"\n",
" //全局变量、静态变量、常量\n",
"\n",
" //创建普通局部变量\n",
" int a = 30;\n",
" int b = 40;\n",
"\n",
" cout << \"局部变量a的地址为\" << (int)&a << endl;\n",
" cout << \"局部变量b的地址为\" << (int)&b << endl;\n",
"\n",
" cout << \"全局变量g_a的地址为\" << (int)&g_a << endl;\n",
" cout << \"全局变量g_b的地址为\" << (int)&g_b << endl;\n",
"\n",
" //静态变量 在普通变量前面加static,属于静态变量\n",
" static int s_a = 10;\n",
" static int s_b = 10;\n",
"\n",
" cout << \"静态变量s_a的地址为\" << (int)&s_a << endl;\n",
" cout << \"静态变量s_b的地址为\" << (int)&s_b << endl;\n",
"\n",
" //常量\n",
" //字符串常量\n",
" cout << \"字符串常量的地址为:\" << (int)&\"hello world\" << endl;\n",
"\n",
" //const修饰的变量\n",
" //const修饰的局部变量,const修饰的局部变量\n",
" cout << \"全局常量c_g_a的地址为\" << (int)&c_g_a << endl;\n",
" cout << \"全局常量c_g_a的地址为\" << (int)&c_g_b << endl;\n",
"\n",
" const int c_l_a = 10; // c-const g-global l-local;\n",
" const int c_l_b = 10;\n",
" cout << \"局域常量c_l_a的地址为\" << (int)&c_l_a << endl;\n",
" cout << \"局域常量c_l_b的地址为\" << (int)&c_l_a << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 局部变量a的地址为14023100 \n",
" - 局部变量b的地址为14023088 \n",
" - 全局变量g_a的地址为4964352 \n",
" - 全局变量g_b的地址为4964356 \n",
" - 静态变量s_a的地址为4964360 \n",
" - 静态变量s_b的地址为4964364 \n",
" - 字符串常量的地址为4955128 \n",
" - 全局常量c_g_a的地址为4954928 \n",
" - 全局常量c_g_a的地址为4954932 \n",
" - 局域常量c_l_a的地址为14023076 \n",
" - 局域常量c_l_b的地址为14023076 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.3 栈区"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 栈区\n",
"\n",
"1. 由编译器自动分配释放,存放函数的参数值、局部变量等。\n",
"2. 不要返回局部变量的地址,栈区开辟的数据由编译器自动释放。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"//栈区数据注意事项:不要返回局部变量的地址\n",
"//栈区的数据由编译器管理开辟和释放\n",
"\n",
"int* func(int b) //返回的是一个地址 int*;形参的数据也会放在栈区\n",
"{\n",
" int a = 10; //局部变量存放的数据10存放在栈区栈区的数据在函数执行完后自动释放\n",
" return &a; //返回局部变量的地址即数据10的的地址\n",
"}\n",
"\n",
"int main()\n",
"{\n",
" //接收func函数的返回值\n",
" int* p = func(1); //用指针接收栈区上的数据10的地址由于栈区上数据10已经被释放所以对地址解引用会获得乱码的值。\n",
"\n",
" cout << *p << endl; //第一次可以 打印正确的数字,是因为编译器做了保留\n",
" cout << *p << endl; //第二次这个数据就不在保留了。\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 10 \n",
" - 1905325 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.4 堆区"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 堆区:\n",
"\n",
"1. 由程序员分配释放,若程序员不释放,程序结束时由操作系统回收。\n",
"2. 在C++中主要利用new在堆区开辟内存。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int* func() //返回的是一个地址 int*;形参的数据也会放在栈区\n",
"{\n",
" //利用new关键字可以将数据开辟到堆区\n",
" //指针本质也是变量,这里的指针是局部变量,局部变量的数据放在栈上,即指针保存的数据是放在堆区\n",
" int * p = new int(10); //new关键字会返回一个地址因此用栈上的指针来接收堆上数据的地址。\n",
" return p;\n",
"}\n",
"int main()\n",
"{\n",
" //在堆区开辟数据\n",
" int* p = func(); //堆区的地址返回给 *p 了,栈区数据是否,堆区数据没释放\n",
"\n",
" cout << *p << endl;\n",
" cout << *p << endl;\n",
" cout << *p << endl;\n",
" cout << *p << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 10 \n",
" - 10 \n",
" - 10 \n",
" - 10 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 3. new操作符"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① C++中利用new操作符在堆区开辟数据。\n",
"\n",
"② 堆区开辟的数据,由程序员手动开辟,手动释放,释放利用操作符 delete。\n",
"\n",
"③ 语法new 数据类型\n",
"\n",
"④ 利用new创建的数据会返回该数据对应的类型的指针。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"//1、new的基本语法\n",
"\n",
"int* func() //返回的是一个地址 int*;形参的数据也会放在栈区\n",
"{\n",
" //在堆区创建整型数据\n",
" //new返回是该数据类型的指针\n",
" int* p = new int(10);\n",
" return p;\n",
"}\n",
"\n",
"void test01()\n",
"{\n",
" int* p = func();\n",
" cout << *p << endl;\n",
" cout << *p << endl;\n",
" cout << *p << endl;\n",
" //堆区的数据,由程序员管理开辟,程序员管理释放\n",
" //如果想释放堆区数据,利用关键字 delete\n",
" delete p;\n",
"\n",
" // cout << *p << endl; //报错,内存已经被释放,再次访问就是非法操作,会报错\n",
"}\n",
"\n",
"//2、在堆区利用new开辟数据\n",
"void test02()\n",
"{\n",
" //创建10整型数据的数组在堆区\n",
" int* arr = new int[10];//10代表数组有10个元素\n",
"\n",
" for (int i = 0; i < 10; i++)\n",
" {\n",
" arr[i] = i + 100; //给10个元素赋值 100~109\n",
" }\n",
"\n",
" for (int i = 0; i < 10; i++)\n",
" {\n",
" cout << arr[i] << endl; \n",
" }\n",
" //释放堆区数据\n",
" //释放数组的时候,要加[]才可以\n",
" delete[] arr;\n",
"}\n",
"\n",
"int main()\n",
"{\n",
" test01();\n",
" test02();\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 10 \n",
" - 10 \n",
" - 10 \n",
" - 100 \n",
" - 101 \n",
" - 102 \n",
" - 103 \n",
" - 104 \n",
" - 105 \n",
" - 106 \n",
" - 107 \n",
" - 108 \n",
" - 109 \n",
" - 请按任意键继续. . ."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,279 @@
# C++的内存模型
# 1. 内存分区
① C++在程序执行时将内存大方向划分为4个区域。
1. 代码区:存放函数体的二进制代码,由操作系统进行管理的。
2. 全局区:存放全局变量和静态变量以及常量。
3. 栈区:由编译器自动分配释放,存放函数的参数值、局部变量等。
4. 堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收。
② 内存四区的意义:不同区域存放的数据,赋予不同的生命周期,给我们更大的灵活编程。
① 在程序编译后生成了exe可执行程序未执行该程序前分为两个区域代码区、全局区。
② 所有的写的代码(注释、变量、语句等)都会放到代码区中。
③ 栈区中的数据由编译器决定数据的生成和死亡。
④ 堆区中的数据由程序员决定数据的生存和死亡。
# 2. 内存四区
## 2.1 代码区
① 代码区:
1. 存放CPU执行的机器指令。
2. 代码区是共享的,共享的目的是对于频繁被执行的程序,只需要内存中有一份代码即可。
3. 代码区是只读的,使其只读的原因是防止程序员意外地修改了它的指令。
## 2.2 全局区
① 全局区:
1. 全局变量和静态变量存放在此,局部常量不放在全局区。
2. 全局区还包含了常量区,字符串常量和其他常量也存放在此。
3. 该区域的数据在程序结束后由操作系统释放。
```python
#include <iostream>
using namespace std;
//全局变量
int g_a = 10;
int g_b = 20;
//const修饰的全局常量
const int c_g_a = 50;
const int c_g_b = 60;
int main()
{
//全局区
//全局变量、静态变量、常量
//创建普通局部变量
int a = 30;
int b = 40;
cout << "局部变量a的地址为" << (int)&a << endl;
cout << "局部变量b的地址为" << (int)&b << endl;
cout << "全局变量g_a的地址为" << (int)&g_a << endl;
cout << "全局变量g_b的地址为" << (int)&g_b << endl;
//静态变量 在普通变量前面加static,属于静态变量
static int s_a = 10;
static int s_b = 10;
cout << "静态变量s_a的地址为" << (int)&s_a << endl;
cout << "静态变量s_b的地址为" << (int)&s_b << endl;
//常量
//字符串常量
cout << "字符串常量的地址为:" << (int)&"hello world" << endl;
//const修饰的变量
//const修饰的局部变量,const修饰的局部变量
cout << "全局常量c_g_a的地址为" << (int)&c_g_a << endl;
cout << "全局常量c_g_a的地址为" << (int)&c_g_b << endl;
const int c_l_a = 10; // c-const g-global l-local;
const int c_l_b = 10;
cout << "局域常量c_l_a的地址为" << (int)&c_l_a << endl;
cout << "局域常量c_l_b的地址为" << (int)&c_l_a << endl;
system("pause");
return 0;
}
```
运行结果:
- 局部变量a的地址为14023100
- 局部变量b的地址为14023088
- 全局变量g_a的地址为4964352
- 全局变量g_b的地址为4964356
- 静态变量s_a的地址为4964360
- 静态变量s_b的地址为4964364
- 字符串常量的地址为4955128
- 全局常量c_g_a的地址为4954928
- 全局常量c_g_a的地址为4954932
- 局域常量c_l_a的地址为14023076
- 局域常量c_l_b的地址为14023076
- 请按任意键继续. . .
## 2.3 栈区
① 栈区
1. 由编译器自动分配释放,存放函数的参数值、局部变量等。
2. 不要返回局部变量的地址,栈区开辟的数据由编译器自动释放。
```python
#include <iostream>
using namespace std;
//栈区数据注意事项:不要返回局部变量的地址
//栈区的数据由编译器管理开辟和释放
int* func(int b) //返回的是一个地址 int*;形参的数据也会放在栈区
{
int a = 10; //局部变量存放的数据10存放在栈区栈区的数据在函数执行完后自动释放
return &a; //返回局部变量的地址即数据10的的地址
}
int main()
{
//接收func函数的返回值
int* p = func(1); //用指针接收栈区上的数据10的地址由于栈区上数据10已经被释放所以对地址解引用会获得乱码的值。
cout << *p << endl; //第一次可以 打印正确的数字是因为编译器做了保留
cout << *p << endl; //第二次这个数据就不在保留了
system("pause");
return 0;
}
```
运行结果:
- 10
- 1905325
- 请按任意键继续. . .
## 2.4 堆区
① 堆区:
1. 由程序员分配释放,若程序员不释放,程序结束时由操作系统回收。
2. 在C++中主要利用new在堆区开辟内存。
```python
#include <iostream>
using namespace std;
int* func() //返回的是一个地址 int*;形参的数据也会放在栈区
{
//利用new关键字可以将数据开辟到堆区
//指针本质也是变量,这里的指针是局部变量,局部变量的数据放在栈上,即指针保存的数据是放在堆区
int * p = new int(10); //new关键字会返回一个地址因此用栈上的指针来接收堆上数据的地址。
return p;
}
int main()
{
//在堆区开辟数据
int* p = func(); //堆区的地址返回给 *p 了,栈区数据是否,堆区数据没释放
cout << *p << endl;
cout << *p << endl;
cout << *p << endl;
cout << *p << endl;
system("pause");
return 0;
}
```
运行结果:
- 10
- 10
- 10
- 10
- 请按任意键继续. . .
# 3. new操作符
① C++中利用new操作符在堆区开辟数据。
② 堆区开辟的数据,由程序员手动开辟,手动释放,释放利用操作符 delete。
③ 语法new 数据类型
④ 利用new创建的数据会返回该数据对应的类型的指针。
```python
#include <iostream>
using namespace std;
//1、new的基本语法
int* func() //返回的是一个地址 int*;形参的数据也会放在栈区
{
//在堆区创建整型数据
//new返回是该数据类型的指针
int* p = new int(10);
return p;
}
void test01()
{
int* p = func();
cout << *p << endl;
cout << *p << endl;
cout << *p << endl;
//堆区的数据,由程序员管理开辟,程序员管理释放
//如果想释放堆区数据,利用关键字 delete
delete p;
// cout << *p << endl; //报错内存已经被释放再次访问就是非法操作会报错
}
//2、在堆区利用new开辟数据
void test02()
{
//创建10整型数据的数组在堆区
int* arr = new int[10];//10代表数组有10个元素
for (int i = 0; i < 10; i++)
{
arr[i] = i + 100; //给10个元素赋值 100~109
}
for (int i = 0; i < 10; i++)
{
cout << arr[i] << endl;
}
//释放堆区数据
//释放数组的时候,要加[]才可以
delete[] arr;
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
```
运行结果:
- 10
- 10
- 10
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 请按任意键继续. . .

View File

@ -0,0 +1,466 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的引用"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 引用"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.1 引用基本语法"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 作用:给变量起别名。\n",
"\n",
"② 语法:数据类型 &别名 = 原名"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int main()\n",
"{\n",
" //引用基本语法\n",
" //数据类型 &别名 = 原名\n",
"\n",
" int a = 10;\n",
" //创建引用\n",
" int& b = a;\n",
"\n",
" b = 100;\n",
"\n",
" cout << \"a= \" << a << endl;\n",
" cout << \"b= \" << a << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - a= 100 \n",
" - b= 100 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.2 引用注意事项"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 引用必须初始化。\n",
"\n",
"② 引用在初始化后,不可以改变。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"int main()\n",
"{\n",
" //1、引用必须初始化\n",
" int a = 10;\n",
" int &b = a; // int &b; 是错误的,必须要初始化\n",
"\n",
" //2、引用在初始化后不可以改变\n",
" int c = 20;\n",
" b = c; // 赋值操作,而不是更改引用。把 c = 20 的数据20给了 b 指向的内存的数据,而 a、b 的指向的内存是一样的。\n",
" // 这里并不是 b 指向 c 的内存。\n",
"\n",
" cout << \"a = \" << a << endl; //a内存中数据变了\n",
" cout << \"b = \" << b << endl;\n",
" cout << \"c = \" << c << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - a = 20 \n",
" - b = 20 \n",
" - c = 20 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.3 引用做函数参数"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 函数传参时,可以利用引用的技术让形参修饰实参。\n",
"\n",
"② 可以简化指针修改实参。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"//1、值传递\n",
"void mySwap01(int a,int b)\n",
"{\n",
" int temp = a;\n",
" a = b;\n",
" b = temp;\n",
"}\n",
"\n",
"//2、地址传递\n",
"void mySwap02(int * a, int * b)\n",
"{\n",
" int temp = *a;\n",
" *a = *b;\n",
" *b = temp;\n",
"}\n",
"\n",
"//2、引用传递\n",
"//这里面的&a的实参为a(恰巧为a恰巧一样)的别名,对&a中的a操作修改就是对实参a修改\n",
"void mySwap03(int &a, int &b) \n",
"{\n",
" int temp = a;\n",
" a = b;\n",
" b = temp;\n",
"}\n",
"\n",
"int main()\n",
"{\n",
" int a = 10;\n",
" int b = 20;\n",
"\n",
" mySwap01(a, b); //值传递,形参不会修饰实参\n",
" \n",
" cout << \"a = \" << a << endl;\n",
" cout << \"b = \" << b << endl;\n",
"\n",
" mySwap02(&a, &b); //地址传递,形参会修饰实参\n",
"\n",
" cout << \"a = \" << a << endl;\n",
" cout << \"b = \" << b << endl;\n",
"\n",
" mySwap03(a, b); //引用传递,形参会修饰实参\n",
"\n",
" cout << \"a = \" << a << endl;\n",
" cout << \"b = \" << b << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - a = 10 \n",
" - b = 20 \n",
" - a = 20 \n",
" - b = 10 \n",
" - a = 10 \n",
" - b = 20 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.4 引用做函数返回值"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 引用是可以作为函数的返回值存在的。\n",
"\n",
"② 不要返回局部变量引用。\n",
"\n",
"③ 函数调用可以作为左值。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"//引用做函数的返回值\n",
"//1、不要返回局部变量的引用\n",
"int& test01()\n",
"{\n",
" int a = 10; //局部变量存放在四区中的栈区\n",
" return a;\n",
"}\n",
"\n",
"//2、函数的调用可以作为左值\n",
"int& test02()\n",
"{\n",
" static int a = 10; //加上关键字static变成静态变量存放在全局区全局区上的数据在程序结束后释放掉\n",
" return a; //函数的返回值是a的一个引用\n",
"}\n",
"\n",
"int main()\n",
"{\n",
" /*\n",
" int& ref = test01();\n",
" cout << \"ref = \" << ref << endl; //第一次结果正确,是因为编译器做了保留\n",
" cout << \"ref = \" << ref << endl; //第一次结果正确是因为栈区a的内存已经释放\n",
" */\n",
"\n",
" \n",
" int& ref = test02(); //由于返回的是a的引用所以要用引用来接收这里用ref来接收ref为原名a的别名\n",
" cout << \"ref = \" << ref << endl; \n",
" cout << \"ref = \" << ref << endl; \n",
" cout << \"ref = \" << ref << endl; \n",
"\n",
" test02() = 1000; //对a的引用进行操作相当于原名a赋值赋值为1000\n",
" cout << \"ref = \" << ref << endl; //通过原名a的别名ref访问1000\n",
" cout << \"ref = \" << ref << endl;\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - ref = 10 \n",
" - ref = 10 \n",
" - ref = 10 \n",
" - ref = 1000 \n",
" - ref = 1000 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.5 引用本质"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 引用的本质在C++内部实现是一个指针常量。\n",
"\n",
"② C++推荐引用计数,因为语法方便,引用本质是指针常量,但是所有的指针操作编译器都帮我们做了。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"//发现是引用,转换为 int* const ref = &a;\n",
"void func(int& ref)\n",
"{\n",
" ref = 100; //ref是引用转换为 * ref = 100;\n",
"}\n",
"\n",
"int main()\n",
"{\n",
" int a = 10;\n",
"\n",
" //自动转换为 int * const ref = &a; 指针常量是指针不可改,引用不可更改别名。\n",
" //虽然指针常量指向的地址不可以更改,但是地址中的值可以更改。\n",
" int& ref = a;\n",
"\n",
" ref = 20; //内部发现ref是引用自动帮我们转换为 *ref = 20; 解引用找到相应的数据改为20\n",
"\n",
" cout << \"a\" << a << endl;\n",
" cout << \"ref\" << ref << endl;\n",
"\n",
" func(a);\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - a20 \n",
" - ref20 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.6 常量引用"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 作用:常量引用主要用来修饰形参,防止误操作。\n",
"\n",
"② 在函数形参列表中可以加const修饰形参防止形参改变实参。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"void showValue(const int& val)\n",
"{\n",
" // val = 1000; 报错,不能修改了\n",
" cout << \"val = \" << val << endl;\n",
"}\n",
"\n",
"int main()\n",
"{\n",
" //常量引用\n",
" //使用场景:用来修饰形参,防止误操作\n",
"\n",
" /*\n",
" int a = 10;\n",
" int& ref = 10; //报错,引用必须引一块合法的内存空间\n",
" */\n",
"\n",
" //加上const之后编译器代码修改为 int temp = 10; const in & ref = temp \n",
" const int& ref = 10;\n",
" //ref = 20; //加入const之后变为只读不可以修改\n",
"\n",
" int a = 100;\n",
" showValue(a);\n",
" cout << \"a = \" << a << endl;\n",
"\n",
" system(\"pause\");\n",
" \n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - val = 100 \n",
" - a = 100 \n",
" - 请按任意键继续. . ."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,303 @@
# C++的引用
# 1. 引用
## 1.1 引用基本语法
① 作用:给变量起别名。
② 语法:数据类型 &别名 = 原名
```python
#include <iostream>
using namespace std;
int main()
{
//引用基本语法
//数据类型 &别名 = 原名
int a = 10;
//创建引用
int& b = a;
b = 100;
cout << "a= " << a << endl;
cout << "b= " << a << endl;
system("pause");
return 0;
}
```
运行结果:
- a= 100
- b= 100
- 请按任意键继续. . .
## 1.2 引用注意事项
① 引用必须初始化。
② 引用在初始化后,不可以改变。
```python
#include <iostream>
using namespace std;
int main()
{
//1、引用必须初始化
int a = 10;
int &b = a; // int &b; 是错误的,必须要初始化
//2、引用在初始化后不可以改变
int c = 20;
b = c; // 赋值操作,而不是更改引用。把 c = 20 的数据20给了 b 指向的内存的数据,而 a、b 的指向的内存是一样的。
// 这里并不是 b 指向 c 的内存。
cout << "a = " << a << endl; //a内存中数据变了
cout << "b = " << b << endl;
cout << "c = " << c << endl;
system("pause");
return 0;
}
```
运行结果:
- a = 20
- b = 20
- c = 20
- 请按任意键继续. . .
## 1.3 引用做函数参数
① 函数传参时,可以利用引用的技术让形参修饰实参。
② 可以简化指针修改实参。
```python
#include <iostream>
using namespace std;
//1、值传递
void mySwap01(int a,int b)
{
int temp = a;
a = b;
b = temp;
}
//2、地址传递
void mySwap02(int * a, int * b)
{
int temp = *a;
*a = *b;
*b = temp;
}
//2、引用传递
//这里面的&a的实参为a(恰巧为a恰巧一样)的别名,对&a中的a操作修改就是对实参a修改
void mySwap03(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
int main()
{
int a = 10;
int b = 20;
mySwap01(a, b); //值传递,形参不会修饰实参
cout << "a = " << a << endl;
cout << "b = " << b << endl;
mySwap02(&a, &b); //地址传递,形参会修饰实参
cout << "a = " << a << endl;
cout << "b = " << b << endl;
mySwap03(a, b); //引用传递,形参会修饰实参
cout << "a = " << a << endl;
cout << "b = " << b << endl;
system("pause");
return 0;
}
```
运行结果:
- a = 10
- b = 20
- a = 20
- b = 10
- a = 10
- b = 20
- 请按任意键继续. . .
## 1.4 引用做函数返回值
① 引用是可以作为函数的返回值存在的。
② 不要返回局部变量引用。
③ 函数调用可以作为左值。
```python
#include <iostream>
using namespace std;
//引用做函数的返回值
//1、不要返回局部变量的引用
int& test01()
{
int a = 10; //局部变量存放在四区中的栈区
return a;
}
//2、函数的调用可以作为左值
int& test02()
{
static int a = 10; //加上关键字static变成静态变量存放在全局区全局区上的数据在程序结束后释放掉
return a; //函数的返回值是a的一个引用
}
int main()
{
/*
int& ref = test01();
cout << "ref = " << ref << endl; //第一次结果正确是因为编译器做了保留
cout << "ref = " << ref << endl; //第一次结果正确是因为栈区a的内存已经释放
*/
int& ref = test02(); //由于返回的是a的引用所以要用引用来接收这里用ref来接收ref为原名a的别名
cout << "ref = " << ref << endl;
cout << "ref = " << ref << endl;
cout << "ref = " << ref << endl;
test02() = 1000; //对a的引用进行操作相当于原名a赋值赋值为1000
cout << "ref = " << ref << endl; //通过原名a的别名ref访问1000
cout << "ref = " << ref << endl;
system("pause");
return 0;
}
```
运行结果:
- ref = 10
- ref = 10
- ref = 10
- ref = 1000
- ref = 1000
- 请按任意键继续. . .
## 1.5 引用本质
① 引用的本质在C++内部实现是一个指针常量。
② C++推荐引用计数,因为语法方便,引用本质是指针常量,但是所有的指针操作编译器都帮我们做了。
```python
#include <iostream>
using namespace std;
//发现是引用,转换为 int* const ref = &a;
void func(int& ref)
{
ref = 100; //ref是引用转换为 * ref = 100;
}
int main()
{
int a = 10;
//自动转换为 int * const ref = &a; 指针常量是指针不可改,引用不可更改别名。
//虽然指针常量指向的地址不可以更改,但是地址中的值可以更改。
int& ref = a;
ref = 20; //内部发现ref是引用自动帮我们转换为 *ref = 20; 解引用找到相应的数据改为20
cout << "a" << a << endl;
cout << "ref" << ref << endl;
func(a);
system("pause");
return 0;
}
```
运行结果:
- a20
- ref20
- 请按任意键继续. . .
## 1.6 常量引用
① 作用:常量引用主要用来修饰形参,防止误操作。
② 在函数形参列表中可以加const修饰形参防止形参改变实参。
```python
#include <iostream>
using namespace std;
void showValue(const int& val)
{
// val = 1000; 报错,不能修改了
cout << "val = " << val << endl;
}
int main()
{
//常量引用
//使用场景:用来修饰形参,防止误操作
/*
int a = 10;
int& ref = 10; //报错,引用必须引一块合法的内存空间
*/
//加上const之后编译器代码修改为 int temp = 10; const in & ref = temp
const int& ref = 10;
//ref = 20; //加入const之后变为只读不可以修改
int a = 100;
showValue(a);
cout << "a = " << a << endl;
system("pause");
return 0;
}
```
运行结果:
- val = 100
- a = 100
- 请按任意键继续. . .

View File

@ -0,0 +1,67 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的面向对象"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 面向对象三大特性"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① C++面向对象的三大特性为:封装、继承、多态。\n",
"\n",
"② C++认为万事万物皆为对象,对象上有其属性和行为。\n",
"\n",
"③ 例如:\n",
"\n",
"1. 人可以作为对象,属性有姓名、年龄、身高、体重......行为有走、跑、跳、吃饭、唱歌......\n",
"2. 车也可以作为对象,属性有轮胎、方向盘、车灯......行为有载人、放音乐、放空调......\n",
"3. 具有相同新值的对象,可以抽象为类,人属于人类,车属于车类。"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,13 @@
# C++的面向对象
# 1. 面向对象三大特性
① C++面向对象的三大特性为:封装、继承、多态。
② C++认为万事万物皆为对象,对象上有其属性和行为。
③ 例如:
1. 人可以作为对象,属性有姓名、年龄、身高、体重......行为有走、跑、跳、吃饭、唱歌......
2. 车也可以作为对象,属性有轮胎、方向盘、车灯......行为有载人、放音乐、放空调......
3. 具有相同新值的对象,可以抽象为类,人属于人类,车属于车类。

View File

@ -0,0 +1,716 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的封装"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 封装"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.1 封装属性和行为"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 封装是C++面向对象三大特性之一。\n",
"\n",
"② 封装的意义一:\n",
"\n",
"1. 将属性和行为作为一个整体,表现生活中的事物。\n",
"2. 将属性和行为加以权限控制。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"const double PI = 3.14;\n",
"\n",
"//设计一个圆类,求圆的周长\n",
"//圆求周长的公式: 2 * PI * 半径\n",
"\n",
"//class 代表设计一个类,类后面紧跟着的就是类名称\n",
"class Circle\n",
"{\n",
" //访问权限\n",
" //公共权限\n",
" public: //是冒号,不是分号\n",
"\n",
" //属性\n",
" //半径\n",
" int m_r;\n",
"\n",
" //行为\n",
" //获取圆的周长\n",
" double calculateZC()\n",
" {\n",
" return 2 * PI * m_r;\n",
" }\n",
"};\n",
"\n",
"int main()\n",
"{\n",
" //通过圆类 创建具体的圆(对象)\n",
" //实例化 (通过一个类 创建一个对象的过程)\n",
" Circle c1;\n",
" //给圆对象 的属性进行赋值\n",
" c1.m_r = 10;\n",
"\n",
" // 2 * PI * 10 = 62.8\n",
" cout << \"圆的周长为:\" << c1.calculateZC() << endl;\n",
"\n",
" system(\"pause\");\n",
" \n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 圆的周长为62.8"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.2 封装权限"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 类在设计时,可以把属性和行为放在不同的权限下,加以控制。\n",
"\n",
"② 封装的意义二:\n",
"\n",
"1. public 公共权限\n",
"2. protected 保护权限\n",
"3. private 私有权限"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"//访问权限\n",
"//三种\n",
"//公共权限 public 类内可以访问成员 类外可以访问成员\n",
"//保护权限 protected 类内可以访问成员 类外不可以访问成员 子类可以访问父类中的保护内容\n",
"//私有权限 private 类内可以访问权限 类外不可以访问成员 子类不可以访问父类中的私有内容\n",
"\n",
"class Person\n",
"{\n",
"//公共权限\n",
"public: \n",
" string m_Name; //姓名\n",
"\n",
"protected:\n",
" string m_Car; //汽车\n",
"\n",
"private:\n",
" int m_Password; //银行卡密码\n",
"\n",
"public:\n",
" void func()\n",
" {\n",
" m_Name = \"李四\";\n",
" m_Car = \"奔驰\"; //保护权限内容,在类外访问不到\n",
" m_Password = 123;\n",
" }\n",
"};\n",
"\n",
"int main()\n",
"{\n",
" //实例化具体对象\n",
" Person p1;\n",
" p1.m_Name = \"李四\";\n",
" p1.m_Car = \"奔驰\"; //保护权限内容,在类外访问不到\n",
" p1.m_Password = 123; //私有权限内容,在类外访问不到\n",
"\n",
" p1.func(); //公共权限内容,在类可以访问\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.3 struct 和 class 区别"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 在C++中struct和class唯一的区别就在于默认的访问权限不同。\n",
"\n",
"② 区别:\n",
"\n",
"1. struct 默认权限为公共。\n",
"2. class 默认权限为私有。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"//访问权限\n",
"//三种\n",
"//公共权限 public 类内可以访问成员 类外可以访问成员\n",
"//保护权限 protected 类内可以访问成员 类外不可以访问成员 子类可以访问父类中的保护内容\n",
"//私有权限 private 类内可以访问权限 类外不可以访问成员 子类不可以访问父类中的私有内容\n",
"\n",
"class C1\n",
"{\n",
" int m_A; // 默认权限是私有\n",
"};\n",
"\n",
"struct C2\n",
"{\n",
" int m_A; //默认权限 是公共\n",
"};\n",
"\n",
"int main()\n",
"{\n",
" //struct 和 class 区别\n",
" //struct 默认权限是 公共 public\n",
" //class 默认权限是 私有 private\n",
" C1 c1;\n",
" c1.m_A = 100; //私有权限,不能访问\n",
"\n",
" C2 c2;\n",
" c2.m_A = 100; //公共权限,可以访问\n",
"\n",
" system(\"pause\");\n",
" \n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.4 成员属性设置为私有"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 优点1将所有成员属性设置为私有可以自己控制读写权限。\n",
"\n",
"② 优点2可以通过写权限检测数据的有效性。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"#include <string>\n",
"\n",
"//成员属性设置为私有\n",
"//1、可以自己控制读写权限\n",
"//2、对于写可以检测数据的有效性\n",
"\n",
"class Person\n",
"{\n",
"public:\n",
" //设置姓名\n",
" void setName(string name)\n",
" {\n",
" m_Name = name;\n",
" }\n",
" //获取姓名\n",
" string getName()\n",
" {\n",
" return m_Name;\n",
" }\n",
"\n",
" //获取年龄\n",
" int getAge()\n",
" {\n",
" m_Age = 0; //初始化为0岁\n",
" return m_Age;\n",
" }\n",
"\n",
" void setLover(string lover)\n",
" {\n",
" m_Lover = lover;\n",
" }\n",
"\n",
"private:\n",
" //姓名 可读可写\n",
" string m_Name;\n",
" //年龄 只读\n",
" int m_Age;\n",
" //情人 只写\n",
" string m_Lover;\n",
"};\n",
"\n",
"int main()\n",
"{\n",
" Person p;\n",
" p.setName(\"张三\");\n",
"\n",
" cout << \"姓名为:\" << p.getName() << endl;\n",
"\n",
" cout << \"年龄为:\" << p.getName() << endl;\n",
"\n",
" //p.m_Age = 18; //私有权限,不可以改\n",
" p.getAge();\n",
" cout << \"姓名为:\" << p.getAge() << endl;\n",
"\n",
" p.setLover(\"小李\");\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 姓名为:张三 \n",
" - 年龄为0 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"#include <string>\n",
"\n",
"//成员属性设置为私有\n",
"//1、可以自己控制读写权限\n",
"//2、对于写可以检测数据的有效性\n",
"\n",
"class Person\n",
"{\n",
"public:\n",
" //设置姓名\n",
" void setName(string name)\n",
" {\n",
" m_Name = name;\n",
" }\n",
" //获取姓名\n",
" string getName()\n",
" {\n",
" return m_Name;\n",
" }\n",
"\n",
" //获取年龄 可读可写 \n",
" int getAge()\n",
" {\n",
" return m_Age;\n",
" }\n",
"\n",
" //设置年龄 如果想修改年龄的范围必须是0~150之间\n",
" void setAge(int age)\n",
" {\n",
" if (age < 0 || age>150)\n",
" {\n",
" m_Age = 0; //强制改为0\n",
" cout << \"你这个老妖精!\" << endl;\n",
" return; //强制退出\n",
" }\n",
" m_Age = age;\n",
" }\n",
"\n",
" void setLover(string lover)\n",
" {\n",
" m_Lover = lover;\n",
" }\n",
"\n",
"private:\n",
" //姓名 可读可写\n",
" string m_Name;\n",
" //年龄 只读\n",
" int m_Age;\n",
" //情人 只写\n",
" string m_Lover;\n",
"};\n",
"\n",
"int main()\n",
"{\n",
" Person p;\n",
" p.setName(\"张三\");\n",
"\n",
" cout << \"姓名为:\" << p.getName() << endl;\n",
"\n",
"\n",
" //p.m_Age = 18; //私有权限,不可以类外改\n",
" p.setAge(1000); \n",
" cout << \"年龄为:\" << p.getAge() << endl;\n",
"\n",
" //设置情人为苍井女士\n",
" p.setLover(\"小李\"); //有这个函数可以设置\n",
" //cout << \"情人为:\" << p.getLover() << endl; //没有这个函数,不能获得\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 姓名为:张三 \n",
" - 你这个老妖精! \n",
" - 年龄为0 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.5 设计学生类"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"案例描述:设计一个学生类,属性有姓名和学号,可以给姓名和学号赋值,可以显示学生的姓名和学号。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"#include<string>\n",
"\n",
"//设计学生类\n",
"class Student\n",
"{\n",
"public: //公共权限\n",
"\n",
" //类中的属性和行为 我们统一称为成员\n",
" // 属性 成员属性 成员变量\n",
" // 行为 成员函数 成员方法\n",
" \n",
" //属性\n",
" string m_Name; //姓名\n",
" int m_Id; //学号\n",
"\n",
" //行为\n",
" //显示姓名和学号\n",
" void showStudent()\n",
" {\n",
" cout << \"姓名:\" << m_Name << \" 学号:\" << m_Id << endl;\n",
" }\n",
"\n",
" //给姓名赋值的行为\n",
" void setName(string name)\n",
" {\n",
" m_Name = name;\n",
" }\n",
"};\n",
"\n",
"int main()\n",
"{\n",
" //创建一个具体学生 实例化对象\n",
" Student s1;\n",
" //给s1对象 进行属性赋值操作\n",
" s1.m_Name = \"张三\";\n",
" s1.m_Id = 1;\n",
"\n",
" s1.showStudent();\n",
"\n",
" Student s2;\n",
" s2.m_Name = \"李四\";\n",
" s2.m_Id = 2;\n",
" s2.showStudent();\n",
"\n",
" Student s3;\n",
" s3.setName(\"王五\");\n",
" s3.m_Id = 3;\n",
" s3.showStudent();\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 姓名:张三 学号1 \n",
" - 姓名:李四 学号2 \n",
" - 姓名:王五 学号3 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1.6 设计立方体类"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"案例描述:设计立方体类(Cube),求出立方体的面积和体积,分别用全局函数和成员函数判断两个立方体是否相等。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"//立方体类设计\n",
"//1、创建立方体类\n",
"//2、设计属性\n",
"//3、获取立方体面积和体积\n",
"//4、分别利用全局函数和成员函数 判断两个立方体是否相等\n",
"\n",
"class Cube\n",
"{\n",
"public:\n",
" //设置长\n",
" void setL(int l)\n",
" {\n",
" m_L = l;\n",
" }\n",
"\n",
" //获取长\n",
" int getL()\n",
" {\n",
" return m_L;\n",
" }\n",
"\n",
" //设置宽\n",
" void setW(int w)\n",
" {\n",
" m_W = w;\n",
" }\n",
"\n",
" //获取宽\n",
" int getW()\n",
" {\n",
" return m_W;\n",
" }\n",
"\n",
" //设置高\n",
" void setH(int h)\n",
" {\n",
" m_H = h;\n",
" }\n",
"\n",
" //获取高\n",
" int getH()\n",
" {\n",
" return m_H;\n",
" }\n",
"\n",
" //获取立方体面积\n",
" int calculateS()\n",
" {\n",
" return 2 * m_L * m_W + 2 * m_W * m_H + 2 * m_L * m_H;\n",
" }\n",
"\n",
" //获取立方体体积\n",
" int calculateV()\n",
" {\n",
" return m_L * m_W * m_H;\n",
" }\n",
"\n",
" //利用成员函数判断两个立方体是否相等\n",
" bool isSameByClass(Cube c) //成员函数只需要传入一个类为参数\n",
" {\n",
" if (m_L == c.getL() && m_W == c.getW() && m_H == c.getH()) //类内可以访问成员函数m_L、m_W、m_H\n",
" {\n",
" return true;\n",
" }\n",
" else\n",
" {\n",
" return false;\n",
" }\n",
" }\n",
"\n",
"\n",
"private:\n",
" int m_L; //长\n",
" int m_W; //宽\n",
" int m_H; //高\n",
"};\n",
"\n",
"//利用全局函数判断,两个立方体是否相等\n",
"bool isSame(Cube c1, Cube c2) //值传递会拷贝一份数据,通过引用传递用原始数据,不会拷贝数据\n",
"{\n",
" if (c1.getL() == c2.getL() && c1.getW() == c2.getW()\n",
" && c1.getH() == c2.getH())\n",
" {\n",
" return true;\n",
" }\n",
" else\n",
" {\n",
" return false;\n",
" }\n",
"}\n",
"\n",
"int main()\n",
"{\n",
" //创建立方体对象\n",
" Cube c1;\n",
" c1.setL(10);\n",
" c1.setW(10);\n",
" c1.setH(10);\n",
"\n",
" cout << \"c1的面积为\" << c1.calculateS() << endl; \n",
" cout << \"c1的体积为\" << c1.calculateV() << endl; \n",
"\n",
" Cube c2;\n",
" c2.setL(10);\n",
" c2.setW(10);\n",
" c2.setH(11);\n",
"\n",
" bool ret = isSame(c1, c2);\n",
" if (ret)\n",
" {\n",
" cout << \"利用全局函数判断c1和c2是相等的\" << endl;\n",
" }\n",
" else\n",
" {\n",
" cout << \"利用全局函数判断c1和c2是不相等的\" << endl;\n",
" }\n",
"\n",
"\n",
" //利用成员函数判断\n",
" ret = c1.isSameByClass(c2);\n",
" if (ret)\n",
" {\n",
" cout << \"利用成员函数判断c1和c2是相等的\" << endl;\n",
" }\n",
" else\n",
" {\n",
" cout << \"利用成员函数判断c1和c2是不相等的\" << endl;\n",
" }\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - c1的面积为600 \n",
" - c1的体积为1000 \n",
" - 利用全局函数判断c1和c2是不相等的 \n",
" - 利用成员函数判断c1和c2是不相等的 \n",
" - 请按任意键继续. . ."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,554 @@
# C++的封装
# 1. 封装
## 1.1 封装属性和行为
① 封装是C++面向对象三大特性之一。
② 封装的意义一:
1. 将属性和行为作为一个整体,表现生活中的事物。
2. 将属性和行为加以权限控制。
```python
#include <iostream>
using namespace std;
const double PI = 3.14;
//设计一个圆类,求圆的周长
//圆求周长的公式: 2 * PI * 半径
//class 代表设计一个类,类后面紧跟着的就是类名称
class Circle
{
//访问权限
//公共权限
public: //是冒号,不是分号
//属性
//半径
int m_r;
//行为
//获取圆的周长
double calculateZC()
{
return 2 * PI * m_r;
}
};
int main()
{
//通过圆类 创建具体的圆(对象)
//实例化 (通过一个类 创建一个对象的过程)
Circle c1;
//给圆对象 的属性进行赋值
c1.m_r = 10;
// 2 * PI * 10 = 62.8
cout << "圆的周长为:" << c1.calculateZC() << endl;
system("pause");
return 0;
}
```
运行结果:
- 圆的周长为62.8
## 1.2 封装权限
① 类在设计时,可以把属性和行为放在不同的权限下,加以控制。
② 封装的意义二:
1. public 公共权限
2. protected 保护权限
3. private 私有权限
```python
#include <iostream>
using namespace std;
//访问权限
//三种
//公共权限 public 类内可以访问成员 类外可以访问成员
//保护权限 protected 类内可以访问成员 类外不可以访问成员 子类可以访问父类中的保护内容
//私有权限 private 类内可以访问权限 类外不可以访问成员 子类不可以访问父类中的私有内容
class Person
{
//公共权限
public:
string m_Name; //姓名
protected:
string m_Car; //汽车
private:
int m_Password; //银行卡密码
public:
void func()
{
m_Name = "李四";
m_Car = "奔驰"; //保护权限内容,在类外访问不到
m_Password = 123;
}
};
int main()
{
//实例化具体对象
Person p1;
p1.m_Name = "李四";
p1.m_Car = "奔驰"; //保护权限内容,在类外访问不到
p1.m_Password = 123; //私有权限内容,在类外访问不到
p1.func(); //公共权限内容,在类可以访问
system("pause");
return 0;
}
```
## 1.3 struct 和 class 区别
① 在C++中struct和class唯一的区别就在于默认的访问权限不同。
② 区别:
1. struct 默认权限为公共。
2. class 默认权限为私有。
```python
#include <iostream>
using namespace std;
//访问权限
//三种
//公共权限 public 类内可以访问成员 类外可以访问成员
//保护权限 protected 类内可以访问成员 类外不可以访问成员 子类可以访问父类中的保护内容
//私有权限 private 类内可以访问权限 类外不可以访问成员 子类不可以访问父类中的私有内容
class C1
{
int m_A; // 默认权限是私有
};
struct C2
{
int m_A; //默认权限 是公共
};
int main()
{
//struct 和 class 区别
//struct 默认权限是 公共 public
//class 默认权限是 私有 private
C1 c1;
c1.m_A = 100; //私有权限,不能访问
C2 c2;
c2.m_A = 100; //公共权限,可以访问
system("pause");
return 0;
}
```
## 1.4 成员属性设置为私有
① 优点1将所有成员属性设置为私有可以自己控制读写权限。
② 优点2可以通过写权限检测数据的有效性。
```python
#include <iostream>
using namespace std;
#include <string>
//成员属性设置为私有
//1、可以自己控制读写权限
//2、对于写可以检测数据的有效性
class Person
{
public:
//设置姓名
void setName(string name)
{
m_Name = name;
}
//获取姓名
string getName()
{
return m_Name;
}
//获取年龄
int getAge()
{
m_Age = 0; //初始化为0岁
return m_Age;
}
void setLover(string lover)
{
m_Lover = lover;
}
private:
//姓名 可读可写
string m_Name;
//年龄 只读
int m_Age;
//情人 只写
string m_Lover;
};
int main()
{
Person p;
p.setName("张三");
cout << "姓名为:" << p.getName() << endl;
cout << "年龄为:" << p.getName() << endl;
//p.m_Age = 18; //私有权限,不可以改
p.getAge();
cout << "姓名为:" << p.getAge() << endl;
p.setLover("小李");
system("pause");
return 0;
}
```
运行结果:
- 姓名为:张三
- 年龄为0
- 请按任意键继续. . .
```python
#include <iostream>
using namespace std;
#include <string>
//成员属性设置为私有
//1、可以自己控制读写权限
//2、对于写可以检测数据的有效性
class Person
{
public:
//设置姓名
void setName(string name)
{
m_Name = name;
}
//获取姓名
string getName()
{
return m_Name;
}
//获取年龄 可读可写
int getAge()
{
return m_Age;
}
//设置年龄 如果想修改年龄的范围必须是0~150之间
void setAge(int age)
{
if (age < 0 || age>150)
{
m_Age = 0; //强制改为0
cout << "你这个老妖精!" << endl;
return; //强制退出
}
m_Age = age;
}
void setLover(string lover)
{
m_Lover = lover;
}
private:
//姓名 可读可写
string m_Name;
//年龄 只读
int m_Age;
//情人 只写
string m_Lover;
};
int main()
{
Person p;
p.setName("张三");
cout << "姓名为:" << p.getName() << endl;
//p.m_Age = 18; //私有权限,不可以类外改
p.setAge(1000);
cout << "年龄为:" << p.getAge() << endl;
//设置情人为苍井女士
p.setLover("小李"); //有这个函数可以设置
//cout << "情人为:" << p.getLover() << endl; //没有这个函数不能获得
system("pause");
return 0;
}
```
运行结果:
- 姓名为:张三
- 你这个老妖精!
- 年龄为0
- 请按任意键继续. . .
## 1.5 设计学生类
案例描述:设计一个学生类,属性有姓名和学号,可以给姓名和学号赋值,可以显示学生的姓名和学号。
```python
#include <iostream>
using namespace std;
#include<string>
//设计学生类
class Student
{
public: //公共权限
//类中的属性和行为 我们统一称为成员
// 属性 成员属性 成员变量
// 行为 成员函数 成员方法
//属性
string m_Name; //姓名
int m_Id; //学号
//行为
//显示姓名和学号
void showStudent()
{
cout << "姓名:" << m_Name << " 学号" << m_Id << endl;
}
//给姓名赋值的行为
void setName(string name)
{
m_Name = name;
}
};
int main()
{
//创建一个具体学生 实例化对象
Student s1;
//给s1对象 进行属性赋值操作
s1.m_Name = "张三";
s1.m_Id = 1;
s1.showStudent();
Student s2;
s2.m_Name = "李四";
s2.m_Id = 2;
s2.showStudent();
Student s3;
s3.setName("王五");
s3.m_Id = 3;
s3.showStudent();
system("pause");
return 0;
}
```
运行结果:
- 姓名:张三 学号1
- 姓名:李四 学号2
- 姓名:王五 学号3
- 请按任意键继续. . .
## 1.6 设计立方体类
案例描述:设计立方体类(Cube),求出立方体的面积和体积,分别用全局函数和成员函数判断两个立方体是否相等。
```python
#include <iostream>
using namespace std;
//立方体类设计
//1、创建立方体类
//2、设计属性
//3、获取立方体面积和体积
//4、分别利用全局函数和成员函数 判断两个立方体是否相等
class Cube
{
public:
//设置长
void setL(int l)
{
m_L = l;
}
//获取长
int getL()
{
return m_L;
}
//设置宽
void setW(int w)
{
m_W = w;
}
//获取宽
int getW()
{
return m_W;
}
//设置高
void setH(int h)
{
m_H = h;
}
//获取高
int getH()
{
return m_H;
}
//获取立方体面积
int calculateS()
{
return 2 * m_L * m_W + 2 * m_W * m_H + 2 * m_L * m_H;
}
//获取立方体体积
int calculateV()
{
return m_L * m_W * m_H;
}
//利用成员函数判断两个立方体是否相等
bool isSameByClass(Cube c) //成员函数只需要传入一个类为参数
{
if (m_L == c.getL() && m_W == c.getW() && m_H == c.getH()) //类内可以访问成员函数m_L、m_W、m_H
{
return true;
}
else
{
return false;
}
}
private:
int m_L; //长
int m_W; //宽
int m_H; //高
};
//利用全局函数判断,两个立方体是否相等
bool isSame(Cube c1, Cube c2) //值传递会拷贝一份数据,通过引用传递用原始数据,不会拷贝数据
{
if (c1.getL() == c2.getL() && c1.getW() == c2.getW()
&& c1.getH() == c2.getH())
{
return true;
}
else
{
return false;
}
}
int main()
{
//创建立方体对象
Cube c1;
c1.setL(10);
c1.setW(10);
c1.setH(10);
cout << "c1的面积为" << c1.calculateS() << endl;
cout << "c1的体积为" << c1.calculateV() << endl;
Cube c2;
c2.setL(10);
c2.setW(10);
c2.setH(11);
bool ret = isSame(c1, c2);
if (ret)
{
cout << "利用全局函数判断c1和c2是相等的" << endl;
}
else
{
cout << "利用全局函数判断c1和c2是不相等的" << endl;
}
//利用成员函数判断
ret = c1.isSameByClass(c2);
if (ret)
{
cout << "利用成员函数判断c1和c2是相等的" << endl;
}
else
{
cout << "利用成员函数判断c1和c2是不相等的" << endl;
}
system("pause");
return 0;
}
```
运行结果:
- c1的面积为600
- c1的体积为1000
- 利用全局函数判断c1和c2是不相等的
- 利用成员函数判断c1和c2是不相等的
- 请按任意键继续. . .

View File

@ -0,0 +1,426 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的调用其他类"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 类中有其他的类"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"//点和圆关系案例\n",
"\n",
"//点类\n",
"class Point\n",
"{\n",
"public:\n",
" //设置x\n",
" void setX(int x)\n",
" {\n",
" m_X = x;\n",
" }\n",
" //获取x\n",
" int getX()\n",
" {\n",
" return m_X;\n",
" }\n",
" //设置y\n",
" void setY(int y)\n",
" {\n",
" m_Y = y;\n",
" }\n",
" //获取y\n",
" int getY()\n",
" {\n",
" return m_Y;\n",
" }\n",
"\n",
"private:\n",
" int m_X;\n",
" int m_Y;\n",
"};\n",
"\n",
"//圆类\n",
"class Circle\n",
"{\n",
"public:\n",
" //设置半径\n",
" void setR(int r)\n",
" {\n",
" m_R = r;\n",
" }\n",
" //获取半径\n",
" int getR()\n",
" {\n",
" return m_R;\n",
" }\n",
" //设置圆心\n",
" void setCenter(Point center)\n",
" {\n",
" m_Center = center;\n",
" }\n",
" //获取圆心\n",
" Point getCenter()\n",
" {\n",
" return m_Center;\n",
" }\n",
"private:\n",
" int m_R; //半径\n",
" Point m_Center; //圆心 //在类中可以让另一个类 作为本类中的成员\n",
"};\n",
"\n",
"//判断点和圆关系\n",
"void isInCircle(Circle& c, Point& p)\n",
"{\n",
" //计算两点之间距离 平方\n",
" int distance =\n",
" (c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) +\n",
" (c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY()); //c.getCenter()返回的是圆心点center类\n",
" //可以调用圆心点center类中的方法\n",
"\n",
" //计算半径的平方\n",
" int rDistance = c.getR() * c.getR();\n",
"\n",
" //判断关系\n",
" if (distance == rDistance)\n",
" {\n",
" cout << \"点在圆上\" << endl;\n",
" }\n",
" else if (distance > rDistance)\n",
" {\n",
" cout << \"点在圆外\" << endl;\n",
" }\n",
" else\n",
" {\n",
" cout << \"点在圆内\" << endl;\n",
" }\n",
"}\n",
"\n",
"int main()\n",
"{\n",
" //创建圆\n",
" Circle c;\n",
" c.setR(10);\n",
" Point center;\n",
" center.setX(10); //设置点的横坐标\n",
" center.setY(0); //设置点的纵坐标\n",
" c.setCenter(center); //设置点类传入圆类\n",
"\n",
" //创建点\n",
" Point p;\n",
" p.setX(10);\n",
" p.setY(10);\n",
"\n",
" //判断关系\n",
" isInCircle(c, p);\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 点在圆上 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 2. 导入其他文件的类"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.1 point.h头文件"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"//这是point.h头文件\n",
"\n",
"#pragma once //防止头文件重复包含,防止头文件冲突\n",
"#include <iostream> //标准输入输出\n",
"using namespace std; //标准命名空间\n",
"\n",
"//只要函数声明、变量声明\n",
"//成员函数只需要声明就好了,末尾有分号。\n",
"class Point\n",
"{\n",
"public:\n",
" //设置x\n",
" void setX(int x);\n",
"\n",
" //获取x\n",
" int getX();\n",
"\n",
" //设置y\n",
" void setY(int y);\n",
"\n",
" //获取y\n",
" int getY();\n",
"\n",
"\n",
"private:\n",
" int m_X;\n",
" int m_Y;\n",
"};"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.2 point.cpp源文件"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"//这是point.cpp源文件\n",
"#include \"point.h\"\n",
"\n",
"//定义函数时,要加上作用域,\"双冒号::\"表示Point作用域下的函数\n",
"void Point::setX(int x)\n",
"{\n",
" m_X = x;\n",
"}\n",
"//获取x\n",
"int Point::getX()\n",
"{\n",
" return m_X;\n",
"}\n",
"//设置y\n",
"void Point::setY(int y)\n",
"{\n",
" m_Y = y;\n",
"}\n",
"//获取y\n",
"int Point::getY()\n",
"{\n",
" return m_Y;\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.3 circle.h头文件"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#pragma once \n",
"#include <iostream> //标准输出流\n",
"using namespace std; //标准命名空间\n",
"#include \"Point.h\" //一个类中用到另一个类,把另一个类包含的头文件包含进来\n",
"\n",
"//圆类\n",
"class Circle\n",
"{\n",
"public:\n",
" //设置半径\n",
" void setR(int r);\n",
"\n",
" //获取半径\n",
" int getR();\n",
"\n",
" //设置圆心\n",
" void setCenter(Point center);\n",
"\n",
" //获取圆心\n",
" Point getCenter();\n",
"\n",
"private:\n",
" int m_R; //半径\n",
" Point m_Center; //圆心 //在类中可以让另一个类 作为本类中的成员\n",
"};"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.4 circle.cpp头文件"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"//这是circle.cpp头文件\n",
"\n",
"#include \"circle.h\"\n",
"\n",
"//设置半径\n",
"void Circle::setR(int r)\n",
"{\n",
" m_R = r;\n",
"}\n",
"\n",
"//获取半径\n",
"int Circle::getR()\n",
"{\n",
" return m_R;\n",
"}\n",
"\n",
"//设置圆心\n",
"void Circle::setCenter(Point center)\n",
"{\n",
" m_Center = center;\n",
"}\n",
"\n",
"//获取圆心\n",
"Point Circle::getCenter()\n",
"{\n",
" return m_Center;\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2.5 main.cpp文件"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"//这个是主文件 .cpp文件\n",
"\n",
"#include <iostream>\n",
"using namespace std;\n",
"#include \"circle.h\" //想用点类,就要包含点类的头文件\n",
"#include \"point.h\" //想用圆类,就要包含点类的头文件\n",
"\n",
"\n",
"//判断点和圆关系\n",
"void isInCircle(Circle& c, Point& p)\n",
"{\n",
" //计算两点之间距离 平方\n",
" int distance =\n",
" (c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) +\n",
" (c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY()); //c.getCenter()返回的是圆心点center类\n",
" //可以调用圆心点center类中的方法\n",
"\n",
" //计算半径的平方\n",
" int rDistance = c.getR() * c.getR();\n",
"\n",
" //判断关系\n",
" if (distance == rDistance)\n",
" {\n",
" cout << \"点在圆上\" << endl;\n",
" }\n",
" else if (distance > rDistance)\n",
" {\n",
" cout << \"点在圆外\" << endl;\n",
" }\n",
" else\n",
" {\n",
" cout << \"点在圆内\" << endl;\n",
" }\n",
"}\n",
"\n",
"int main()\n",
"{\n",
" //创建圆\n",
" Circle c;\n",
" c.setR(10);\n",
" Point center;\n",
" center.setX(10); //设置点的横坐标\n",
" center.setY(0); //设置点的纵坐标\n",
" c.setCenter(center); //设置点类传入圆类\n",
"\n",
" //创建点\n",
" Point p;\n",
" p.setX(10);\n",
" p.setY(10);\n",
" \n",
" //判断关系\n",
" isInCircle(c, p);\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,318 @@
# C++的调用其他类
# 1. 类中有其他的类
```python
#include <iostream>
using namespace std;
//点和圆关系案例
//点类
class Point
{
public:
//设置x
void setX(int x)
{
m_X = x;
}
//获取x
int getX()
{
return m_X;
}
//设置y
void setY(int y)
{
m_Y = y;
}
//获取y
int getY()
{
return m_Y;
}
private:
int m_X;
int m_Y;
};
//圆类
class Circle
{
public:
//设置半径
void setR(int r)
{
m_R = r;
}
//获取半径
int getR()
{
return m_R;
}
//设置圆心
void setCenter(Point center)
{
m_Center = center;
}
//获取圆心
Point getCenter()
{
return m_Center;
}
private:
int m_R; //半径
Point m_Center; //圆心 //在类中可以让另一个类 作为本类中的成员
};
//判断点和圆关系
void isInCircle(Circle& c, Point& p)
{
//计算两点之间距离 平方
int distance =
(c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) +
(c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY()); //c.getCenter()返回的是圆心点center类
//可以调用圆心点center类中的方法
//计算半径的平方
int rDistance = c.getR() * c.getR();
//判断关系
if (distance == rDistance)
{
cout << "点在圆上" << endl;
}
else if (distance > rDistance)
{
cout << "点在圆外" << endl;
}
else
{
cout << "点在圆内" << endl;
}
}
int main()
{
//创建圆
Circle c;
c.setR(10);
Point center;
center.setX(10); //设置点的横坐标
center.setY(0); //设置点的纵坐标
c.setCenter(center); //设置点类传入圆类
//创建点
Point p;
p.setX(10);
p.setY(10);
//判断关系
isInCircle(c, p);
system("pause");
return 0;
}
```
运行结果:
- 点在圆上
- 请按任意键继续. . .
# 2. 导入其他文件的类
## 2.1 point.h头文件
```python
//这是point.h头文件
#pragma once //防止头文件重复包含,防止头文件冲突
#include <iostream> //标准输入输出
using namespace std; //标准命名空间
//只要函数声明、变量声明
//成员函数只需要声明就好了,末尾有分号。
class Point
{
public:
//设置x
void setX(int x);
//获取x
int getX();
//设置y
void setY(int y);
//获取y
int getY();
private:
int m_X;
int m_Y;
};
```
## 2.2 point.cpp源文件
```python
//这是point.cpp源文件
#include "point.h"
//定义函数时,要加上作用域,"双冒号::"表示Point作用域下的函数
void Point::setX(int x)
{
m_X = x;
}
//获取x
int Point::getX()
{
return m_X;
}
//设置y
void Point::setY(int y)
{
m_Y = y;
}
//获取y
int Point::getY()
{
return m_Y;
}
```
## 2.3 circle.h头文件
```python
#pragma once
#include <iostream> //标准输出流
using namespace std; //标准命名空间
#include "Point.h" //一个类中用到另一个类,把另一个类包含的头文件包含进来
//圆类
class Circle
{
public:
//设置半径
void setR(int r);
//获取半径
int getR();
//设置圆心
void setCenter(Point center);
//获取圆心
Point getCenter();
private:
int m_R; //半径
Point m_Center; //圆心 //在类中可以让另一个类 作为本类中的成员
};
```
## 2.4 circle.cpp头文件
```python
//这是circle.cpp头文件
#include "circle.h"
//设置半径
void Circle::setR(int r)
{
m_R = r;
}
//获取半径
int Circle::getR()
{
return m_R;
}
//设置圆心
void Circle::setCenter(Point center)
{
m_Center = center;
}
//获取圆心
Point Circle::getCenter()
{
return m_Center;
}
```
## 2.5 main.cpp文件
```python
//这个是主文件 .cpp文件
#include <iostream>
using namespace std;
#include "circle.h" //想用点类,就要包含点类的头文件
#include "point.h" //想用圆类,就要包含点类的头文件
//判断点和圆关系
void isInCircle(Circle& c, Point& p)
{
//计算两点之间距离 平方
int distance =
(c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) +
(c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY()); //c.getCenter()返回的是圆心点center类
//可以调用圆心点center类中的方法
//计算半径的平方
int rDistance = c.getR() * c.getR();
//判断关系
if (distance == rDistance)
{
cout << "点在圆上" << endl;
}
else if (distance > rDistance)
{
cout << "点在圆外" << endl;
}
else
{
cout << "点在圆内" << endl;
}
}
int main()
{
//创建圆
Circle c;
c.setR(10);
Point center;
center.setX(10); //设置点的横坐标
center.setY(0); //设置点的纵坐标
c.setCenter(center); //设置点类传入圆类
//创建点
Point p;
p.setX(10);
p.setY(10);
//判断关系
isInCircle(c, p);
system("pause");
return 0;
}
```

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 KiB

View File

@ -0,0 +1,334 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的友元"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 友元简介"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 生活中你的家有客厅(Public),有你的卧室(Private),客厅所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你能进去,但是呢,你也可以允许你的好闺蜜进去。\n",
"\n",
"② 在程序里,有些私有属性,也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术。\n",
"\n",
"③ 友元的目的就是让一个函数或者类访问另一个类中私有成员。\n",
"\n",
"④ 友元的关键字为 friend。\n",
"\n",
"⑤ 友元的三种实现:\n",
"\n",
"1. 全局函数做友元。\n",
"2. 类做友元。\n",
"3. 成员函数做友元。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"//建筑物类\n",
"class Buiding\n",
"{\n",
" //goodfriend全局函数是Buiding类好朋友可以访问Buiding中私有成员\n",
" friend void goodfriend(Buiding* buiding);\n",
"\n",
"public:\n",
" Buiding() //构造函数 赋初值\n",
" {\n",
" m_SittingRoom = \"客厅\";\n",
" m_BedRoom = \"卧室\";\n",
" }\n",
"\n",
"public:\n",
" string m_SittingRoom; //客厅\n",
"\n",
"private:\n",
" string m_BedRoom;\n",
"};\n",
"\n",
"//全局函数\n",
"void goodfriend(Buiding *buiding)\n",
"{\n",
" cout << \"好基友全局函数 正在访问:\" << buiding->m_SittingRoom << endl;\n",
" cout << \"好基友全局函数 正在访问:\" << buiding->m_BedRoom << endl;\n",
"\n",
"}\n",
"\n",
"void test01()\n",
"{\n",
" Buiding building;\n",
" goodfriend(&building);\n",
"}\n",
"\n",
"int main()\n",
"{\n",
" test01();\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 好基友全局函数 正在访问:客厅 \n",
" - 好基友全局函数 正在访问:卧室 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 2. 友元类"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"//类做友元\n",
"class Building; //声明\n",
"\n",
"class GoodGay\n",
"{\n",
"public:\n",
" GoodGay();\n",
"\n",
" void visit(); //参观函数 访问Building中的属性\n",
"\n",
" Building* building;\n",
"};\n",
"\n",
"class Building\n",
"{\n",
" //GoodGay类是本类的好朋友可以访问本类的私有成员\n",
" friend class GoodGay;\n",
"\n",
"public:\n",
" Building();\n",
"\n",
"public:\n",
" string m_SittingRoom; //客厅\n",
"private:\n",
" string m_BedRoom; //卧室\n",
"};\n",
"\n",
"//类外写成员函数,写类名的作用域\n",
"\n",
"//Building构造函数\n",
"Building::Building()\n",
"{\n",
" m_SittingRoom = \"客厅\";\n",
" m_BedRoom = \"卧室\";\n",
"}\n",
"\n",
"//GoodGay构造函数\n",
"GoodGay::GoodGay()\n",
"{\n",
" //创建建筑物对象\n",
" building = new Building; //这里会调用Building的构造函数\n",
" //new是创建什么样的数据类型就返回什么样的数据类型的指针 \n",
"}\n",
"\n",
"void GoodGay::visit()\n",
"{\n",
" cout << \"好基友类正在访问:\" << building->m_SittingRoom << endl;\n",
"\n",
" cout << \"好基友类正在访问:\" << building->m_BedRoom << endl;\n",
"\n",
"}\n",
"\n",
"void test01()\n",
"{\n",
" GoodGay gg; //创建一个GoodGay的对象会调用GoodGay构造函数会创建一个building然后调用building构造函数 \n",
" gg.visit();\n",
"}\n",
"\n",
"int main()\n",
"{\n",
" test01();\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 好基友类正在访问:客厅 \n",
" - 好基友类正在访问:卧室 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 3. 成员函数做友元"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"class Building;\n",
"class GoodGay\n",
"{\n",
"public:\n",
" GoodGay();\n",
"\n",
" void visit(); //让visit函数可以访问Building中私有成员\n",
" void visit2(); //让visit2函数不可以访问Buildinng中私有成员\n",
"\n",
" Building* building;\n",
"};\n",
"\n",
"class Building\n",
"{\n",
" //告诉编译器GoodGay类下的visit成员函数作为本类的好朋友可以访问私有成员 \n",
" friend void GoodGay::visit();\n",
"\n",
"public:\n",
" Building();\n",
"\n",
"public:\n",
" string m_SittingRoom; //客厅\n",
"\n",
"private:\n",
" string m_BedRoom; //卧室\n",
"};\n",
"\n",
"// 类外实现构造函数\n",
"Building::Building()\n",
"{\n",
" m_SittingRoom = \"客厅\";\n",
" m_BedRoom = \"卧室\";\n",
"}\n",
"\n",
"GoodGay::GoodGay()\n",
"{\n",
" building = new Building;\n",
"}\n",
"\n",
"// 类外实现成员函数\n",
"void GoodGay::visit()\n",
"{\n",
" cout << \"visit 函数正在访问\" << building->m_SittingRoom << endl;\n",
" cout << \"visit 函数正在访问\" << building->m_BedRoom << endl;\n",
"\n",
"}\n",
"\n",
"void GoodGay::visit2()\n",
"{\n",
" cout << \"visit2 函数正在访问\" << building->m_SittingRoom << endl;\n",
" //cout << \"visit 函数正在访问\" << building->m_BedRoom << endl;\n",
"\n",
"}\n",
"\n",
"void test01()\n",
"{\n",
" GoodGay gg;\n",
" gg.visit();\n",
" gg.visit2();\n",
"}\n",
"\n",
"int main()\n",
"{\n",
" test01();\n",
" \n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - visit 函数正在访问客厅 \n",
" - visit 函数正在访问卧室 \n",
" - visit2 函数正在访问客厅 \n",
" - 请按任意键继续. . ."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {
"height": "calc(100% - 180px)",
"left": "10px",
"top": "150px",
"width": "341.333px"
},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,238 @@
# C++的友元
# 1. 友元简介
① 生活中你的家有客厅(Public),有你的卧室(Private),客厅所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你能进去,但是呢,你也可以允许你的好闺蜜进去。
② 在程序里,有些私有属性,也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术。
③ 友元的目的就是让一个函数或者类访问另一个类中私有成员。
④ 友元的关键字为 friend。
⑤ 友元的三种实现:
1. 全局函数做友元。
2. 类做友元。
3. 成员函数做友元。
```python
#include <iostream>
using namespace std;
//建筑物类
class Buiding
{
//goodfriend全局函数是Buiding类好朋友可以访问Buiding中私有成员
friend void goodfriend(Buiding* buiding);
public:
Buiding() //构造函数 赋初值
{
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
public:
string m_SittingRoom; //客厅
private:
string m_BedRoom;
};
//全局函数
void goodfriend(Buiding *buiding)
{
cout << "好基友全局函数 正在访问:" << buiding->m_SittingRoom << endl;
cout << "好基友全局函数 正在访问:" << buiding->m_BedRoom << endl;
}
void test01()
{
Buiding building;
goodfriend(&building);
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 好基友全局函数 正在访问:客厅
- 好基友全局函数 正在访问:卧室
- 请按任意键继续. . .
# 2. 友元类
```python
#include <iostream>
using namespace std;
//类做友元
class Building; //声明
class GoodGay
{
public:
GoodGay();
void visit(); //参观函数 访问Building中的属性
Building* building;
};
class Building
{
//GoodGay类是本类的好朋友可以访问本类的私有成员
friend class GoodGay;
public:
Building();
public:
string m_SittingRoom; //客厅
private:
string m_BedRoom; //卧室
};
//类外写成员函数,写类名的作用域
//Building构造函数
Building::Building()
{
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
//GoodGay构造函数
GoodGay::GoodGay()
{
//创建建筑物对象
building = new Building; //这里会调用Building的构造函数
//new是创建什么样的数据类型就返回什么样的数据类型的指针
}
void GoodGay::visit()
{
cout << "好基友类正在访问:" << building->m_SittingRoom << endl;
cout << "好基友类正在访问:" << building->m_BedRoom << endl;
}
void test01()
{
GoodGay gg; //创建一个GoodGay的对象会调用GoodGay构造函数会创建一个building然后调用building构造函数
gg.visit();
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 好基友类正在访问:客厅
- 好基友类正在访问:卧室
- 请按任意键继续. . .
# 3. 成员函数做友元
```python
#include <iostream>
using namespace std;
class Building;
class GoodGay
{
public:
GoodGay();
void visit(); //让visit函数可以访问Building中私有成员
void visit2(); //让visit2函数不可以访问Buildinng中私有成员
Building* building;
};
class Building
{
//告诉编译器GoodGay类下的visit成员函数作为本类的好朋友可以访问私有成员
friend void GoodGay::visit();
public:
Building();
public:
string m_SittingRoom; //客厅
private:
string m_BedRoom; //卧室
};
// 类外实现构造函数
Building::Building()
{
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
GoodGay::GoodGay()
{
building = new Building;
}
// 类外实现成员函数
void GoodGay::visit()
{
cout << "visit 函数正在访问" << building->m_SittingRoom << endl;
cout << "visit 函数正在访问" << building->m_BedRoom << endl;
}
void GoodGay::visit2()
{
cout << "visit2 函数正在访问" << building->m_SittingRoom << endl;
//cout << "visit 函数正在访问" << building->m_BedRoom << endl;
}
void test01()
{
GoodGay gg;
gg.visit();
gg.visit2();
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- visit 函数正在访问客厅
- visit 函数正在访问卧室
- visit2 函数正在访问客厅
- 请按任意键继续. . .

View File

@ -0,0 +1,720 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++ 运算符重载"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 运算符重载简介"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 运算符重载:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。\n",
"\n",
"② 对于内置的数据类型的表达式的运算符是不可能改变的。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 2. 加号运算符重载"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 加号运算符作用:实现两个自定义数据类型相加的运算。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"//加号运算符重载\n",
"class Person\n",
"{\n",
"public:\n",
"\n",
" //1、成员函数重载+号\n",
" Person operator+(Person& p)\n",
" {\n",
" Person temp;\n",
" temp.m_A = this->m_A + p.m_A;\n",
" temp.m_B = this->m_B + p.m_B;\n",
" return temp;\n",
" }\n",
" int m_A;\n",
" int m_B;\n",
"};\n",
"\n",
"/*\n",
"//全局函数重载+号\n",
"Person operator+(Person &p1, Person &p2)\n",
"{\n",
" Person temp;\n",
" temp.m_A = p1.m_A + p2.m_A;\n",
" temp.m_B = p1.m_B + p2.m_B;\n",
" return temp;\n",
"}\n",
"*/\n",
"\n",
"//函数重载的版本\n",
"Person operator+(Person& p1, int num)\n",
"{\n",
" Person temp;\n",
" temp.m_A = p1.m_A + num;\n",
" temp.m_B = p1.m_B + num;\n",
" return temp;\n",
"}\n",
"\n",
"void test01()\n",
"{\n",
" Person p1;\n",
" p1.m_A = 10;\n",
" p1.m_B = 10;\n",
" Person p2;\n",
" p2.m_A = 10;\n",
" p2.m_B = 10;\n",
"\n",
" //成员函数重载本质调用 \n",
" //Person p3 = p1.operator+(p2);\n",
" \n",
" //全局函数重载本质调用 \n",
" //Person p3 = operator+(p1,p2);\n",
" \n",
" Person p3 = p1 + p2; //重载本质被简化后的形式\n",
"\n",
" //运算符重载,也可以发生函数重载\n",
"\n",
" Person p4 = p1 + 10; //Person + int\n",
"\n",
" cout << \"p3.m_A\" << p3.m_A << endl;\n",
" cout << \"p3.m_B\" << p3.m_B << endl;\n",
"\n",
" cout << \"p4.m_A\" << p4.m_A << endl;\n",
" cout << \"p4.m_B\" << p4.m_B << endl;\n",
"\n",
"}\n",
"\n",
"\n",
"int main()\n",
"{\n",
" test01();\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - p3.m_A20 \n",
" - p3.m_B20 \n",
" - p4.m_A20 \n",
" - p4.m_B20 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 3. 左移运算符重载"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 左移运算符重载:可以输出自定义数据类型。\n",
"\n",
"② 重载左移运算符配合友元可以实现自定义数据类型。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"//左移运算符\n",
"class Person\n",
"{\n",
"\n",
" friend ostream& operator<<(ostream& out, Person& p);\t\n",
"\n",
"public:\n",
" Person(int a, int b)\n",
" {\n",
" m_A = a;\n",
" m_B = b;\n",
" }\n",
"\n",
" /*\n",
" //利用成员函数重载 左移运算符 p.operator<<(cout) 简化版本 p << cout\n",
" //成员函数不能利用重载<<运算符因为无法实现cout在左侧\n",
" //当不知道返回值是什么类型的时候可以先写个void以后再改\n",
" void operator<<(Person& p)\n",
" {\n",
" \n",
" }\n",
" */\n",
" \n",
"private:\n",
" int m_A;\n",
" int m_B;\n",
"};\n",
"\n",
"//只能利用全局函数重载左移运算符\n",
"//如果返回类型为void那么就无法无限追加也没有办法在后面添加换行符\n",
"ostream & operator<<(ostream &cout, Person &p) //本质 operator << (cout , p) , 简化 cout << p\n",
" //cout是别名这里可以取out、kn...\n",
" //cout为ostream输出流数据类型 \n",
"{\n",
" cout << \"m_A= \" << p.m_A << \" m_B=\" << p.m_B;\n",
" return cout;\n",
"}\n",
"\n",
"void test01()\n",
"{\n",
" Person p(10,10);\n",
"\n",
" cout << p << \" hello world\" << endl;\n",
"}\n",
"\n",
"\n",
"int main()\n",
"{\n",
" test01();\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - m_A= 10 m_B=10 hello world \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 4. 递增运算符"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 递增运算符重载:通过重载递增运算符,实现自己的整型数据。\n",
"\n",
"② 前置递增返回的是引用,后置递增返回的是值。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"//重载递增运算符\n",
"\n",
"class MyInteger\n",
"{\n",
" friend ostream& operator<<(ostream& cout, MyInteger myint);\n",
"\n",
"public:\n",
" MyInteger()\n",
" {\n",
" m_Num = 0;\n",
" }\n",
" \n",
" //重载前置++运算符,返回引用是为了一直对一个数据进行递增操作,而返回值并不是一直对一个数据进行递增操作 \n",
" MyInteger& operator++()\n",
" {\n",
" //先进行++运算\n",
" m_Num++;\n",
"\n",
" //再将自身做一个返回\n",
" return *this; //把自身做一个返回\n",
" }\n",
"\n",
" //重载后置++运算符 int代表占位参数可以用于区分前置和后置递增\n",
" //后置递增不能返回引用因为temp是局部变量如果返回temp当程序运行完后变量就释放了再调用temp就是非法操作了 \n",
" MyInteger operator++(int)\n",
" {\n",
" //先记录当时结果\n",
" MyInteger temp = *this;\n",
" //后 递增\n",
" m_Num++;\n",
" //最后将记录结果做返回\n",
" return temp;\n",
" }\n",
"private:\n",
" int m_Num;\n",
"};\n",
"\n",
"//只能利用全局函数重载左移运算符\n",
"ostream & operator<<(ostream &cout, MyInteger myint) //本质 operator << (cout , p) , 简化 cout << p\n",
" //cout是别名这里可以取out、kn...\n",
" //cout为ostream输出流数据类型 \n",
"{\n",
" cout << myint.m_Num;\n",
"\n",
" return cout;\n",
"}\n",
"\n",
"void test01()\n",
"{\n",
" MyInteger myint;\n",
"\n",
" cout << ++(++myint) << endl;\n",
" cout << myint << endl;\n",
"}\n",
"\n",
"void test02()\n",
"{\n",
" MyInteger myint;\n",
"\n",
" cout << myint++ << endl;\n",
" cout << myint << endl;\n",
"\n",
"}\n",
"\n",
"int main()\n",
"{\n",
" test01();\n",
" test02();\n",
"\n",
" /*\n",
" int a = 0;\n",
" cout << ++(++a) << endl; //运行结果为2\n",
" cout << a << endl; //运行结果为2表示一直对一个数据进行递增\n",
" */\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 2 \n",
" - 2 \n",
" - 0 \n",
" - 1 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 5. 赋值运算符"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① C++编译器至少给一个类添加4个函数\n",
"\n",
"1. 默认构造函数(无参,函数体为空)\n",
"2. 默认析构函数(无参,函数体为空)\n",
"3. 默认拷贝构造函数,对属性进行值拷贝\n",
"4. 赋值运算符operator=,对属性进行值拷贝\n",
"5. 如果类中有属性指向堆区,做赋值操作时也会出现浅拷贝问题。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"\n",
"//重载赋值运算符\n",
"\n",
"class Person\n",
"{\n",
"public:\n",
" Person(int age)\n",
" {\n",
" m_Age = new int(age);\n",
" }\n",
" \n",
" ~Person()\n",
" {\n",
" if (m_Age != NULL)\n",
" {\n",
" delete m_Age;\n",
" m_Age = NULL;\n",
" }\n",
" }\n",
"\n",
" //重载 赋值运算符\n",
" //如果返回的是值,而不是引用,是创建一个拷贝函数,返回的是一个副本,而不是自身\n",
" Person& operator=(Person& p)\n",
" {\n",
" //编译器默认是提供浅拷贝\n",
" //m_Age = p.m_Age;\n",
"\n",
" //浅拷贝带来的问题是,当创建数据在堆区时,析构代码导致内存重复释放,报错\n",
"\n",
" //应该先判断是否有属性在堆区,如果有先释放干净,然后再深拷贝\n",
" if (m_Age != NULL)\n",
" {\n",
" delete m_Age;\n",
" m_Age = NULL;\n",
" }\n",
"\n",
" //深拷贝\n",
" m_Age = new int(*p.m_Age);\n",
"\n",
" //返回对象本身\n",
" return *this;\n",
" }\n",
"\n",
" int *m_Age;\n",
"};\n",
"\n",
"void test01()\n",
"{\n",
" Person p1(18);\n",
"\n",
" Person p2(20);\n",
"\n",
" Person p3(23);\n",
"\n",
" p3 = p2 = p1; //赋值操作\n",
"\n",
" cout << \"p1的年龄为\" << *p1.m_Age << endl;\n",
"\n",
" cout << \"p2的年龄为\" << *p2.m_Age << endl;\n",
"\n",
" cout << \"p3的年龄为\" << *p3.m_Age << endl;\n",
"\n",
"\n",
"}\n",
"\n",
"int main()\n",
"{\n",
" test01();\n",
"\n",
" /*\n",
" \n",
" int a = 10;\n",
" int b = 20;\n",
" int c = 30;\n",
" \n",
" c = b = a;\n",
"\n",
" cout << \"a= \" << a << endl;\n",
" cout << \"b= \" << b << endl;\n",
" cout << \"c= \" << c << endl;\n",
" */\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - p1的年龄为18 \n",
" - p2的年龄为18 \n",
" - p3的年龄为18 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 6. 关系重载运算符"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"#include<string>\n",
"\n",
"//重载关系运算符\n",
"\n",
"class Person\n",
"{\n",
"public:\n",
" Person(string name, int age)\n",
" {\n",
" m_Name = name;\n",
" m_Age = age;\n",
" }\n",
"\n",
" //重载 == 号\n",
" bool operator==(Person& p)\n",
" {\n",
" if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)\n",
" {\n",
" return true;\n",
" }\n",
" return false;\n",
" }\n",
"\n",
" bool operator!=(Person& p)\n",
" {\n",
" if (this->m_Name != p.m_Name && this->m_Age != p.m_Age)\n",
" {\n",
" return true;\n",
" }\n",
" return false;\n",
" }\n",
"\n",
" string m_Name;\n",
" int m_Age;\n",
"};\n",
"\n",
"void test01()\n",
"{\n",
" Person p1(\"Tom\", 17);\n",
"\n",
" Person p2(\"Jerry\", 18);\n",
"\n",
" if (p1 == p2)\n",
" {\n",
" cout << \"p1和p2是相等的\" << endl;\n",
" }\n",
" else\n",
" {\n",
" cout << \"p1和p2是不相等的\" << endl;\n",
"\n",
" }\n",
"\n",
" if (p1 != p2)\n",
" {\n",
" cout << \"p1和p2是不相等的\" << endl;\n",
" }\n",
" else\n",
" {\n",
" cout << \"p1和p2是相等的\" << endl;\n",
"\n",
" }\n",
"\n",
"\n",
"}\n",
"\n",
"int main()\n",
"{\n",
" test01();\n",
" \n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - p1和p2是不相等的 \n",
" - p1和p2是不相等的 \n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 7. 函数调用运算符重载"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 函数调用运算符()也可以重载。\n",
"\n",
"② 由于重载后使用的方式非常像函数的调用,因此称为仿函数。\n",
"\n",
"③ 仿函数没有固定写法,非常灵活。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"using namespace std;\n",
"#include<string>\n",
"\n",
"//函数调用运算符重载\n",
"\n",
"//打印输出类\n",
"class MyPrint\n",
"{\n",
"public:\n",
"\n",
" //重载函数调用运算符\n",
" void operator()(string test)\n",
" {\n",
" cout << test << endl;\n",
" }\n",
"\n",
"};\n",
"\n",
"//正常函数\n",
"void MyPrint02(string test)\n",
"{\n",
" cout << test << endl;\n",
"}\n",
"\n",
"void test01()\n",
"{\n",
" MyPrint myPrint;\n",
"\n",
" myPrint(\"hello world\");\n",
"\n",
"}\n",
"\n",
"//仿函数非常灵活,没有固定的写法\n",
"//加法类\n",
"class MyAdd\n",
"{\n",
"public:\n",
" int operator()(int num1, int num2)\n",
" {\n",
" return num1 + num2;\n",
" }\n",
"};\n",
"\n",
"void test02()\n",
"{\n",
" MyAdd myadd;\n",
" int ret = myadd(100,100);\n",
" cout << \"ret = \" << ret << endl;\n",
"\n",
" //匿名函数对象\n",
" cout << MyAdd()(100, 100) << endl;\n",
"\n",
" // MyAdd()为创建一个匿名对象,匿名对象的特点为当前行执行完立即释放\n",
"}\n",
"\n",
"int main()\n",
"{\n",
" test01();\n",
"\n",
" MyPrint02(\"hello world\"); //由于使用起来非常类似于函数调用,因此称为仿函数\n",
"\n",
" test02();\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - hello world \n",
" - hello world \n",
" - ret = 200 \n",
" - 200 \n",
" - 请按任意键继续. . ."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,557 @@
# C++ 运算符重载
# 1. 运算符重载简介
① 运算符重载:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。
② 对于内置的数据类型的表达式的运算符是不可能改变的。
# 2. 加号运算符重载
① 加号运算符作用:实现两个自定义数据类型相加的运算。
```python
#include <iostream>
using namespace std;
//加号运算符重载
class Person
{
public:
//1、成员函数重载+号
Person operator+(Person& p)
{
Person temp;
temp.m_A = this->m_A + p.m_A;
temp.m_B = this->m_B + p.m_B;
return temp;
}
int m_A;
int m_B;
};
/*
//全局函数重载+号
Person operator+(Person &p1, Person &p2)
{
Person temp;
temp.m_A = p1.m_A + p2.m_A;
temp.m_B = p1.m_B + p2.m_B;
return temp;
}
*/
//函数重载的版本
Person operator+(Person& p1, int num)
{
Person temp;
temp.m_A = p1.m_A + num;
temp.m_B = p1.m_B + num;
return temp;
}
void test01()
{
Person p1;
p1.m_A = 10;
p1.m_B = 10;
Person p2;
p2.m_A = 10;
p2.m_B = 10;
//成员函数重载本质调用
//Person p3 = p1.operator+(p2);
//全局函数重载本质调用
//Person p3 = operator+(p1,p2);
Person p3 = p1 + p2; //重载本质被简化后的形式
//运算符重载,也可以发生函数重载
Person p4 = p1 + 10; //Person + int
cout << "p3.m_A" << p3.m_A << endl;
cout << "p3.m_B" << p3.m_B << endl;
cout << "p4.m_A" << p4.m_A << endl;
cout << "p4.m_B" << p4.m_B << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- p3.m_A20
- p3.m_B20
- p4.m_A20
- p4.m_B20
- 请按任意键继续. . .
# 3. 左移运算符重载
① 左移运算符重载:可以输出自定义数据类型。
② 重载左移运算符配合友元可以实现自定义数据类型。
```python
#include <iostream>
using namespace std;
//左移运算符
class Person
{
friend ostream& operator<<(ostream& out, Person& p);
public:
Person(int a, int b)
{
m_A = a;
m_B = b;
}
/*
//利用成员函数重载 左移运算符 p.operator<<(cout) 简化版本 p << cout
//成员函数不能利用重载<<运算符因为无法实现cout在左侧
//当不知道返回值是什么类型的时候可以先写个void以后再改
void operator<<(Person& p)
{
}
*/
private:
int m_A;
int m_B;
};
//只能利用全局函数重载左移运算符
//如果返回类型为void那么就无法无限追加也没有办法在后面添加换行符
ostream & operator<<(ostream &cout, Person &p) //本质 operator << (cout , p) , 简化 cout << p
//cout是别名这里可以取out、kn...
//cout为ostream输出流数据类型
{
cout << "m_A= " << p.m_A << " m_B=" << p.m_B;
return cout;
}
void test01()
{
Person p(10,10);
cout << p << " hello world" << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- m_A= 10 m_B=10 hello world
- 请按任意键继续. . .
# 4. 递增运算符
① 递增运算符重载:通过重载递增运算符,实现自己的整型数据。
② 前置递增返回的是引用,后置递增返回的是值。
```python
#include <iostream>
using namespace std;
//重载递增运算符
class MyInteger
{
friend ostream& operator<<(ostream& cout, MyInteger myint);
public:
MyInteger()
{
m_Num = 0;
}
//重载前置++运算符,返回引用是为了一直对一个数据进行递增操作,而返回值并不是一直对一个数据进行递增操作
MyInteger& operator++()
{
//先进行++运算
m_Num++;
//再将自身做一个返回
return *this; //把自身做一个返回
}
//重载后置++运算符 int代表占位参数可以用于区分前置和后置递增
//后置递增不能返回引用因为temp是局部变量如果返回temp当程序运行完后变量就释放了再调用temp就是非法操作了
MyInteger operator++(int)
{
//先记录当时结果
MyInteger temp = *this;
//后 递增
m_Num++;
//最后将记录结果做返回
return temp;
}
private:
int m_Num;
};
//只能利用全局函数重载左移运算符
ostream & operator<<(ostream &cout, MyInteger myint) //本质 operator << (cout , p) , 简化 cout << p
//cout是别名这里可以取out、kn...
//cout为ostream输出流数据类型
{
cout << myint.m_Num;
return cout;
}
void test01()
{
MyInteger myint;
cout << ++(++myint) << endl;
cout << myint << endl;
}
void test02()
{
MyInteger myint;
cout << myint++ << endl;
cout << myint << endl;
}
int main()
{
test01();
test02();
/*
int a = 0;
cout << ++(++a) << endl; //运行结果为2
cout << a << endl; //运行结果为2表示一直对一个数据进行递增
*/
system("pause");
return 0;
}
```
运行结果:
- 2
- 2
- 0
- 1
- 请按任意键继续. . .
# 5. 赋值运算符
① C++编译器至少给一个类添加4个函数
1. 默认构造函数(无参,函数体为空)
2. 默认析构函数(无参,函数体为空)
3. 默认拷贝构造函数,对属性进行值拷贝
4. 赋值运算符operator=,对属性进行值拷贝
5. 如果类中有属性指向堆区,做赋值操作时也会出现浅拷贝问题。
```python
#include <iostream>
using namespace std;
//重载赋值运算符
class Person
{
public:
Person(int age)
{
m_Age = new int(age);
}
~Person()
{
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
}
//重载 赋值运算符
//如果返回的是值,而不是引用,是创建一个拷贝函数,返回的是一个副本,而不是自身
Person& operator=(Person& p)
{
//编译器默认是提供浅拷贝
//m_Age = p.m_Age;
//浅拷贝带来的问题是,当创建数据在堆区时,析构代码导致内存重复释放,报错
//应该先判断是否有属性在堆区,如果有先释放干净,然后再深拷贝
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
//深拷贝
m_Age = new int(*p.m_Age);
//返回对象本身
return *this;
}
int *m_Age;
};
void test01()
{
Person p1(18);
Person p2(20);
Person p3(23);
p3 = p2 = p1; //赋值操作
cout << "p1的年龄为" << *p1.m_Age << endl;
cout << "p2的年龄为" << *p2.m_Age << endl;
cout << "p3的年龄为" << *p3.m_Age << endl;
}
int main()
{
test01();
/*
int a = 10;
int b = 20;
int c = 30;
c = b = a;
cout << "a= " << a << endl;
cout << "b= " << b << endl;
cout << "c= " << c << endl;
*/
system("pause");
return 0;
}
```
运行结果:
- p1的年龄为18
- p2的年龄为18
- p3的年龄为18
- 请按任意键继续. . .
# 6. 关系重载运算符
```python
#include <iostream>
using namespace std;
#include<string>
//重载关系运算符
class Person
{
public:
Person(string name, int age)
{
m_Name = name;
m_Age = age;
}
//重载 == 号
bool operator==(Person& p)
{
if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
{
return true;
}
return false;
}
bool operator!=(Person& p)
{
if (this->m_Name != p.m_Name && this->m_Age != p.m_Age)
{
return true;
}
return false;
}
string m_Name;
int m_Age;
};
void test01()
{
Person p1("Tom", 17);
Person p2("Jerry", 18);
if (p1 == p2)
{
cout << "p1和p2是相等的" << endl;
}
else
{
cout << "p1和p2是不相等的" << endl;
}
if (p1 != p2)
{
cout << "p1和p2是不相等的" << endl;
}
else
{
cout << "p1和p2是相等的" << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- p1和p2是不相等的
- p1和p2是不相等的
- 请按任意键继续. . .
# 7. 函数调用运算符重载
① 函数调用运算符()也可以重载。
② 由于重载后使用的方式非常像函数的调用,因此称为仿函数。
③ 仿函数没有固定写法,非常灵活。
```python
#include <iostream>
using namespace std;
#include<string>
//函数调用运算符重载
//打印输出类
class MyPrint
{
public:
//重载函数调用运算符
void operator()(string test)
{
cout << test << endl;
}
};
//正常函数
void MyPrint02(string test)
{
cout << test << endl;
}
void test01()
{
MyPrint myPrint;
myPrint("hello world");
}
//仿函数非常灵活,没有固定的写法
//加法类
class MyAdd
{
public:
int operator()(int num1, int num2)
{
return num1 + num2;
}
};
void test02()
{
MyAdd myadd;
int ret = myadd(100,100);
cout << "ret = " << ret << endl;
//匿名函数对象
cout << MyAdd()(100, 100) << endl;
// MyAdd()为创建一个匿名对象,匿名对象的特点为当前行执行完立即释放
}
int main()
{
test01();
MyPrint02("hello world"); //由于使用起来非常类似于函数调用,因此称为仿函数
test02();
system("pause");
return 0;
}
```
运行结果:
- hello world
- hello world
- ret = 200
- 200
- 请按任意键继续. . .

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,943 @@
# C++的继承
# 1. 继承简介
① 继承是面向对象的三大特性之一。
② 定义类时,下级别的成员除了拥有上一级的共性,还有自己的特性。这个时候,就可以考虑利用继承技术,减少重复代码。
![image.png](25_C++的类中继承_files/image.png)
## 1.1 普通实现
```python
#include <iostream>
using namespace std;
#include<string>
//打印输出类
class Java
{
public:
void header()
{
cout << "首页、公开课、登陆、注册...(公共头部)" << endl;
}
void footer()
{
cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
}
void left()
{
cout << "Java、Python、C++....(公共分类列表)" << endl;
}
void content()
{
cout << "Java学科视频" << endl;
}
};
class Python
{
public:
void header()
{
cout << "首页、公开课、登陆、注册...(公共头部)" << endl;
}
void footer()
{
cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
}
void left()
{
cout << "Java、Python、C++....(公共分类列表)" << endl;
}
void content()
{
cout << "Python学科视频" << endl;
}
};
class CPP
{
public:
void header()
{
cout << "首页、公开课、登陆、注册...(公共头部)" << endl;
}
void footer()
{
cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
}
void left()
{
cout << "Java、Python、C++....(公共分类列表)" << endl;
}
void content()
{
cout << "C++学科视频" << endl;
}
};
void test01()
{
cout << "Java下载视频页面如下" << endl;
Java ja;
ja.header();
ja.footer();
ja.left();
ja.content();
cout << "........................" << endl;
cout << "Python下载视频页面如下" << endl;
Python py;
py.header();
py.footer();
py.left();
py.content();
cout << "........................" << endl;
cout << "C++下载视频页面如下:" << endl;
CPP cpp;
cpp.header();
cpp.footer();
cpp.left();
cpp.content();
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- Java下载视频页面如下
- 首页、公开课、登陆、注册...(公共头部)
- 帮助中心、交流合作、站内地图...(公共底部)
- Java、Python、C++....(公共分类列表)
- Java学科视频
- ........................
- Python下载视频页面如下
- 首页、公开课、登陆、注册...(公共头部)
- 帮助中心、交流合作、站内地图...(公共底部)
- Java、Python、C++....(公共分类列表)
- Python学科视频
- ........................
- C++下载视频页面如下:
- 首页、公开课、登陆、注册...(公共头部)
- 帮助中心、交流合作、站内地图...(公共底部)
- Java、Python、C++....(公共分类列表)
- C++学科视频
- 请按任意键继续. . .
## 1.2 继承实现
```python
#include <iostream>
using namespace std;
#include<string>
//打印输出类
class BasePage
{
public:
void header()
{
cout << "首页、公开课、登陆、注册...(公共头部)" << endl;
}
void footer()
{
cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
}
void left()
{
cout << "Java、Python、C++....(公共分类列表)" << endl;
}
};
// 继承的好处:减少重复代码
// 语法class 子类:继承方式 父类
// 子类 也称为 派生类
// 父类 也称为 基类
//Java页面
class Java:public BasePage //继承了BasePage把BasePage里面的内容全部拿到手了
{
public:
void content()
{
cout << "Java学科视频" << endl;
}
};
//Python页面
class Python :public BasePage //继承了BasePage把BasePage里面的内容全部拿到手了
{
public:
void content()
{
cout << "Python学科视频" << endl;
}
};
//C++页面
class CPP :public BasePage //继承了BasePage把BasePage里面的内容全部拿到手了
{
public:
void content()
{
cout << "CPP学科视频" << endl;
}
};
void test01()
{
cout << "Java下载视频页面如下" << endl;
Java ja;
ja.header();
ja.footer();
ja.left();
ja.content();
cout << "........................" << endl;
cout << "Python下载视频页面如下" << endl;
Python py;
py.header();
py.footer();
py.left();
py.content();
cout << "........................" << endl;
cout << "C++下载视频页面如下:" << endl;
CPP cpp;
cpp.header();
cpp.footer();
cpp.left();
cpp.content();
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- Java下载视频页面如下
- 首页、公开课、登陆、注册...(公共头部)
- 帮助中心、交流合作、站内地图...(公共底部)
- Java、Python、C++....(公共分类列表)
- Java学科视频
- ........................
- Python下载视频页面如下
- 首页、公开课、登陆、注册...(公共头部)
- 帮助中心、交流合作、站内地图...(公共底部)
- Java、Python、C++....(公共分类列表)
- Python学科视频
- ........................
- C++下载视频页面如下:
- 首页、公开课、登陆、注册...(公共头部)
- 帮助中心、交流合作、站内地图...(公共底部)
- Java、Python、C++....(公共分类列表)
- CPP学科视频
- 请按任意键继续. . .
# 2. 三种继承改变权限
① 继承的语法class 子类:继承方式 父类
② 继承方式一共有三种:
1. 公共继承
2. 保护继承
3. 私有继承
③ 不同的继承方式,父类中的变量被继承后,权限相应的得到了改变,如下图所示。
![image.png](25_C++的类中继承_files/image.png)
```python
#include <iostream>
using namespace std;
#include<string>
//打印输出类
class Base1
{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
//公共继承
class Son1:public Base1
{
public:
void func()
{
m_A = 10; //父类中的公共权限成员 到子类中依然是公共权限
m_B = 10; //父类中的保护权限成员 到子类中依然是保护权限
//m_C = 10; //父类中的私有权限成员 子类访问不到
}
};
void test01()
{
Son1 s1;
s1.m_A = 100; //公共权限,类内能访问,类外也能访问
//s1.m_B = 100; //保护权限,类内能访问,类外不能访问
}
//保护继承
class Son2:protected Base1
{
public:
void func()
{
m_A = 10; //父类中的公共权限成员 到子类中变为保护权限
m_B = 10; //父类中的保护权限成员 到子类中依然是保护权限
//m_C = 10; //父类中的私有权限成员 子类访问不到
}
};
void test02()
{
Son2 s2;
//s2.m_A = 100; //保护权限,类内能访问,类外不能访问
//s2.m_B = 100; //保护权限,类内能访问,类外不能访问
}
//私有继承
class Son3:private Base1
{
public:
void func()
{
m_A = 10; //父类中的公共权限成员 到子类中变为私有权限
m_B = 10; //父类中的保护权限成员 到子类中变为私有权限
//m_C = 10; //父类中的私有权限成员 子类访问不到
}
};
void test03()
{
Son3 s3;
//s3.m_A = 100; //私有权限,类内能访问,类外不能访问
//s3.m_B = 100; //私有权限,类内能访问,类外不能访问
}
int main()
{
system("pause");
return 0;
}
```
运行结果:
- 请按任意键继续. . .
# 3. 继承对象内存
## 3.1 查询继承对象所占内存
```python
#include <iostream>
using namespace std;
#include<string>
//继承中的对象模型
class Base
{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
//公共继承
class Son:public Base
{
int m_D;
};
//利用开发人员命令提示工具查看对象模型
//跳转盘符→F:
//跳转文件路径→cd 具体路径下
//查看命令
//cl /d1 reportSingleClassLayout查看的类名 "文件名"
void test01()
{
//父类中所有非静态成员属性都会被子类继承下去
//父类中私有成员属性 是被编译器给隐藏了,因此是访问不到,但是确实被继承下去了
cout << "size of Son =" << sizeof(Son) << endl; //16个字节父类3个int一个12个字节字节1个int4个字节
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- size of Son =16
- 按任意键继续. . .
## 3.2 VS自带开发工具查询
① 首先打开visio studio的开发人员命令工具如下图所示。
![image.png](25_C++的类中继承_files/image.png)
② 查询visio studio的项目所在地址。
③ "输入跳转盘符例如C:"->"输入项目所在地的地址"->"输入dir(查询项目中文件信息)"
![image.png](25_C++的类中继承_files/image.png)
② 输入cl(空格)/d1 reportSingleClassLayout查看的类名 "文件名",可以查看类所占内存空间大小。
![image.png](25_C++的类中继承_files/image.png)
# 4. 继承构造和析构顺序
① 继承中,先调用父类构造函数,再调用子类构造函数,析构顺序与构造顺序相反,先调用子类析构函数,再调用父类析构函数。
```python
#include <iostream>
using namespace std;
#include<string>
//继承中的构造和析构顺序
class Base
{
public:
Base()
{
cout << "Base构造函数" << endl;
}
~Base()
{
cout << "Base析构函数" << endl;
}
};
//
class Son:public Base
{
public:
Son()
{
cout << "Son构造函数" << endl;
}
~Son()
{
cout << "Son析构函数" << endl;
}
};
void test01()
{
//Base b; //创建父类对象只有父类的构造函数、析构函数
//继承中的构造和析构顺序如下:
//先构造父类、再构造子类,析构的顺序与构造的顺序相反
Son s;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- Base构造函数
- Son构造函数
- Son析构函数
- Base析构函数
- 请按任意键继续. . .
# 5. 同名成员处理
① 子类对象可以直接访问到子类中同名成员。
② 子类对象加作用域可以访问到父类同名成员。
③ 当子类与父类拥有同名的成员函数,子类会隐藏父类中所有同名成员函数(有参、无参),加作用域才可以访问到父类中同名函数。
```python
#include <iostream>
using namespace std;
#include<string>
//继承中同名成员处理
class Base
{
public:
Base()
{
m_A = 100;
}
int m_A;
void func()
{
cout << "Base - func()调用" << endl;
}
void func(int a)
{
cout << "Base - func(int a)调用" << endl;
}
};
class Son:public Base
{
public:
Son()
{
m_A = 200;
}
void func()
{
cout << "Son - func()调用" << endl;
}
int m_A;
};
//同名成员属性处理方式
void test01()
{
Son s;
cout << "Son 下 m_A=" << s.m_A << endl;
//如果通过子类对象访问到父类中同名成员,需要加作用域
cout << "Base 下 m_A=" << s.Base::m_A << endl;
}
//同名成员函数处理方式
void test02()
{
Son s;
s.func(); //直接调用 调用时子类中的同名成员
//调用父类中同名成员函数
s.Base::func();
//如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类中所有同名成员函数
//如果想访问到父类中被隐藏的同名成员函数,需要加作用域
s.Base::func(100);
}
//同名成员函数处理
int main()
{
test01();
test02();
system("pause");
return 0;
}
```
运行结果:
- Son 下 m_A=200
- Base 下 m_A=100
- Son - func()调用
- Base - func()调用
- Base - func(int a)调用
- 请按任意键继续. . .
# 6. 同名静态成员处理
① 静态成员和非静态成员出现同名,处理方式一致:
1. 访问子类同名成员,直接访问
2. 访问父类同名成员,需要加作用域
② 加上static关键字后成员发生变化成员变成静态成员。
③ 静态成员变量特点:
1. 所有对象都共享同一份数据。
2. 编译阶段就分配内存。
3. 类内声明,类外初始化。
④ 静态成员函数特点:
1. 只能访问静态成员变量,不能访问非静态成员变量。
2. 所有对象都共享同一份函数实例。
```python
#include <iostream>
using namespace std;
//继承中同名静态成员处理方式
class Base
{
public:
static int m_A; //静态成员类内声明,类外初始化
static void func()
{
cout << "Base - static func()" << endl;
}
static void func(int a)
{
cout << "Base - static func(int a)" << endl;
}
};
int Base::m_A=100;
class Son:public Base
{
public:
static int m_A;
static void func()
{
cout << "Son - static void func()" << endl;
}
};
int Son::m_A = 200;
//同名静态成员属性
void test01()
{
//1、通过对象访问
Son s;
cout << "Son 下 m_A = " << s.m_A << endl;
cout << "Base 下 m_A = " << s.Base::m_A << endl;
//2、通过类名访问
cout << "Son 下 m_A = "<< Son::m_A << endl;
//第一个::代表通过类名方式访问 第二个::代表访问父类作用域
cout << "Base 下 m_A= "<< Son::Base::m_A << endl;
}
void test02()
{
//1、通过对象访问
Son s;
s.func();
s.Base::func();
//2、通过类名访问
Son::func();
Son::Base::func();
//子类出现和父类同名静态成员函数,也会隐藏掉父类中所有同名成员函数
//如何想访问父类中被隐藏同名成员,需要加作用域
Son::Base::func(100);
}
//同名成员函数处理
int main()
{
test01();
test02();
system("pause");
return 0;
}
```
运行结果:
- Son 下 m_A = 200
- Base 下 m_A = 100
- Son 下 m_A = 200
- Base 下 m_A= 100
- Son - static void func()
- Base - static func()
- Son - static void func()
- Base - static func()
- Base - static func(int a)
- 请按任意键继续. . .
# 7. 多继承语法
① C++运行一个类继承多个类。
② 语法class 子类:继承方式 父类1继承方式 父类2.....
③ 多继承可能会引发父类中有同名成员出现,需要加作用域区分。
④ C++实际开发中不建议用多继承。
```python
#include <iostream>
using namespace std;
class Base1
{
public:
Base1()
{
m_A = 100;
}
int m_A;
};
class Base2
{
public:
Base2()
{
m_A = 200;
}
int m_A;
};
//子类 需要继承Base1和Base2
//语法class 子类:继承方式 父类1继承方式 父类2.....
class Son:public Base1,public Base2
{
public:
Son()
{
m_C = 300;
m_D = 400;
}
int m_C;
int m_D;
};
void test01()
{
Son s;
cout << "sizeof(Son):" << sizeof(s) << endl;
//当父类中出现同名成员,需要加作用域区分
cout << "Base1::m_A = " << s.Base1::m_A << endl;
cout << "Base2::m_A = " << s.Base2::m_A << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- sizeof(Son):16
- Base1::m_A = 100
- Base2::m_A = 200
- 请按任意键继续. . .
# 8. 菱形继承
## 8.1 菱形继承简介
① 菱形继承概念:
1. 两个派生类继承同一个基类
2. 又有某个类同时继承两个派生类
3. 这种继承被称为菱形继承
② 羊继承了动物的数据,驼同样继承了动物的数据,当草泥马使用数据是,就会产生二义性。
③ 草泥马继承自动物的数据继承了两份,其实我们应当清楚,这份数据我们只需要一份就可以。
④ 菱形继承带来的主要问题是子类继承两份相同的数据,导致资源浪费以及毫无意义。
⑤ 利用虚继承可以解决菱形继承问题。
![image.png](25_C++的类中继承_files/image.png)
## 8.2 菱形继承普通方式
```python
#include <iostream>
using namespace std;
//动物类
class Animal
{
public:
int m_Age;
};
//羊类
class Sheep:public Animal{};
//驼类
class Tuo:public Animal{};
//羊驼类
class SheepTuo:public Sheep,public Tuo{};
void test01()
{
SheepTuo st;
st.Sheep::m_Age = 18;
st.Tuo::m_Age = 28;
//当出现菱形继承,两个父类拥有相同数据,需要加以作用域区分
cout << "st.Sheep::m_Age="<< st.Sheep::m_Age << endl;
cout << "st.Tuo::m_Age=" << st.Tuo::m_Age << endl;
//这份数据我们知道 只有一份就可以,菱形继承导致数据有两份,资源浪费
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- st.Sheep::m_Age=18
- st.Tuo::m_Age=28
- 请按任意键继续. . .
## 8.3 菱形继承虚继承
### 8.3.1 菱形继承虚继承方式
```python
#include <iostream>
using namespace std;
//动物类
class Animal
{
public:
int m_Age;
};
//利用虚继承 解决菱形继承的问题
//继承之前 加上关键字 virtual 变成 虚继承
//虚继承后Animal类 称为 虚基类
//羊类
class Sheep:virtual public Animal{};
//驼类
class Tuo:virtual public Animal{};
//羊驼类
class SheepTuo:public Sheep,public Tuo{};
void test01()
{
SheepTuo st;
st.Sheep::m_Age = 18;
st.Tuo::m_Age = 28;
//当出现菱形继承,两个父类拥有相同数据,需要加以作用域区分
cout << "st.Sheep::m_Age="<< st.Sheep::m_Age << endl;
cout << "st.Tuo::m_Age=" << st.Tuo::m_Age << endl;
//虚继承,多产生一种输出方式(因为上面两个是同一份数据,所以可以不加作用域来区分了)
cout << "st.m_Age=" << st.m_Age << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- st.Sheep::m_Age=28
- st.Tuo::m_Age=28
- st.m_Age=28
- 请按任意键继续. . .
### 8.3.2 菱形继承虚继承VS查询
① Sheep类和Tuo类继承的都是vbptrvbptr为虚基类继承指针。
1. v - virtual
2. b - base
3. ptr = pointer
② 菱形继承并不是继承两份数据,而是继承两份指针,这两个指针会分别指向虚基类表,虚基类表中会记录偏移量,加上这个偏移量,会指向这个唯一的数据。
![image.png](25_C++的类中继承_files/image.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 KiB

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,952 @@
# C++的多态
# 1. 多态简介
① 多态是C++面向对象三大特性之一。
② 多态分为两类:
1. 静态多态:函数重载和运算符重载属于静态多态,复用函数名。
2. 动态多态:派生类和虚函数实现运行时多态。
③ 静态多态和动态多态区别:
1. 静态多态的函数地址早绑定,编译阶段确定函数地址。
2. 动态多态的函数地址晚绑定,运行阶段确定函数地址。
④ 多态满足条件:
1. 有继承关系
2. 子类重写父类中的虚函数
⑤ 多态使用条件:
1. 父类指针或引用指向子类对象
⑥ 重写:函数返回值类型、函数名、参数列表都完全一致称为重写。
# 2. 多态地址绑定
## 2.1 地址早绑定
```python
#include <iostream>
using namespace std;
//多态
//动物类
class Animal
{
public:
void speak()
{
cout << "动物在说话" << endl;
}
};
//猫类
class Cat:public Animal
{
public:
void speak()
{
cout << "小猫在说话" << endl;
}
};
//执行说话的函数
//地址早绑定 在编译阶段确定函数地址
//如果想执行让猫说话,那么这个函数就不能提前绑定,需要在运行阶段进行绑定,地址晚绑定
void doSpeak(Animal &animal) // Animal & animal = cat
{
animal.speak();
}
void test01()
{
Cat cat;
doSpeak(cat);
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 动物在说话
- 请按任意键继续. . .
## 2.2 地址晚绑定虚函数
```python
#include <iostream>
using namespace std;
//多态
//动物类
class Animal
{
public:
virtual void speak()
{
cout << "动物在说话" << endl;
}
};
//猫类
class Cat:public Animal
{
public:
//重写 函数返回值类型、函数名、参数列表都完全相同才叫重写
void speak() //子类virtual可写可不写也可以写 virtual void speak()
{
cout << "小猫在说话" << endl;
}
};
//狗类
class Dog:public Animal
{
public:
virtual void speak()
{
cout << "小狗在说话" << endl;
}
};
//执行说话的函数
//地址早绑定 在编译阶段确定函数地址
//如果想执行让猫说话,那么这个函数就不能提前绑定,需要在运行阶段进行绑定,地址晚绑定
//动态多态满足条件
//1、有继承关系
//2、子类重写父类的虚函数
//动态多态使用
//父类的引用或指针指向子类对象
void doSpeak(Animal &animal) // Animal & animal = cat
{
animal.speak();
}
void test01()
{
Cat cat;
doSpeak(cat);
Dog dog;
doSpeak(dog);
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 小猫在说话
- 小狗在说话
- 请按任意键继续. . .
# 3. 多态的原理剖析
① 当没有发生重写时,子类中的虚函数表内部为父类的虚函数地址。
![image.png](26_C++的类中多态_files/image.png)
② 当子类重写父类的虚函数,子类中的虚函数表内部会替换成子类的虚函数地址。
![image.png](26_C++的类中多态_files/image.png)
```python
#include <iostream>
using namespace std;
//多态
//动物类
class Animal
{
public: //如果是虚函数那么类里面存了一个指针类占4个字节
virtual void speak() //如果是非静态成员函数void speak()那么函数不在类上空类占1个字节空间
{
cout << "动物在说话" << endl;
}
};
//猫类
class Cat:public Animal
{
public:
void speak()
{
cout << "小猫在说话" << endl;
}
};
//狗类
class Dog:public Animal
{
public:
virtual void speak()
{
cout << "小狗在说话" << endl;
}
};
//执行说话的函数
//地址早绑定 在编译阶段确定函数地址
//如果想执行让猫说话,那么这个函数就不能提前绑定,需要在运行阶段进行绑定,地址晚绑定
//动态多态满足条件
//1、有继承关系
//2、子类重写父类的虚函数
//动态多态使用
//父类的引用或指针指向子类对象
void doSpeak(Animal &animal) // Animal & animal = cat
{
animal.speak();
}
void test01()
{
Cat cat;
doSpeak(cat);
Dog dog;
doSpeak(dog);
}
void test02()
{
cout << "sizeof Animal = " << sizeof(Animal) << endl;
}
int main()
{
//test01();
test02();
system("pause");
return 0;
}
```
运行结果:
- sizeof Animal = 4
- 请按任意键继续. . .
# 4. 纯虚函数和抽象类
① 在多态中,通常父类中虚函数的实现时毫无意义的,主要都是调用子类重写的内容。因此,可以将虚函数改为纯虚函数。
② 纯虚函数语法virtual 返回值类型 函数名 (参数列表) = 0
③ 当类中有了纯虚函数,这个类也称为抽象类。
④ 抽象类特点:
1. 无法实例化对象
2. 子类必须重写抽象类中的纯虚函数,否则也属于抽象类。
```python
#include <iostream>
using namespace std;
//纯虚函数和抽象类
class Base
{
public:
//纯虚函数
//只要有一个纯虚函数,这个类称为抽象类
//抽象类特点:
//1、无法实例化对象
//2、抽象类的子类 必须要重写父类中的纯虚函数,否则也属于抽象类
virtual void func() = 0;
};
class Son : public Base
{
public:
virtual void func()
{
cout << "func函数调用" << endl;
}
};
void test01()
{
//Base b; //抽象类是无法实例化对象
//new Base; //抽象类是无法实例化对象
//Son s; //子类中必须重写父类中的纯虚函数,否则无法实例化对象
Base* base = new Son;
base->func();
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- func函数调用
- 请按任意键继续. . .
# 5. 虚析构和纯虚析构
① 多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用子类的析构代码。
② 解决方式:将父类中的析构函数改为虚析构或者纯虚析构。
③ 虚析构和纯虚析构共性:
1. 可以解决父类指针释放子类对象
2. 都需要有具体的函数实现
④ 虚析构语法virtual.类名(){}
⑤ 纯虚析构语法:
1. virtual~类名 = 0
2. 类名::~类名(){}
① 虚析构或纯虚析构就是用来解决通过父类指针释放子类对象。
② 如果子类中没有堆区数据,可以不写为虚析构或纯虚析构。
③ 拥有纯虚析构函数的类也属于抽象类。
```python
#include <iostream>
using namespace std;
#include<string>
//纯虚函数和纯虚机构
class Animal
{
public:
Animal()
{
cout << "Animal构造函数调用" << endl;
}
//纯虚函数
virtual void speak() = 0;
/*
//利用虚析构可以解决,父类指针释放子类对象时不干净的问题
virtual ~Animal()
{
cout << "Animal析构函数调用" << endl;
}
*/
//纯虚析构 需要声明也需要实现
//有了纯虚析构之后,这个类也属于抽象类,无法实例化对象
virtual ~Animal() = 0;
};
Animal::~Animal()
{
cout << "Animal纯虚析构函数调用" << endl;
}
class Cat : public Animal
{
public:
Cat(string name)
{
cout << "Cat构造函数调用" << endl;
m_Name = new string(name);
}
virtual void speak()
{
cout << *m_Name << "小猫在说话" << endl;
}
~Cat()
{
if (m_Name != NULL)
{
cout << "Cat析构函数调用" << endl;
delete m_Name;
m_Name = NULL;
}
}
string* m_Name;
};
void test01()
{
Animal* animal = new Cat("Tom");
animal->speak();
//父类指针在析构时候,不会调用子类中析构函数,导致子类如果有堆区属性,出现内存泄露
delete animal;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- Animal构造函数调用
- Cat构造函数调用
- Tom小猫在说话
- Cat析构函数调用
- Animal纯虚析构函数调用
- 请按任意键继续. . .
# 6. 计算器
① 案例描述:分布利用普通写法和多态技术,设计实现两个操作数进行运算的计算器类。
② 多态的优点:
1. 代码组织结构清晰。
2. 多可读性强。
3. 利于前期和后期的扩展以及维护。
③ C++开发提倡利用多态设计程序架构,因为多态优点很多。
## 6.1 普通写法实现多态
```python
#include <iostream>
using namespace std;
#include<string>
//普通方法实现多态
class Calculator
{
public:
int getResult(string oper)
{
if (oper == "+")
{
return m_Num1 + m_Num2;
}
else if (oper == "-")
{
return m_Num1 - m_Num2;
}
else if (oper == "*")
{
return m_Num1 * m_Num2;
}
//如果想扩展新的功能,需要修改源码
//在真的开发中 提倡 开闭原则
//开闭原则:对扩展进行开发,对修改进行关闭
}
int m_Num1; //操作数1
int m_Num2; //操作数2
};
void test01()
{
//创建计算器对象
Calculator c;
c.m_Num1 = 10;
c.m_Num2 = 10;
cout << c.m_Num1 << "+" << c.m_Num2 << "=" << c.getResult("+") << endl;
cout << c.m_Num1 << "-" << c.m_Num2 << "=" << c.getResult("-") << endl;
cout << c.m_Num1 << "*" << c.m_Num2 << "=" << c.getResult("*") << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 10+10=20
- 10-10=0
- 10*10=100
- 请按任意键继续. . .
## 6.2 多态设计程序架构
```python
#include <iostream>
using namespace std;
#include<string>
//普通方法实现多态
#include <iostream>
using namespace std;
//多态
class AbstractCalculator
{
public:
virtual int getResult()
{
return 0;
}
int m_Num1;
int m_Num2;
};
//加法计算器类
class AddCalculator : public AbstractCalculator
{
public:
int getResult()
{
return m_Num1 + m_Num2;
}
};
//减法计算器类
class SubCalculator : public AbstractCalculator
{
public:
int getResult()
{
return m_Num1 - m_Num2;
}
};
//乘法计算器类
class MulCalculator : public AbstractCalculator
{
public:
int getResult()
{
return m_Num1 * m_Num2;
}
};
void test02()
{
//多态使用条件
//父类指针或者引用指向子类对象
AbstractCalculator* abc = new AddCalculator; //这里用的是父类指针指向子类对象
abc->m_Num1 = 100;
abc->m_Num2 = 200;
cout << abc->m_Num1 << "+" << abc->m_Num2 << "=" << abc->getResult() << endl;
//用完后记得销毁
delete abc;
//减法运算
abc = new SubCalculator; //指针并没有释放
abc->m_Num1 = 100;
abc->m_Num2 = 200;
cout << abc->m_Num1 << "-" << abc->m_Num2 << "=" << abc->getResult() << endl;
//用完后记得销毁
delete abc;
//乘法运算
abc = new MulCalculator; //指针并没有释放
abc->m_Num1 = 100;
abc->m_Num2 = 200;
cout << abc->m_Num1 << "*" << abc->m_Num2 << "=" << abc->getResult() << endl;
//用完后记得销毁
delete abc;
}
int main()
{
test02();
system("pause");
return 0;
}
```
运行结果:
- 100+200=300
- 100-200=-100
- 100*200=20000
- 请按任意键继续. . .
# 7. 制作饮品
① 案例描述:制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料
② 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶。
![image.png](26_C++的类中多态_files/image.png)
```python
#include <iostream>
using namespace std;
class AbstractDring
{
public:
//煮水
virtual void Boil() = 0;
//冲泡
virtual void Brew() = 0;
//倒入杯中
virtual void PourInCup() = 0;
//加入辅料
virtual void PutSomething() = 0;
//制作饮品
void makeDrink()
{
Boil();
Brew();
PourInCup();
PutSomething();
}
};
//制作咖啡
class Coffee :public AbstractDring
{
public:
//煮水
virtual void Boil()
{
cout << "煮农夫山泉" << endl;
}
//冲泡
virtual void Brew()
{
cout << "冲泡咖啡" << endl;
}
//倒入杯中
virtual void PourInCup()
{
cout << "倒入杯中" << endl;
}
//加入辅料
virtual void PutSomething()
{
cout << "加入糖和牛奶" << endl;
}
};
//制作茶叶
class Tea :public AbstractDring
{
public:
//煮水
virtual void Boil()
{
cout << "煮茶叶" << endl;
}
//冲泡
virtual void Brew()
{
cout << "冲泡茶叶" << endl;
}
//倒入杯中
virtual void PourInCup()
{
cout << "倒入杯中" << endl;
}
//加入辅料
virtual void PutSomething()
{
cout << "加入枸杞" << endl;
}
};
//制作函数
void doWork(AbstractDring* abs)
{
abs->makeDrink();
delete abs; //释放
}
void test01()
{
//制作咖啡
doWork(new Coffee);
cout << "----------------" << endl;
doWork(new Tea);
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 煮农夫山泉
- 冲泡咖啡
- 倒入杯中
- 加入糖和牛奶
- $----------------$
- 煮茶叶
- 冲泡茶叶
- 倒入杯中
- 加入枸杞
- 请按任意键继续. . .
# 8. 电脑组装
案例描述电脑用主要组成部件为CPU(用于计算),显卡(用于显示),内存条(用于存储)将每个零件封装出抽象基类并且提供不同的厂商生产不同的零件例如intel厂商和Lennovo厂商创建电脑类提供电脑工作的函数并且调用每个零件工作的接口。测试时组装三台不同的电脑进行工作。
```python
#include <iostream>
using namespace std;
#include<string>
//抽象不同零件类
//抽象CPU类
class CPU
{
public:
//抽象的计算函数
virtual void calculate() = 0;
};
//抽象显卡类
class VideoCard
{
public:
//抽象的显示函数
virtual void display() = 0;
};
//抽象内存条类
class Memory
{
public:
//抽象的存储函数
virtual void storage() = 0;
};
//电脑类
class Computer
{
public:
Computer(CPU* cpu, VideoCard* vc, Memory* mem)
{
m_cpu = cpu;
m_vc = vc;
m_mem = mem;
}
//提供工作的函数
void work()
{
m_cpu->calculate();
m_vc->display();
m_mem->storage();
}
//提供析构函数 释放3个电脑零件
~Computer()
{
if (m_cpu != NULL)
{
delete m_cpu;
m_cpu = NULL;
}
if (m_vc != NULL)
{
delete m_vc;
m_vc = NULL;
}
if (m_mem != NULL)
{
delete m_mem;
m_mem = NULL;
}
}
private:
CPU* m_cpu; //CPU的零件指针
VideoCard* m_vc; //显卡零件指针
Memory* m_mem; //内存条零件指针
};
//具体厂商
//Intel厂商
class IntelCPU : public CPU
{
public:
virtual void calculate()
{
cout << "Intel的CPU开始计算了" << endl;
}
};
class IntelVideoCard : public VideoCard
{
public:
virtual void display()
{
cout << "Intel的显卡开始计算了" << endl;
}
};
class IntelMemory : public Memory
{
public:
virtual void storage()
{
cout << "Intel的内存条开始存储了" << endl;
}
};
//Lenovo厂商
class LenovoCPU : public CPU
{
public:
virtual void calculate()
{
cout << "Lenovo的CPU开始计算了" << endl;
}
};
class LenovoVideoCard : public VideoCard
{
public:
virtual void display()
{
cout << "Lenovo的显卡开始计算了" << endl;
}
};
class LenovoMemory : public Memory
{
public:
virtual void storage()
{
cout << "Lenovo的内存条开始存储了" << endl;
}
};
void test01()
{
//第一台电脑零件
CPU* intelCpu = new IntelCPU;
VideoCard* intelCard = new IntelVideoCard;
Memory* intelMem = new IntelMemory;
cout << "第一台电脑开始工作:" << endl;
//创建第一台电脑
Computer* computer1 = new Computer(intelCpu, intelCard, intelMem);
computer1->work();
delete computer1;
cout << "---------" << endl;
cout << "第二台电脑开始工作:" << endl;
//创建第二台电脑
Computer* computer2 = new Computer(new LenovoCPU, new LenovoVideoCard, new LenovoMemory);
computer2->work();
delete computer2;
cout << "---------" << endl;
cout << "第三台电脑开始工作:" << endl;
//创建第三台电脑
Computer* computer3 = new Computer(new IntelCPU, new LenovoVideoCard, new LenovoMemory);
computer3->work();
delete computer3;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 第一台电脑开始工作:
- Intel的CPU开始计算了
- Intel的显卡开始计算了
- Intel的内存条开始存储了
- $---------$
- 第二台电脑开始工作:
- Lenovo的CPU开始计算了
- Lenovo的显卡开始计算了
- Lenovo的内存条开始存储了
- $---------$
- 第三台电脑开始工作:
- Intel的CPU开始计算了
- Lenovo的显卡开始计算了
- Lenovo的内存条开始存储了
- 请按任意键继续. . .

Binary file not shown.

After

Width:  |  Height:  |  Size: 1005 KiB

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,293 @@
# C++的文件操作
# 1. 文件操作简介
① 程序运行时产生的数据都属于临时数据,程序一旦运行结束都会被释放。
② 通过文件可以将数据持久化。
③ C++中对文件操作需要包含头文件<fstream>
④ 文件类型分为两种:
1. 文本文件文件以文本的ASCII码形式存储在计算机中。
2. 二进制文件:文件以文本的二进制形式存储在计算机中,用户一般不能直接读懂它们。
⑤ 操作文件的三大类
1. ofstream写操作
2. ifstream读操作
3. fstream读写操作
⑥ 文件打开方式可以配合使用,利用|操作符。
1. 例如,用二进制方式写文件 ios:: binary | ios:: out
![image.png](27_C++的文件操作_files/image.png)
# 2. 文本文件--写文件
① 写文件步骤如下:
1. 包含头文件 #include $<fstream>$
2. 创建流对象 ofstream ofs;
3. 打开文件 ofs.open("文件路径",打开方式);
4. 关闭文件 ofs<<"写入数据";
5. 关闭文件 ofs.close();
```python
#include <iostream>
using namespace std;
#include<fstream> //头文件包含
//文本文件 写文件
void test01()
{
//1、包含头文件 fstream
//2、创建流文件
ofstream ofs; //创建流对象
//3、指定打开方式
ofs.open("test.txt", ios::out); //当没有指定某盘路径时,创建的文件在该项目文件的路径下
//4、写内容
ofs << "姓名:张三" << endl;
ofs << "性别:男" << endl;
ofs << "年龄18" << endl;
//5、关闭文件
ofs.close();
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
![image.png](27_C++的文件操作_files/image.png)
# 3. 文本文件--读操作
① 读文件与写文件步骤相似,但是读取方式相对比较多。
② 读文件步骤如下:
1. 包含头文件 #include$<fstream>$
2. 创建流对象 ifstream ifs;
3. 打开文件并判断文件是否成功打开 ifs.open("文件路径",打开方式);
4. 四种方式读取
5. 关闭文件 ifs.close();
```python
#include <iostream>
using namespace std;
#include<fstream>
#include<string>
//文本文件 读文件
void test01()
{
//1、包含头文件 fstream
//2、创建流文件
ifstream ifs; //创建流对象
//3、打开文件并且判断是否打开成功
ifs.open("test.txt", ios::in);
if (!ifs.is_open())
{
cout << "文件打开失败" << endl;
return;
}
//4、读数据
/*
//第一种
char buf[1024] = { 0 }; //字符数组初始化全为0
while (ifs >> buf) //一行一行数据读存到buf里当读不到数据的时候返回False退出循环
{
cout << buf << endl;
}
*/
/*
//第二种
char buf[1024] = { 0 };
while (ifs.getline(buf, sizeof(buf))) //第一个参数为数据放到哪里(地址),第二个参数为最多要读多少个字节数
{
cout << buf << endl;
}
*/
/*
//第三种
string buf;
while (getline(ifs,buf))
{
cout << buf << endl;
}
*/
//第四种
char c;
while ((c = ifs.get()) != EOF) //每一次读取一个字符,字符放入c
{ //EOF表示读取到文件尾
cout << c;
}
//5、关闭文件
ifs.close();
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 姓名:张三
- 性别:男
- 年龄18
- 请按任意键继续. . .
# 4. 二进制文件--写文件
① 以二进制的方式对文件进行读、写操作,打开方式要指定为 ios::binary
② 二进制方式写文件主要利用流对象调用成员函数write函数原型ostream write(const char * buffer,int len)
③ 参数解释字符指针buffer指向内存中一段内存空间len是读写的字节数。
```python
#include <iostream>
using namespace std;
#include<fstream>
//二进制文件 写文件
class Person
{
public:
char m_Name[64]; //姓名
int m_Age; //年龄
//写字符串的时候最好不要用C++的string有可能出现问题最好用C的数组写字符串因为它底层是用C写的
};
void test01()
{
//1、包含头文件
//2、创建流文件
ofstream ofs;
//3、打开文件
ofs.open("person.txt", ios::out | ios::binary); //二进制的方式写文件
//ofstream ofs.open("person.txt",ios::out | ios::binary) 也可以两步合成一步
//4、写文件
Person p = { "张三",18 };
ofs.write((const char*)&p, sizeof(Person)); //对p取地址然后强转为常量指针
//5、关闭文件
ofs.close();
}
int main()
{
test01();
system("pause");
return 0;
}
```
![image.png](27_C++的文件操作_files/image.png)
# 5. 二进制文件--读文件
① 二进制方式读文件主要利用流对象调用成员函数read。
② 函数原型istream& read(char *buffer,int len);
③ 参数解释字符串buffer指向内存中一段内存空间len是读写的字节数。
```python
#include <iostream>
using namespace std;
#include<fstream>
//二进制文件 读文件
class Person
{
public:
char m_Name[64]; //姓名
int m_Age; //年龄
//写字符串的时候最好不要用C++的string有可能出现问题最好用C的数组写字符串因为它底层是用C写的
};
void test01()
{
//1、包含头文件
//2、创建流对象
ifstream ifs;
//3、打开文件
ifs.open("person.txt", ios::in | ios::binary); //二进制的方式读文件
if (!ifs.is_open())
{
cout << "文件打开失败" << endl;
return;
}
//4、写文件
Person p;
ifs.read((char*)&p, sizeof(Person));
cout << "姓名:" << p.m_Name << " 年龄" << p.m_Name << endl;
//5、关闭文件
ifs.close();
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 姓名:张三 年龄:张三
- 请按任意键继续. . .

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

View File

@ -0,0 +1,176 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的函数对象"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 基本概念"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 重载函数调用操作符的类,其对象常称为函数对象。\n",
"\n",
"② 函数对象使用重载的()时,行为类似函数调用,也叫仿函数。\n",
"\n",
"③ 函数对象(仿函数)是一个类,不是一个函数。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 2. 特点"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 函数对象在使用时,可以像普通函数那样调用,可以有参数。\n",
"\n",
"② 函数对象超出普通函数的概念,函数对象可以有自己的状态。\n",
"\n",
"③ 函数对象可以作为参数传递。\n",
"\n",
"④ 仿函数写法是非常灵活的,可以作为参数进行传递。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include<iostream>\n",
"using namespace std;\n",
"\n",
"class MyAdd\n",
"{\n",
"public:\n",
" int operator()(int v1, int v2)\n",
" {\n",
" return v1 + v2;\n",
" }\n",
"};\n",
"\n",
"//1、函数对象在使用时可以像普通函数那样调用可以有参数可以有返回值\n",
"void test01()\n",
"{\n",
" MyAdd myAdd;\n",
" cout << myAdd(10,10) << endl;\n",
"}\n",
"\n",
"//2、函数对象超出普通函数的概念函数对象可以有自己的状态\n",
"class MyPrint\n",
"{\n",
"public:\n",
" MyPrint()\n",
" {\n",
" this->count = 0;\n",
" }\n",
"\n",
" void operator()(string test)\n",
" {\n",
" cout << test << endl;\n",
" this->count++;\n",
" }\n",
" int count; //内部自己状态\n",
"};\n",
"\n",
"void test02()\n",
"{\n",
" MyPrint myPrint;\n",
" myPrint(\"hellow world\");\n",
" myPrint(\"hellow world\");\n",
" myPrint(\"hellow world\");\n",
" myPrint(\"hellow world\");\n",
"\n",
" cout << \"myPrint调用次数为\" << myPrint.count << endl;\n",
"}\n",
"\n",
"//3、函数对象可以作为参数传递\n",
"\n",
"void doPrint(MyPrint &mp, string test)\n",
"{\n",
" mp(test);\n",
"}\n",
"\n",
"void test03()\n",
"{\n",
" MyPrint myPrint;\n",
" doPrint(myPrint,\"hellow world\");\n",
"}\n",
"\n",
"int main() \n",
"{\n",
" test01();\n",
" test02();\n",
" test03();\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果:\n",
" - 20\n",
" - hellow world\n",
" - hellow world\n",
" - hellow world\n",
" - hellow world\n",
" - myPrint调用次数为4\n",
" - hellow world\n",
" - 请按任意键继续. . ."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,103 @@
# C++的函数对象
# 1. 基本概念
① 重载函数调用操作符的类,其对象常称为函数对象。
② 函数对象使用重载的()时,行为类似函数调用,也叫仿函数。
③ 函数对象(仿函数)是一个类,不是一个函数。
# 2. 特点
① 函数对象在使用时,可以像普通函数那样调用,可以有参数。
② 函数对象超出普通函数的概念,函数对象可以有自己的状态。
③ 函数对象可以作为参数传递。
④ 仿函数写法是非常灵活的,可以作为参数进行传递。
```python
#include<iostream>
using namespace std;
class MyAdd
{
public:
int operator()(int v1, int v2)
{
return v1 + v2;
}
};
//1、函数对象在使用时可以像普通函数那样调用可以有参数可以有返回值
void test01()
{
MyAdd myAdd;
cout << myAdd(10,10) << endl;
}
//2、函数对象超出普通函数的概念函数对象可以有自己的状态
class MyPrint
{
public:
MyPrint()
{
this->count = 0;
}
void operator()(string test)
{
cout << test << endl;
this->count++;
}
int count; //内部自己状态
};
void test02()
{
MyPrint myPrint;
myPrint("hellow world");
myPrint("hellow world");
myPrint("hellow world");
myPrint("hellow world");
cout << "myPrint调用次数为" << myPrint.count << endl;
}
//3、函数对象可以作为参数传递
void doPrint(MyPrint &mp, string test)
{
mp(test);
}
void test03()
{
MyPrint myPrint;
doPrint(myPrint,"hellow world");
}
int main()
{
test01();
test02();
test03();
system("pause");
return 0;
}
```
运行结果:
- 20
- hellow world
- hellow world
- hellow world
- hellow world
- myPrint调用次数为4
- hellow world
- 请按任意键继续. . .

View File

@ -0,0 +1,210 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的谓词"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 简介"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 返回bool类型的仿函数称为谓词。\n",
"\n",
"② 如果operator()接受一个参数,那么叫做一元谓词。\n",
"\n",
"③ 如果operator()接受两个参数,那么叫做二元谓词。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 2. 一元谓词"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include<iostream>\n",
"using namespace std;\n",
"#include<vector>\n",
"#include<algorithm>\n",
"\n",
"//仿函数 返回值类型是bool数据类型称为谓词\n",
"//一元谓词\n",
"class GreaterFive\n",
"{\n",
"public:\n",
" bool operator()(int val)\n",
" {\n",
" return val > 5;\n",
" }\n",
"};\n",
"\n",
"void test01()\n",
"{\n",
" vector<int>v;\n",
" for (int i = 0; i < 10; i++)\n",
" {\n",
" v.push_back(i);\n",
" }\n",
"\n",
" //查找容器中有没有大于5的数字\n",
" //GreaterFive() 匿名函数对象\n",
" vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive());\n",
" if (it == v.end())\n",
" {\n",
" cout << \"未找到\" << endl;\n",
" }\n",
" else\n",
" {\n",
" cout << \"找到大于5的数字为\" << *it << endl;\n",
" }\n",
"}\n",
"\n",
"int main() \n",
"{\n",
" test01();\n",
" \n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 找到大于5的数字为6\n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 3. 二元谓词"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include<iostream>\n",
"using namespace std;\n",
"#include<vector>\n",
"#include<algorithm>\n",
"\n",
"//仿函数 返回值类型是bool数据类型称为谓词\n",
"//二元谓词\n",
"class MyCompare\n",
"{\n",
"public:\n",
" bool operator()(int val1,int val2)\n",
" {\n",
" return val1 > val2;\n",
" }\n",
"};\n",
"\n",
"void test01()\n",
"{\n",
" vector<int>v;\n",
" v.push_back(10);\n",
" v.push_back(40);\n",
" v.push_back(50);\n",
" v.push_back(20);\n",
" v.push_back(30);\n",
"\n",
" sort(v.begin(), v.end());\n",
" for (vector<int>::iterator it = v.begin(); it != v.end(); it++)\n",
" {\n",
" cout << *it << \" \";\n",
" }\n",
" cout << endl;\n",
"\n",
" //使用函数对象,改变算法策略,变为排序规则为从大到小\n",
" sort(v.begin(), v.end(), MyCompare()); //MyCompare()为函数对象,是匿名函数\n",
"\n",
" cout << \"----\" << endl;\n",
" for (vector<int>::iterator it = v.begin(); it != v.end(); it++)\n",
" {\n",
" cout << *it << \" \";\n",
" }\n",
" cout << endl;\n",
"}\n",
"\n",
"int main() {\n",
"\n",
" test01();\n",
"\n",
" system(\"pause\");\n",
" \n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果: \n",
" - 10 20 30 40 50\n",
" - $----$\n",
" - 50 40 30 20 10\n",
" - 请按任意键继续. . ."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,128 @@
# C++的谓词
# 1. 简介
① 返回bool类型的仿函数称为谓词。
② 如果operator()接受一个参数,那么叫做一元谓词。
③ 如果operator()接受两个参数,那么叫做二元谓词。
# 2. 一元谓词
```python
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
//仿函数 返回值类型是bool数据类型称为谓词
//一元谓词
class GreaterFive
{
public:
bool operator()(int val)
{
return val > 5;
}
};
void test01()
{
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//查找容器中有没有大于5的数字
//GreaterFive() 匿名函数对象
vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive());
if (it == v.end())
{
cout << "未找到" << endl;
}
else
{
cout << "找到大于5的数字为" << *it << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 找到大于5的数字为6
- 请按任意键继续. . .
# 3. 二元谓词
```python
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
//仿函数 返回值类型是bool数据类型称为谓词
//二元谓词
class MyCompare
{
public:
bool operator()(int val1,int val2)
{
return val1 > val2;
}
};
void test01()
{
vector<int>v;
v.push_back(10);
v.push_back(40);
v.push_back(50);
v.push_back(20);
v.push_back(30);
sort(v.begin(), v.end());
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
//使用函数对象,改变算法策略,变为排序规则为从大到小
sort(v.begin(), v.end(), MyCompare()); //MyCompare()为函数对象,是匿名函数
cout << "----" << endl;
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main() {
test01();
system("pause");
return 0;
}
```
运行结果:
- 10 20 30 40 50
- $----$
- 50 40 30 20 10
- 请按任意键继续. . .

View File

@ -0,0 +1,335 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# C++的内建函数对象"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 1. 内建函数对象"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① STL内建来了一些函数对象\n",
"\n",
"1. 算术仿函数\n",
"2. 关系仿函数\n",
"3. 逻辑仿函数\n",
"\n",
"② 用法:\n",
"\n",
"1. 这些仿函数所产生的对象,用法和一般函数完全相同。\n",
"2. 使用内建函数对象,需要引入头文件 #include<functional>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 2. 算术仿函数"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 功能描述:实现四则运算。\n",
"\n",
"② 其中negate是一元运算其他都是二元运算。\n",
"\n",
"③ 仿函数原型:\n",
"\n",
"1. $template<class T> T plus<T>$ //加法仿函数\n",
"2. $template<class T> T minus<T>$ //减法仿函数\n",
"3. $template<class T> T multiplies<T>$ //乘法仿函数\n",
"4. $template<class T> T divides<T>$ //除法仿函数\n",
"5. $template<class T> T modulus<T>$ //取模仿函数\n",
"6. $template<class T> T negate<T>$ //取反仿函数\n",
"\n",
"④ 使用内建函数对象时,需要引入头文件#include <functional>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include<iostream>\n",
"using namespace std;\n",
"#include<functional> //内建函数对象头文件\n",
"\n",
"//内建函数对象 算术仿函数\n",
"\n",
"//negate 一元仿函数 取反仿函数\n",
"void test01()\n",
"{\n",
" negate<int>n;\n",
"\n",
" cout << n(50) << endl;\n",
"}\n",
"\n",
"//plus 二元仿函数 加法\n",
"void test02()\n",
"{\n",
" plus<int>p; //写一个int就好了不用写两个int它默认是两个同类型的int相加\n",
"\n",
" cout << p(50,60) << endl;\n",
"}\n",
"\n",
"int main() {\n",
"\n",
" test01();\n",
" test02();\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果:\n",
" - -50\n",
" - 110\n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 3. 关系仿函数"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 功能描述:实现关系对比。\n",
"\n",
"② 仿函数原型: \n",
"\n",
"1. $template<class T> bool equal_to<T>$ //等于\n",
"2. $template<class T> bool notequal_to<T>$ //不等于\n",
"3. $template<>class T> bool greater<T>$ //大于\n",
"4. $template<class T> bool greater_qual<T>$ //大于等于\n",
"5. $template<class T> bool less<T>$ //小于\n",
"6. $template<class T>bool less_equal<T>$ //小于等于 \n",
"\n",
"③ 关系仿函数中最常用的就是greater<>大于。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include<iostream>\n",
"using namespace std;\n",
"#include<functional> //内建函数对象头文件\n",
"#include<vector>\n",
"#include<algorithm>\n",
"\n",
"\n",
"//内建函数对象 关系仿函数\n",
"//大于 greater\n",
"class MyCompare\n",
"{\n",
" bool operator()(int v1, int v2)\n",
" {\n",
" return v1 > v2;\n",
" }\n",
"};\n",
"\n",
"void test01()\n",
"{\n",
" vector<int>v;\n",
"\n",
" v.push_back(10);\n",
" v.push_back(20);\n",
" v.push_back(30);\n",
" v.push_back(40);\n",
" v.push_back(50);\n",
"\n",
" for (vector<int>::iterator it = v.begin();it!=v.end();it++)\n",
" {\n",
" cout << *it << \" \";\n",
" }\n",
" cout << endl;\n",
"\n",
" //降序\n",
" \n",
" //方式一:\n",
" //sort(v.begin(), v.end(), MyCompare());\n",
" \n",
" //方式二:\n",
" sort(v.begin(), v.end(), greater<int>()); //greater<int>()为编译器给提供的函数对象,为内建的函数对象\n",
"\n",
" for (vector<int>::iterator it = v.begin(); it != v.end(); it++)\n",
" {\n",
" cout << *it << \" \";\n",
" }\n",
" cout << endl;\n",
"}\n",
"\n",
"int main() {\n",
"\n",
" test01();\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果:\n",
" - 10 20 30 40 50\n",
" - 50 40 30 20 10\n",
" - 请按任意键继续. . ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 4. 逻辑仿函数"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"① 功能描述:实现关系对比\n",
"\n",
"② 仿函数原型:\n",
"\n",
"1. $template<class T> bool logical_and<T>$ //逻辑与\n",
"2. $template<class T> bool logical_or<T>$ //逻辑或\n",
"3. $template<class T> bool logical_not<T>$ //逻辑非\n",
"\n",
"③ 逻辑仿函数实际应用较少,了解即可。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include<iostream>\n",
"using namespace std;\n",
"#include<functional> //内建函数对象头文件\n",
"#include<vector>\n",
"#include<algorithm>\n",
"\n",
"\n",
"//内建函数对象 逻辑仿函数\n",
"//逻辑非 logical_not\n",
"\n",
"void test01()\n",
"{\n",
" vector<bool>v;\n",
"\n",
" v.push_back(true);\n",
" v.push_back(false);\n",
" v.push_back(true);\n",
" v.push_back(true);\n",
" v.push_back(false);\n",
"\n",
" for (vector<bool>::iterator it = v.begin();it!=v.end();it++)\n",
" {\n",
" cout << *it << \" \";\n",
" }\n",
" cout << endl;\n",
"\n",
" //利用逻辑非 将容器v 搬运到 容器v2中并执行取反操作\n",
" vector<bool>v2;\n",
" v2.resize(v.size()); //目标容器要提前开辟一个空间\n",
"\n",
" transform(v.begin(),v.end(),v2.begin(),logical_not<bool>()); //第一个参数:原容器起始迭代器,第二个参数:原容器终止迭代器,第三个参数:目标容器起始迭代器\n",
"\n",
" for (vector<bool>::iterator it = v2.begin(); it != v2.end(); it++)\n",
" {\n",
" cout << *it << \" \";\n",
" }\n",
" cout << endl;\n",
"}\n",
"\n",
"\n",
"\n",
"int main() {\n",
"\n",
" test01();\n",
"\n",
" system(\"pause\");\n",
"\n",
" return 0;\n",
"\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"运行结果:\n",
" - 1 0 1 1 0\n",
" - 0 1 0 0 1\n",
" - 请按任意键继续. . ."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.6.3",
"language": "python",
"name": "python3.6.3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@ -0,0 +1,224 @@
# C++的内建函数对象
# 1. 内建函数对象
① STL内建来了一些函数对象
1. 算术仿函数
2. 关系仿函数
3. 逻辑仿函数
② 用法:
1. 这些仿函数所产生的对象,用法和一般函数完全相同。
2. 使用内建函数对象,需要引入头文件 #include<functional>
# 2. 算术仿函数
① 功能描述:实现四则运算。
② 其中negate是一元运算其他都是二元运算。
③ 仿函数原型:
1. $template<class T> T plus<T>$ //加法仿函数
2. $template<class T> T minus<T>$ //减法仿函数
3. $template<class T> T multiplies<T>$ //乘法仿函数
4. $template<class T> T divides<T>$ //除法仿函数
5. $template<class T> T modulus<T>$ //取模仿函数
6. $template<class T> T negate<T>$ //取反仿函数
④ 使用内建函数对象时,需要引入头文件#include <functional>
```python
#include<iostream>
using namespace std;
#include<functional> //内建函数对象头文件
//内建函数对象 算术仿函数
//negate 一元仿函数 取反仿函数
void test01()
{
negate<int>n;
cout << n(50) << endl;
}
//plus 二元仿函数 加法
void test02()
{
plus<int>p; //写一个int就好了不用写两个int它默认是两个同类型的int相加
cout << p(50,60) << endl;
}
int main() {
test01();
test02();
system("pause");
return 0;
}
```
运行结果:
- -50
- 110
- 请按任意键继续. . .
# 3. 关系仿函数
① 功能描述:实现关系对比。
② 仿函数原型:
1. $template<class T> bool equal_to<T>$ //等于
2. $template<class T> bool notequal_to<T>$ //不等于
3. $template<>class T> bool greater<T>$ //大于
4. $template<class T> bool greater_qual<T>$ //大于等于
5. $template<class T> bool less<T>$ //小于
6. $template<class T>bool less_equal<T>$ //小于等于
③ 关系仿函数中最常用的就是greater<>大于。
```python
#include<iostream>
using namespace std;
#include<functional> //内建函数对象头文件
#include<vector>
#include<algorithm>
//内建函数对象 关系仿函数
//大于 greater
class MyCompare
{
bool operator()(int v1, int v2)
{
return v1 > v2;
}
};
void test01()
{
vector<int>v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(50);
for (vector<int>::iterator it = v.begin();it!=v.end();it++)
{
cout << *it << " ";
}
cout << endl;
//降序
//方式一:
//sort(v.begin(), v.end(), MyCompare());
//方式二:
sort(v.begin(), v.end(), greater<int>()); //greater<int>()为编译器给提供的函数对象,为内建的函数对象
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main() {
test01();
system("pause");
return 0;
}
```
运行结果:
- 10 20 30 40 50
- 50 40 30 20 10
- 请按任意键继续. . .
# 4. 逻辑仿函数
① 功能描述:实现关系对比
② 仿函数原型:
1. $template<class T> bool logical_and<T>$ //逻辑与
2. $template<class T> bool logical_or<T>$ //逻辑或
3. $template<class T> bool logical_not<T>$ //逻辑非
③ 逻辑仿函数实际应用较少,了解即可。
```python
#include<iostream>
using namespace std;
#include<functional> //内建函数对象头文件
#include<vector>
#include<algorithm>
//内建函数对象 逻辑仿函数
//逻辑非 logical_not
void test01()
{
vector<bool>v;
v.push_back(true);
v.push_back(false);
v.push_back(true);
v.push_back(true);
v.push_back(false);
for (vector<bool>::iterator it = v.begin();it!=v.end();it++)
{
cout << *it << " ";
}
cout << endl;
//利用逻辑非 将容器v 搬运到 容器v2中并执行取反操作
vector<bool>v2;
v2.resize(v.size()); //目标容器要提前开辟一个空间
transform(v.begin(),v.end(),v2.begin(),logical_not<bool>()); //第一个参数:原容器起始迭代器,第二个参数:原容器终止迭代器,第三个参数:目标容器起始迭代器
for (vector<bool>::iterator it = v2.begin(); it != v2.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main() {
test01();
system("pause");
return 0;
}
```
运行结果:
- 1 0 1 1 0
- 0 1 0 0 1
- 请按任意键继续. . .

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

View File

@ -0,0 +1,180 @@
# 最全面的 C++ 笔记
笔记视频:
视频讲解【主讲方:黑马程序员】
1. https://www.bilibili.com/video/BV1et411b73Z?p=1
-------------------------------------------------------------
-------------------------------------------------------------
笔记备注:
1. 在线观看笔记时有时会出现图片或公式显示不完整这是Github网站没有解析好笔记下载到本地观看就正常了。不会下载笔记的百度查一下"Github如何下载文件"。)
2. Pycharm 的 Jupyter Notebook 打开笔记时,图片不会正常显示,笔记是用 Anaconda 的 Jupyter Notebook 打开的。(不会打开笔记的,百度查一下"Anaconda如何打开Jupyter Notebook文件"或者我的主页Python仓库里面"00_Python编辑器"里面有写。)
3. 安装 Jupyter Notebook 的目录插件,可以快速通过目录,跳转到相应的章节,如下图所示。(不会安装目录的,百度查一下"Jupyter Notebook如何安装目录"或者我的主页Python仓库里面"00_Python编辑器"里面有相关链接。)
补充说明C++代码我是在VS2019中运行的Jupyter Notebook仅是笔记文档。
![image](https://user-images.githubusercontent.com/60348867/199900750-6ee1becc-d5ce-49ac-81e9-83d4e276114f.png)
-------------------------------------------------------------
-------------------------------------------------------------
更多笔记:
我的Github主页还有其他优秀视频的笔记希望能帮助到你~
1. https://github.com/AccumulateMore
我的哔哩哔哩, 大模型、多模态笔记【手把手教你做科研 更新ing】希望能帮助到你~
1. https://www.bilibili.com/video/BV1xM4m1m7vA/?spm_id_from=333.999.0.0&vd_source=c9745e4447536b28b2b0735071d30bd6
"♥我的笔记,希望对你有帮助♥"
♥小声哔哔你的star是我更新的动力~♥
-------------------------------------------------------------
-------------------------------------------------------------
搭建交流群,帮助孤单的自学者交流
| 【深度学习 学习交流①群】 | 【深度学习 学习交流②群】 | 微信 |
| -------- | -------- | -------- |
| ![312f346ad393a2f617f21da7ffec9d8](https://github.com/AccumulateMore/CV/assets/60348867/c99750a2-89c0-45ed-bf42-e8f63a222d60)<br/> | ![2f44c2648aaf04f393162501e9e4e0a](https://github.com/AccumulateMore/CV/assets/60348867/d6c44e7b-8349-4de3-b91b-ed62ee7c1544)<br/> | ![2297947b9d8b74a0f219e8d3287a131](https://github.com/user-attachments/assets/a853bda5-16e6-4944-96af-d061172bdabc)<br> |
超过200人扫码入群方式失效只能微信好友邀请入群。
看人之短,无一可交之人。看人之长,天下皆是吾师。
备注:好友申请时,声明目的,需要什么
| 备注 | 备注 | 备注 |
| -------------------- | -------- | -------- |
| 需要论文辅导研0研1免费半年掌握三年知识<br/> | 要进学习交流群<br/> | 要数据集<br> |
| 需要学习指导指数级学习快速拿到offer<br/> | 需要实习(可开实习证明)<br/> | ......<br> |
| 需要商业级项目快速从0到1简历增添项目<br/> | 指导改简历(从面试官角度出发)<br/> | ......<br> |
-------------------------------------------------------------
-------------------------------------------------------------
帮你们就业,有意向的可以投简历
备注:初学者也可以根据市场上就业需求,去学习自己。
联影医疗 地点(可选):上海、北京、深圳、武汉、广州、成都、西安、沈阳、三亚等
内推人:联影老员工
岗位职责【图像方向】:
参与联影集团产品的AI算法开发工作或图形算法开发工作负责下列至少一项工作
1. 负责提供产品级高端算法解决方案包括联影通用软件平台、联影高级应用后处理工作站、联影智能uAl平台、联影机器人手术规划与导航、MR/CT/RT/MI/US事业部的算法需求、科研院所和医院的前瞻性研究项目等参与创新技术的产品化工作。
2. 医学图像3D渲染算法和应用维护与开发利用图像处理和人工智能技术从事医学图像处理领域相关算法的设计和研发。
任职要求:
1. 熟悉机器视觉原理熟悉以下领域之一3D重建、立体视觉、SLAM、通用图像视频分类、目标检测、人体姿态估计。
2. 熟悉以下医学图像后处理算法之一:图形算法、重建算法、分割算法、检测算法、分类算法、配准算法、深度学习算法、流体力学算法、灌注算法、纹理分析算法等。
岗位职责【语音方向】:
1. 负责音频信号处理和识别相关算法的研究和实现,包含但不限于回声消除、麦克风阵列、盲源分离等技术。
2. 负责深度学习、神经网络等AI音频算法的研究和实现。
任职要求:
1. 扎实的数学理论及数字信号处理基础掌握Matlab及C/C++语言编程。
2. 有语音、音频信号处理(降噪,回声消除、麦阵、音效等)相关经验。
3. 有深度学习、神经网络、智能语音识别相关研究。
岗位职责【大模型方向】:
1. 负责大语言模型方面的算法开发、优化、应用落地。
2. 负责相应AI解决方案设计参与关键技术研发攻关技术难点。
3. 负责设计和实现大语言模型相关的算法和模型实现,研究并设计新是算法和模型,解决大语言模型应用问题。
4. 负责开发和优化大语言模型的训练过程,设计并实现大语言模型的训练算法和策略,配置和优化训练的超参数和计算资源,保证模型的训练效果和效率。
5. 负责构建和管理大规模医疗文本数据集,用于模型预训练和微调,完成不用场景下的下游任务。
6. 负责进行大语言模型的评估和验证,设计评估指标和实验;设计和实施评估指标和实验,对训练好的大语言模型进行性能评估和分析。识别模型的弱点和改进空间,提出相应的改进策略和方法。
7. 参与高校、科研、医疗机构科研合作,协助科研成果落地转化。
任职要求:
1. 具有机器学习、自然语言处理、医学影像分析,或相关领域的学习和研究。
2. 有预训练大语言模型或GPT模型等相关研究开发经验。
3. 在机器学习(ICMLNeurlPS、ICLR等)、计算机视觉(CVPR、ICCV、ECCV等)、自然语言处理(ACLEMNLP等)和医疗影像分析(MICCAI、IPMI)等顶级会议,或者顶级期刊(IEEE T-PAMIIEEE TMI、Medical lmage Analysis)发表过相关论文。
4. 具有人工智能相关专业(计算机视觉、机器学习、医疗图像分析等)硕士及以上学位。
5. 能熟练使用英语。
补充能内推简历的也可以联系我把岗位职责、任职要求发给我【你收公司内推奖金、ta们就业双赢】。
-------------------------------------------------------------
-------------------------------------------------------------
想学习商业级项目的,下面商业级项目可以学习,与大量求职者卷一卷,提高核心竞争力。
| 商业项目 | 商业项目 | 商业项目 | 商业项目 |
| -------------------- | -------- | -------- | -------- |
| 人脸识别与管理系统<br/> | 车牌识别与管理系统<br/> | 手势识别系统<br/> | 人脸面部活体检测系统<br> |
| 目标检测与自动标注系统<br/> | 人脸表情识别系统<br/> | 行人跌倒检测系统<br/> | PCB板缺陷检测系统<br> |
| 安全帽检测系统<br/> | 生活垃圾分类系统<br/> | 火焰烟雾检测系统<br/> | 路面坑洞检测系统<br> |
| 钢材表面缺陷检测系统<br/> | 肺炎诊断系统<br/> | 面部口罩检测系统<br/> | 西红柿成熟度检测系统<br> |
| 血细胞检测计数系统<br/> | 舰船分类检测系统<br/> | 吸烟行为检测系统<br/> | 水稻害虫检测系统<br> |
| 交通标志检测系统<br/> | 行人追踪计数系统<br/> | 车辆追踪计数系统<br/> | 脑肿瘤检测系统<br> |
| 无人机视角检测系统<br/> | 裂缝检测分析系统<br/> | 水下海生物检测系统<br/> | 草莓成熟度检测系统<br> |
| 条形码检测系统<br/> | 交通信号灯检测系统<br/> | 金属品瑕疵检测系统<br/> | 链条缺陷检测系统<br> |
| 螺栓螺母检测系统<br/> | 焊缝缺陷检测系统<br/> | 蛀牙检测识别系统<br/> | 非机动车头盔检测系统<br> |
| 水果检测识别系统<br/> | 蔬菜检测系统<br/> | 高密度人脸检测系统<br/> | 肾结石检测系统<br> |
| 反光衣检测预警系统<br/> | 人员闯入报警系统<br/> | 玉米病害检测系统<br/> | 橙子病害识别系统<br> |
| 木薯病害识别预防系统<br/> | 野火烟雾检测系统<br/> | 路面坑洞检测分割系统<br/> | 遥感地面物体检测系统<br> |
| 田间杂草检测系统<br/> | 葡萄病害识别系统<br/> | 车牌检测识别系统<br/> | 草莓病害检测分割系统<br> |
| 车辆行人追踪系统<br/> | 水稻病害识别系统<br/> | 中草药识别系统<br/> | 车辆行人检测系统<br> |
| 条形码识别系统<br/> | 交通信号灯识别系统<br/> | 水下海生物检测系统<br/> | 交通事故检测系统<br> |
| 安检危险品检测系统<br/> | 农作物检测系统<br/> | 危险驾驶行为检测系统<br/> | 维修工具检测系统<br> |
| 建筑墙面损伤检测系统<br/> | 煤矿传送带异物检测系统<br/> | 老鼠智能检测系统<br/> | 水面垃圾检测系统<br> |
| 遥感视角船只检测系统<br/> | 胃肠道息肉检测系统<br/> | 心脏间隔壁分割系统<br/> | 半导体芯片缺陷检测系统<br> |
| 视网膜疾病诊断系统<br/> | 运动鞋品牌识别系统<br/> | X光骨折检测系统<br/> | 遥感视角农田分割系统<br> |
| 电瓶车进电梯检测系统<br/> | 遥感视角房屋分割系统<br/> | CT肺结节检测系统<br/> | 舌苔舌像诊断系统<br> |
| 输电线路设备检测系统<br/> | 零售柜商品识别系统<br/> | 远距离停车位检测系统<br/> | 安全帽检测系统<br> |
| 机场航拍小目标检测系统<br/> | 景区垃圾识别系统<br/> | 快递包裹检测系统<br/> | 无人机目标检测系统<br> |
| 疲劳驾驶检测系统<br/> | 布匹缺陷检测系统<br/> | 夜视行人检测系统<br/> | 教研人员检测与计数系统<br> |
-------------------------------------------------------------
-------------------------------------------------------------
2021年我硕士毕业时【简历】技能书写可以借鉴
![image](https://github.com/user-attachments/assets/13ce32b7-112d-4037-8abc-d2a8fa420730)
用了几个技巧,分享给大家:
1. 技能只写掌握了XX没掌握不要写掌握且更熟练的放前面掌握但不熟练的放后面。
2. 写掌握某项技能时,后面要论证自己真的掌握了,提供相关经历,方便面试官切入询问。
3. 围绕算法岗展开技能阐述,从编程语言、到深度学习框架、到图像处理算法、服务器数据库存储图像等。
4. 只写岗位需要的技能,与算法岗不需要的硬件知识、组织能力等不要写,让简历更高匹配算法岗。
5. 掌握一种类别技能,只占一行,不要有的两行、有的一行,看着不整齐。
6. 面试官及HR会看着感觉整齐、可信、岗位匹配度高。
要知道很多大公司HR经常一天要看几百份甚至上千份简历基本都是10秒内看一份简历。
就是这关键的10秒HR就决定了是进入面试还是PASS。
我已经指导过上千位同学,即使市场大环境不好,很多同学都入职各家公司成功了。
| 金九 内推第一名 | 银十 内推第一名 | 2024内推第一名 |
| ------ | ------ | ------ |
| ![eda6e9ca0f5ae0ca9da1dd193e17306](https://github.com/user-attachments/assets/e2f38221-3112-4c28-bf96-fa86fd82aa72)<br/>|![21ad65da6049aed8a878b5f5c011d7a](https://github.com/user-attachments/assets/c5316cb3-0943-46a0-8c2d-8aed86ff5149)<br/> | ![7849d9a28b4242737194a6d3e685688](https://github.com/user-attachments/assets/f3c9ac1b-f13a-401e-85bd-e87768272b39)<br> |
一起沾沾喜气,好运是可以传染的~
个人经验拿offer最快的方式就是不走弯路在少量的时间积累大量技能。
(不要等到火烧眉毛,再来找我抢救.......
-------------------------------------------------------------
-------------------------------------------------------------
"♥我们读书是为了成为提灯人去照亮黑暗,而不是为了自己有灯而沾沾自喜还要去吹灭别人的蜡烛♥"

View File

@ -0,0 +1,11 @@
import os
# 设置要扫描的根目录
root_dir = "../CPlusPlus-main"
# 遍历目录并输出所有文件
for root, dirs, files in os.walk(root_dir):
for file in files:
name_without_ext = os.path.splitext(file)[0]
rel_path = os.path.join(root, file).replace("\\", "/") # 统一路径格式为 Unix 风格
print(f"- {name_without_ext}: {rel_path}")

36
docs/脚本/转成md.py Normal file
View File

@ -0,0 +1,36 @@
import os
import subprocess
def convert_ipynb_to_md(root_dir, output_dir=None):
for root, dirs, files in os.walk(root_dir):
for file in files:
if file.endswith(".ipynb"):
ipynb_path = os.path.join(root, file)
print(f"正在转换: {ipynb_path}")
if output_dir:
# 指定输出目录(保留子目录结构)
rel_path = os.path.relpath(root, root_dir)
full_output_dir = os.path.join(output_dir, rel_path)
os.makedirs(full_output_dir, exist_ok=True)
cmd = [
"jupyter", "nbconvert", "--to", "markdown",
ipynb_path, "--output-dir", full_output_dir
]
else:
# 输出到原目录
cmd = [
"jupyter", "nbconvert", "--to", "markdown",
ipynb_path
]
subprocess.run(cmd)
# ✅ 用法:修改下面两个路径
source_folder = "../CPlusPlus-main" # ← 你的.ipynb源目录
markdown_output_folder = None # ← 设置为 None 表示输出在原目录下
# markdown_output_folder = "docs_md" # ← 设置输出目录
convert_ipynb_to_md(source_folder, markdown_output_folder)

View File

@ -1,5 +0,0 @@
import os
import subprocess
# 运行 mkdocs serve 命令
subprocess.run(['mkdocs', 'serve'])

View File

@ -54,6 +54,40 @@ nav:
- 第十七章 标准库特殊设施: Cpp-Notes-main/Cpp-Primer/17.标准库特殊设施.md - 第十七章 标准库特殊设施: Cpp-Notes-main/Cpp-Primer/17.标准库特殊设施.md
- 第十八章 用于大型程序的工具: Cpp-Notes-main/Cpp-Primer/18.用于大型程序的工具.md - 第十八章 用于大型程序的工具: Cpp-Notes-main/Cpp-Primer/18.用于大型程序的工具.md
- 第十九章 特殊工具与技术: Cpp-Notes-main/Cpp-Primer/19.特殊工具与技术.md - 第十九章 特殊工具与技术: Cpp-Notes-main/Cpp-Primer/19.特殊工具与技术.md
- CPlusPlus:
- 01_C++的注释: CPlusPlus-main/01_C++的注释.md
- 02_C++的main函数: CPlusPlus-main/02_C++的main函数.md
- 03_C++的打印: CPlusPlus-main/03_C++的打印.md
- 04_C++的常量: CPlusPlus-main/04_C++的常量.md
- 05_C++的变量: CPlusPlus-main/05_C++的变量.md
- 06_C++的关键字: CPlusPlus-main/06_C++的关键字.md
- 07_C++的标识符: CPlusPlus-main/07_C++的标识符.md
- 08_C++的数据类型: CPlusPlus-main/08_C++的数据类型.md
- 09_C++的转义字符: CPlusPlus-main/09_C++的转义字符.md
- 10_C++的数据输入: CPlusPlus-main/10_C++的数据输入.md
- 11_C++的运算符: CPlusPlus-main/11_C++的运算符.md
- 12_C++的程序流程结构: CPlusPlus-main/12_C++的程序流程结构.md
- 13_C++的数组: CPlusPlus-main/13_C++的数组.md
- 14_C++的函数: CPlusPlus-main/14_C++的函数.md
- 15_C++的指针: CPlusPlus-main/15_C++的指针.md
- 16_C++的结构体: CPlusPlus-main/16_C++的结构体.md
- 17_C++的内存模型: CPlusPlus-main/17_C++的内存模型.md
- 18_C++的引用: CPlusPlus-main/18_C++的引用.md
- 19_C++的面向对象: CPlusPlus-main/19_C++的面向对象.md
- 20_C++的类中封装: CPlusPlus-main/20_C++的类中封装.md
- 21_C++的调用其他类: CPlusPlus-main/21_C++的调用其他类.md
- 22_C++的类中特性: CPlusPlus-main/22_C++的类中特性.md
- 23_C++的类中友元: CPlusPlus-main/23_C++的类中友元.md
- 24_C++的类中运算符重载: CPlusPlus-main/24_C++的类中运算符重载.md
- 25_C++的类中继承: CPlusPlus-main/25_C++的类中继承.md
- 26_C++的类中多态: CPlusPlus-main/26_C++的类中多态.md
- 27_C++的文件操作: CPlusPlus-main/27_C++的文件操作.md
- 28_C++的模板: CPlusPlus-main/28_C++的模板.md
- 29_C++的STL: CPlusPlus-main/29_C++的STL.md
- 30_C++的函数对象: CPlusPlus-main/30_C++的函数对象.md
- 31_C++的谓词: CPlusPlus-main/31_C++的谓词.md
- 32_C++的内建函数对象: CPlusPlus-main/32_C++的内建函数对象.md
- 33_C++的常用算法: CPlusPlus-main/33_C++的常用算法.md
theme: theme:
@ -85,6 +119,11 @@ theme:
icon: icon:
logo: material/school logo: material/school
plugins:
- search
- mkdocs-jupyter
#markdown_extensions: #markdown_extensions:
# - admonition # - admonition
# - def_list # - def_list