C++成长之旅
前提:万能头文件 为什么我们需要万能头文件?
万能头文件可以帮助我们不用像C语言一样挨个引入库
C++万能头文件的引入
Window: https://blog.csdn.net/weixin_52985599/article/details/112301569
MacOS:
C++基础 打印HelloWorld
Hello,World C++代码
#include <bits/stdc++.h> using namespace std;int main () { cout << "Hello,World" << endl; return 0 ; }
基本数据类型
数据类型
代码
整形
Int
长整形
Long
长长整形
long long
短整形
Short
字符型
Char
单精度浮点型
Float
双精度浮点型
Double
变量名
变量名必须以字母或下划线开头。
变量名可以包含字母、数字和下划线。
变量名不能包含空格或其他特殊字符。
变量名应该具有描述性,以便于代码的可读性和可维护性。
定义变量 形式:数据类型 变量名 = 字面值
示范
int a = 10 ;long a = 10 ;long long a = 20 ;char c = 'a' ;float f = 3.23 ;double d = 3.24435 ;
SizeOf sizeOf是用来获取该数据类型在内存中占用的空间大小
通过以下代码可以看到各个数据类型所占用的内存空间
#include <bits/stdc++.h> using namespace std; int main () { short num = 10 ; cout << "short = " << sizeof(num) << endl; int num1 = 10 ; cout << "int = " << sizeof(num1) << endl; long num2 = 10 ; cout << "long = " << sizeof(num2) << endl; long long num3 = 10 ; cout << "long long = " << sizeof(num3) << endl; float f = 10.23 ; cout << "float = " << sizeof(f) << endl; double d = 10.234 ; cout << "double = " << sizeof(d) << endl; }
浮点型 如果float定义的变量字面值后面不加上f的话会被转化成double类型
科学技术法
float t = 3e2 ; cout << "t = " << t; float t1 = 3e-2 ; cout << "t1 = " << t1;
字符型 字符型只占用一个内存空间
如何定义字符型
字符和ASCII值的转换
int a = (int )ch;cout << a << endl;
转义字符 \ + 某一个特殊含义的字符,就可以把他变成子面含义上的字符
示范
\\ -> \ \* -> * \n ->换行 \t -> 水平制表符 == 四个空格
字符串 C风格的字符串
char [] ch = "helloworld" ;
C++风格的字符串
布尔型 布尔型占用一个内存空间
如何定义bool类型
整形1 代表 true
整形0 代表false
获取键盘输入 cin(c in) 用来获取键盘输入
示范
string h = "helloh" ; cout << "请输入h的值" ; cin >> h; cout << "h = " << h << endl;
If条件判断语句
int a = 10 ;int b = 30 ;if (a > b){ cout << "a = " << a << endl; }else { cout << "b = " << b << endl; }
解析代码
条件判断如果a大的打印a ,小于等于的情况都打印b
int a = 10 ;int b = 30 ;if (a > b){ cout << "a = " << a << endl; }else if (a < b){ cout << "b = " << b << endl; }else { cout << "a = b" << endl; }
通过else…if来判断多种条件
代码解析
如果a > b 打印a,如果a < b打印b,相等的情况打印a = b
如果判断两个值相等,条件判断相等使用==
判断两个值不等 !=
三目操作符 格式:条件判断语句 ?成立执行的结果 :不成立执行的结果
int a = 10 ;int b = 20 ;int c = 0 ;c = a > b ? a : b; cout << "c = " << c << endl; return 0 ;
解析:当a > b 返回结果为a 否则返回结果为b 最终将正确返回的结果传递给c
Switch条件判断语句 以下代码是一个简单的打分系统
cout << "请你为电影打分" << endl; int score = 0 ; cin >> score; string res = "" ; switch (score){ case 10 : res = "我是10" ; break ; case 5 : res = "我是5" ; break ; case 0 : res = "我是0" ; break ; default : res = "我什么也不是" ; break ; } cout << res << endl;
代码解析
输入一个值放入到score中如果score = 10执行case 10对应的语句,如果为5执行5对应的语句,default是如果这些条件都不满足,执行,default放在最后
while循环 指针 如何定义指针?
int a = 20 ;int * p = &a;cout << "p = " << p << endl; cout << "*p = " << *p << endl;
*p又叫做解引用
指针占用的内存空间
空指针
如何定义?
注意事项
空指针是指向内存地址中编号为0的空间
空指针用户是无法进行访问的
*p = 10; 报错
野指针
野指针指向的是一块非法的内存空间
指针常量
指针常量:指针在前,常量在后int* const
int a = 10 ;int b;int * const p = &a;*p = 20 ;
指针常量值可以进行修改,但是地址无法进行修改
常量指针
常量指针:指针在后,常量在前
const int * p = &a;p = &b;
常量指针值不可以进行修改,地址可以进行修改
Const对地址和值都进行修饰
这种情况下值和地址都无法进行修改
指针与数组 第一次使用指针的时候访问的数组中的第一个元素
那么指针如何后移呢?
p++就可以实现向后偏移四个字节即一个数组中下一个元素的效果
int arr[5 ] = {1 ,2 ,3 ,4 ,5 }; cout << arr[0 ] << endl; int * p = arr; cout << *p << endl; p++; cout << *p << endl;
那么如何通过指针来遍历数组呢?
int arr1[5 ] = {1 ,2 ,3 ,4 ,5 }; int * p1 = arr1; for (int i = 0 ;i < sizeof (arr1) / sizeof (arr1[0 ]);i++){ cout << *p1++ << endl; }
指针与函数 这种方式来对a,b进行交换,交换的是形参a和b,实参a b的值并没有修改
void swap01 (int a,int b) { int temp = a; a = b; b = temp; } int main () { int a = 20 ; int b = 10 ; swap01 (a,b); cout << "a = " << a << endl; cout << "b = " << b << endl; return 0 ; }
我们可以借助指针来对a b的地址进行交换,从而达到交换实参值的效果
void swap02 (int * a,int * b) { int temp = *a; *a = *b; *b = temp; } int main () { int a = 20 ; int b = 10 ; swap02 (&a,&b); cout << "a = " << a << endl; cout << "b = " << b << endl; return 0 ; }
指针函数和数组 借助指针和函数,打印冒泡排序
void printArr (int * arr,int len) { for (int i = 0 ;i < len;i++){ cout << arr[i] << endl; } } void Bubble (int * arr,int len) { for (int i = 0 ;i < len;i++){ for (int j = 0 ;j < len - i - 1 ;j++){ if (arr[j] > arr[j + 1 ]){ int temp = arr[j]; arr[j] = arr[j + 1 ]; arr[j + 1 ] = temp; } } } } int main () { int arr[] = {9 ,8 ,7 ,6 ,5 ,4 ,3 ,2 ,1 ,0 }; int len = sizeof(arr) / sizeof(arr[0 ]); Bubble(arr,len); printArr(arr,len); return 0 ; }
结构体 可以自定义数据类型
定义结构体
struct Student { int age; string name; string sex; };
访问结构体(第一种方式)
struct Student s1;s1.age = 12 ; s1.name = "xiaohong" ; s1.sex = "female" ; cout << "age = " << s1.age << " name = " << s1.name << " sex = " << s1.sex;
访问结构体(第二种方式)
struct Student s2 = {20 ,"xiaoming" ,"male" };cout << "age = " << s2.age << " name = " << s2.name << " sex = " << s2.sex;
访问结构体(第三种方式不常用)
struct Student { int age; string name; string sex; }s3; s3.age = 1000 ; s3.name = "销量" ; s3.sex = "none"
结构体数组
定义结构体
struct Student { int age; string name; string sex; };
定义结构体数组
Student stu[3 ] = { {1 ,"a" ,"male" }, {2 ,"b" ,"female" }, {3 ,"c" ,"male" } };
将结构体数组中某个元素的属性进行修改
stu[0 ].age = 2 ; stu[0 ].name = "xiaoming" ; stu[0 ].sex = "female" ;
遍历结构体数组
for (int i = 0 ;i < 3 ;i++){ cout << " age = " << stu[i].age << " name = " << stu[i].name << " sex = " << stu[i].sex << endl; }
结构体指针
定义结构体
struct Student { int age; string name; string sex; };
定义指针指向结构体变量地址
Student s = {1 ,"sdf" ,"female" }; Student* p = &s;
借助结构体指针访问内部属性
cout << " age = " << p->age << " name = " << p->name << " sex = " << p->sex;
结构体嵌套 定义结构体
struct Student { int age; string name; string sex; }; struct Teacher { int age; string name; string sex; Student stu; };
借助teacher来访问student的属性
Teacher t; t.age = 20 ; t.stu.age = 30 ; t.stu.sex = "female" ;
结构体作为函数参数
const修饰结构体 有效的防止了对结构体中的数据进行误操作
void PrintStuMsg (const Student* s) { cout << " age = " << s->age << " name = " << s->name << " sex = " << s->sex << endl; }
案例一 要求创建三个老师有各自的姓名,并且分配给每一个老师5个学生,每一个学生有自己的名字和分数,要求分数随机
思路分析
创建老师的结构体,学生的结构体
关联老师和学生,通过在Teacher结构体中放置学生的结构体数组[5]
为每一个老师和学生添加名字
通过随机数为每一个学生添加随机分数,这个随机分数此时为静态分数
创建随机数种子,使随机数随机起来
打印每一个老师,及其带领的学生的信息
#include <bits/stdc++.h> using namespace std;struct Student { string name; int score; }; struct Teacher { string name; Student stuArr[5 ]; }; void allocate (Teacher tArray[],int len) { string str = "ABCDEF" ; for (int i = 0 ;i < len;i++){ tArray[i].name = "Teacher_" ; tArray[i].name += str[i]; for (int j = 0 ;j < 5 ;j++){ tArray[i].stuArr[j].name = "Student_" ; tArray[i].stuArr[j].name += str[j]; int random = rand () % 61 + 40 ; tArray[i].stuArr[j].score = random; } } } void PrintInfo (Teacher tArr[],int len) { for (int i = 0 ;i < len;i++){ cout << " TeacherName = " << tArr[i].name << endl; for (int j = 0 ;j < 5 ;j++){ cout << "\t学生姓名 = " << tArr[i].stuArr[j].name << " 学生分数 = " << tArr[i].stuArr[j].score << endl; } } } int main () { srand ((unsigned int )time (NULL )); Teacher tArr[3 ]; int len = sizeof (tArr) / sizeof (tArr[0 ]); allocate (tArr,len); PrintInfo (tArr,len); return 0 ; }
案例二 给出一组英雄信息数据,要求通过每一个英雄的年龄进行排序
思路
创建英雄结构体
冒泡排序
打印信息
#include <bits/stdc++.h> using namespace std;struct Hero { string name; int age; string sex; }; void Bubble (Hero h[],int len) { for (int i = 0 ;i < len - 1 ;i++){ for (int j = 0 ;j < len - i - 1 ;j++){ if (h[j].age > h[j + 1 ].age){ Hero temp = h[j]; h[j] = h[j + 1 ]; h[j + 1 ] = temp; } } } } void printHero (Hero h[],int len) { for (int i = 0 ;i < len;i++){ cout << " name = " << h[i].name << " age = " << h[i].age << " sex = " << h[i].sex << endl; } } int main () { Hero h[5 ] = { {"刘备" ,50 ,"男" }, {"吕布" ,39 ,"男" }, {"张飞" ,34 ,"男" }, {"貂蝉" ,19 ,"女" }, {"蔡文姬" ,20 ,"女" } }; int len = sizeof (h) / sizeof (h[0 ]); Bubble (h,len); printHero (h,len); return 0 ; }
通讯录管理系统 操作页面 void showMenu () { cout << "***** ***** ***** ******" << endl; cout << "***** 1.添加联系人 ***** " << endl; cout << "***** 2.显示联系人 ***** " << endl; cout << "***** 3.删除联系人 ***** " << endl; cout << "***** 4.查找联系人 ***** " << endl; cout << "***** 5.修改联系人 ***** " << endl; cout << "***** 6.清空联系人 ***** " << endl; cout << "***** 0.退出通讯录 ***** " << endl; cout << "***** ***** ***** ******" << endl; }
初始化联系人结构体 struct Person { string m_Name; string m_Sex; int m_Age; string m_Phone; string m_Addr; };
初始化通讯录结构体 #define MAX 1000 struct AddressBook { Person perArray[MAX]; int m_Size; };
退出系统 while (true ){ showMenu (); cin >> select; switch (select){ case 1 : break ; case 2 : break ; case 3 : break ; case 4 : break ; case 5 : break ; case 6 : break ; case 0 : cout << "欢迎下次使用" << endl; return 0 ; break ; default : break ; }
添加联系人 void addPerson (AddressBook* abs) { if (abs->m_Size == MAX){ cout << "通讯录名额已满,无法加入" ; return ; }else { string name; cout << "请输入你的姓名" << endl; cin >> name; abs->perArray[abs->m_Size].m_Name = name; int age; cout << "请输入你的年龄" << endl; cin >> age; abs->perArray[abs->m_Size].m_Age = age; int sex; cout << "请输入你的性别" << endl; while (true ){ cout << "1 -> 男 " << " 2 -> 女" << endl; cin >> sex; if (sex == 1 ) { abs->perArray[abs->m_Size].m_Sex = "男" ; break ; }else if (sex == 2 ){ abs->perArray[abs->m_Size].m_Sex = "女" ; } cout << "输入有误重新输入" << endl; } string phone; cout << "请输入你的电话号码" << endl; cin >> phone; abs->perArray[abs->m_Size].m_Phone = phone; string addr; cout << "请输入你的地址" << endl; cin >> addr; abs->perArray[abs->m_Size].m_Addr = addr; abs->m_Size++; cout << "添加成功" << endl; system ("clear" ); } } int main () { AddressBook abs; abs.m_Size = 0 ; }
显示联系人 遍历通讯录数组
void showPerson (AddressBook* abs) { int size = abs->m_Size; if (size == 0 ){ cout << "通讯录中没有人" << endl; }else { for (int i = 0 ;i < size;i++){ cout << " name = " << abs->perArray[i].m_Name << " age = " << abs->perArray[i].m_Age << " sex = " << abs->perArray[i].m_Sex << " phone = " << abs->perArray[i].m_Phone << " addr = " << abs->perArray[i].m_Addr << endl; } } }
删除联系人 数组前移,长度减去1
int isExist (AddressBook* abs,string name) { for (int i = 0 ;i < abs->m_Size;i++){ if (abs->perArray[i].m_Name == name){ return i; } } return -1 ; } void deletePerson (AddressBook* abs) { cout << "请输入你要删除的联系人" << endl; string name; cin >> name; int res = isExist (abs,name); if (res != -1 ){ for (int i = 0 ;i < abs->m_Size;i++){ abs->perArray[i] = abs->perArray[i + 1 ]; } abs->m_Size--; cout << "删除成功" << endl; }else { cout << "没有你要找的人" << endl; } }
查找联系人 void findPerson (AddressBook* abs) { cout << "请输入你想查找的人" << endl; string name; cin >> name; int res = isExist (abs,name); if (res != -1 ){ cout << " name = " << abs->perArray[res].m_Name << " age = " << abs->perArray[res].m_Age << " sex = " << abs->perArray[res].m_Sex << " phone " << abs->perArray[res].m_Phone << " addr = " << abs->perArray[res].m_Addr; }else { cout << "查无此人" << endl; } }
修改联系人 查找修改人的下标,对每一个属性进行修改操作
void modifyPerson (AddressBook* abs) { cout << "请输入你修改的人" << endl; string name; cin >> name; int res = isExist (abs,name); if (res != -1 ){ cout << "请输入修改的名字" << endl; string newName; cin >> newName; abs->perArray[res].m_Name = newName; cout << "请输入修改的年龄" << endl; int newAge; cin >> newAge; abs->perArray[res].m_Age = newAge; cout << "请输入修改的性别" << endl; while (true ){ cout << " 1 -> 男 " << " 2 -> 女 " << endl; int newSex; cin >> newSex; if (newSex == 1 ){ abs->perArray[res].m_Sex = "男" ; break ; }else if (newSex == 2 ){ abs->perArray[res].m_Sex = "女" ; break ; } cout << "输入错误请重新输入" << endl; } cout << "请输入修改的电话" << endl; string newPhone; cin >> newPhone; abs->perArray[res].m_Phone = newPhone; cout << "请输入修改的地址" << endl; string newAddr; cin >> newAddr; abs->perArray[res].m_Addr = newAddr; }else { cout << "查无此人" << endl; } }
清空联系人
清空联系人本质并没有将人清掉,只不过是遍历不到了而已,下一次添加数据把之前残留的数据进行了覆盖而已
void clearPerson (AddressBook* abs) { abs->m_Size = 0 ; cout << "通讯录清空成功" << endl; }
完整代码 #include <bits/stdc++.h> #include <iostream> using namespace std;#define MAX 1000 struct Person { string m_Name; string m_Sex; int m_Age; string m_Phone; string m_Addr; }; struct AddressBook { Person perArray[MAX]; int m_Size; }; void showMenu () { cout << "***** ***** ***** ******" << endl; cout << "***** 1.添加联系人 ***** " << endl; cout << "***** 2.显示联系人 ***** " << endl; cout << "***** 3.删除联系人 ***** " << endl; cout << "***** 4.查找联系人 ***** " << endl; cout << "***** 5.修改联系人 ***** " << endl; cout << "***** 6.清空联系人 ***** " << endl; cout << "***** 0.退出通讯录 ***** " << endl; cout << "***** ***** ***** ******" << endl; } void addPerson (AddressBook* abs) { if (abs->m_Size == MAX){ cout << "通讯录名额已满,无法加入" ; return ; }else { string name; cout << "请输入你的姓名" << endl; cin >> name; abs->perArray[abs->m_Size].m_Name = name; int age; cout << "请输入你的年龄" << endl; cin >> age; abs->perArray[abs->m_Size].m_Age = age; int sex; cout << "请输入你的性别" << endl; while (true ){ cout << "1 -> 男 " << " 2 -> 女" << endl; cin >> sex; if (sex == 1 ) { abs->perArray[abs->m_Size].m_Sex = "男" ; break ; }else if (sex == 2 ){ abs->perArray[abs->m_Size].m_Sex = "女" ; } cout << "输入有误重新输入" << endl; } string phone; cout << "请输入你的电话号码" << endl; cin >> phone; abs->perArray[abs->m_Size].m_Phone = phone; string addr; cout << "请输入你的地址" << endl; cin >> addr; abs->perArray[abs->m_Size].m_Addr = addr; abs->m_Size++; cout << "添加成功" << endl; } } void showPerson (AddressBook* abs) { int size = abs->m_Size; if (size == 0 ){ cout << "通讯录中没有人" << endl; }else { for (int i = 0 ;i < size;i++){ cout << " name = " << abs->perArray[i].m_Name << " age = " << abs->perArray[i].m_Age << " sex = " << abs->perArray[i].m_Sex << " phone = " << abs->perArray[i].m_Phone << " addr = " << abs->perArray[i].m_Addr << endl; } } } int isExist (AddressBook* abs,string name) { for (int i = 0 ;i < abs->m_Size;i++){ if (abs->perArray[i].m_Name == name){ return i; } } return -1 ; } void deletePerson (AddressBook* abs) { cout << "请输入你要删除的联系人" << endl; string name; cin >> name; int res = isExist (abs,name); if (res != -1 ){ for (int i = 0 ;i < abs->m_Size;i++){ abs->perArray[i] = abs->perArray[i + 1 ]; } abs->m_Size--; cout << "删除成功" << endl; }else { cout << "没有你要找的人" << endl; } } void findPerson (AddressBook* abs) { cout << "请输入你想查找的人" << endl; string name; cin >> name; int res = isExist (abs,name); if (res != -1 ){ cout << " name = " << abs->perArray[res].m_Name << " age = " << abs->perArray[res].m_Age << " sex = " << abs->perArray[res].m_Sex << " phone " << abs->perArray[res].m_Phone << " addr = " << abs->perArray[res].m_Addr; }else { cout << "查无此人" << endl; } } void modifyPerson (AddressBook* abs) { cout << "请输入你修改的人" << endl; string name; cin >> name; int res = isExist (abs,name); if (res != -1 ){ cout << "请输入修改的名字" << endl; string newName; cin >> newName; abs->perArray[res].m_Name = newName; cout << "请输入修改的年龄" << endl; int newAge; cin >> newAge; abs->perArray[res].m_Age = newAge; cout << "请输入修改的性别" << endl; while (true ){ cout << " 1 -> 男 " << " 2 -> 女 " << endl; int newSex; cin >> newSex; if (newSex == 1 ){ abs->perArray[res].m_Sex = "男" ; break ; }else if (newSex == 2 ){ abs->perArray[res].m_Sex = "女" ; break ; } cout << "输入错误请重新输入" << endl; } cout << "请输入修改的电话" << endl; string newPhone; cin >> newPhone; abs->perArray[res].m_Phone = newPhone; cout << "请输入修改的地址" << endl; string newAddr; cin >> newAddr; abs->perArray[res].m_Addr = newAddr; }else { cout << "查无此人" << endl; } } void clearPerson (AddressBook* abs) { abs->m_Size = 0 ; cout << "通讯录清空成功" << endl; } int main () { AddressBook abs; abs.m_Size = 0 ; int select; while (true ){ showMenu (); cin >> select; switch (select){ case 1 : addPerson (&abs); break ; case 2 : showPerson (&abs); break ; case 3 : deletePerson (&abs); break ; case 4 : findPerson (&abs); break ; case 5 : modifyPerson (&abs); break ; case 6 : clearPerson (&abs); break ; case 0 : cout << "欢迎下次使用" << endl; return 0 ; break ; default : break ; } } return 0 ; }
C++核心 内存四区
代码区
存放CPU执行的机器指令
**特点:**代码区是共享的,代码区是只读的
全局区
存放的变量:全局变量,静态变量,全局常量,字符串常量
通过打印可知全局变量和局部变量所在的区域不一样
栈区
由编译器管理内存的释放
局部变量存放于栈区,当函数执行玩后栈区的数据就会被释放,所以不要返回局部变量的内存地址
堆区
由程序员管理的内存
**如何创建: **借助new 数据类型(传入的值)在堆区中开辟一段内存空间,通过解引用的方式来进行访问,函数调用后不会自动释放内存
**如何创建一个数组: *int p = new int[10];
如何释放: delete + 内存地址 手动释放内存,释放数组delete[] + 地址
引用
通过引用我们可以让一个变量指向另一个变量的内存地址,从而操作同一块内存空间
int a = 10 ; int &b = a; b = 20 ; cout << a << endl; cout << b << endl;
注意事项
引用不能只声明,不指向
引用一旦初始化后就无法进行修改
引用作为函数的参数 可以做到形参修饰实参的效果
void swap (int &a,int &b) { int temp = a; a = b; b = temp; }
引用作为函数的返回值
不要返回局部变量的引用
函数的返回如果是引用的话可以作为左值去使用
int & func () { static int a = 20 ; return a; } int main () { int &fuc1 = func (); cout << fuc1 << endl; func () = 100 ; cout << fuc1 << endl; }
引用作为指针常量 int main () { int a = 20 ; int &b = a; b = 20 ; cout << a << endl; cout << b << endl; return 0 ; }
const修饰引用 主要用于防止函数不小心进行修改
void showTime (const int & val) { cout << val << endl; } int main () { const int & ref = 10 ; int a = 10 ; showTime (a); cout << a << endl; }
函数高级 默认参数 函数参数可以设置成默认值
int getSum (int a,int b,int c = 10 ) { return a + b + c; }
在这个案例中如果你传入了三个参数,默认值将被你传入的参数取代掉
函数可以提前进行声明操作
int getSum (int a,int b,int c) ;
注意
设置默认值的参数后面必须都设置默认值
声明和实现只能有一个有默认参数
占位参数 void getSum (int a,int ) { cout << "Hello world" << endl; }
占位参数是可以有默认值的
void getSum(int a,int = 10){ cout << "Hello world" << endl; }
函数重载 什么事函数重载?
多个函数方法名一致,参数不同,类型不同,顺序不同,调用时根据参数的不同执行不同的函数
void sayHello () { cout << "Hello" << endl; } void sayHello (int a) { cout << a << endl; } void sayHello (double s) { cout << s << endl; } void sayHello (int a,double s) { cout << s << endl; } void sayHello (double a,int s) { cout << s << endl; }
注意事项
引用重载
void sayHello (int &a) { cout << "Hello world1" << endl; } void sayHello (const int &a) { cout << "Hello world2" << endl; } int main () { int a = 10 ; sayHello (a); sayHello (10 ); return 0 ; }
尽量在重载的时候不要给参数设置默认值
类和对象 什么是类呢?
每个人都有自己的特征,同理其他物质也有自己的属性,我们可以将不同特征的人作为一个类,物质也可以作为一个类
C++面向对象的三大特性
封装 创建一个计算圆周长的类
const double PI = 3.14 ;class Circle { public : int c_dis; double calZC () { return 2 * c_dis * PI; } };
如何使用这个类呢?
int main () { Circle cc; cc.c_dis = 10 ; cout << cc.calZC () << endl; 调用类的方法 return 0 ;
案例:设计一个学生类,每一个学生有自己的姓名和年龄,我们需要调用这个类中的show方法对学生的信息进行显示
#include <bits/stdc++.h> using namespace std;class Stu { public : string name; int age; void show () { cout << name << ":" << age << endl; return ; } }; int main () { Stu stu; stu.name = "张三" ; stu.age = 12 ; stu.show (); return 0 ; }
当然,类中的方法其实也是可以对属性进行修改的
假如我们想要对名字进行修改
除了
stu.name = "张三"
还可以
void gvName (string n) { name = n; }
类中的属性被称为成员属性,类中的方法被称为成员方法
访问权限
公共访问权限:类里面可以访问,类外面也可以访问
私有访问权限:类里面可以访问,外面不可以访问
保护访问权限:类里面可以访问,外面不可以访问
#include <bits/stdc++.h> using namespace std;class Peo {public : string name; private : int age; protected : char sex; public : void set () { name = "张三" ; age = 29 ; sex = '6' ; } }; int main () { Peo peo; peo.name = "张三" ; return 0 ; }
通过对类的介绍我们会发现类和结构体十分的相似
那么他们的区别是什么呢?
类的默认访问权限是private,而结构体默认是public
实际开发中成员属性设置为私有,通过成员方法进行修改和访问
class Peo { string name; int age; string m_lover; public : void setName (string n) { name = n; } string getName () { return name; } int getAge () { age = 0 ; return age; } void set_lover (string s) { m_lover = s; } };
对象的初始化和清理 构造函数
书写格式
构造函数不用写返回值(包含void)
构造函数名字必须与类名保持一致
可以有参数,可以发生重载现象
构造函数在对象创建好后就会被自动调用
class Person {public : Person (){ cout << "hello" << endl; } };
析构函数
不用写返回值
名和类名一致,名称前需要加~
没有参数,无法发生重载现象
对象销毁的时候会自动调用
class Person {public : Person (){ cout << "hello" << endl; } ~Person (){ cout << "dead program" << endl; } };
当创建对象的时候打印”hello”,当栈内存释放的时候,打印dead Program
构造函数的分类
根据有无参数,我们可以分为两类,一类是有参数构造函数,还有一类是无参数构造函数
class Person {public : Person (){ cout << "hello" << endl; } Person (int a){ cout << "hello1" << endl; } }
拷贝构造函数(将某一个对象身上的属性施加到当前对象身上)
class Person { int age; public : Person (){ cout << "hello" << endl; } ~Person (){ cout << "dead program" << endl; } Person (const Person &b) { age = b.age; } };
如何触发有参构造
如何触发拷贝构造
注意事项:在调用默认构造函数的时候不要加(),否则可能会被认为是函数声明
显示类
针对于上面创建出来的对象,我们发挥对象应有的价值
Person p; Person p1 = Person (10 ); Person p2 = Person (p1); Person (p2);
在这里Person(10)是匿名对象,在对象创建好后就释放掉,所以我们需要为其命名
不要使用拷贝构造初始化匿名构造
隐式转换法
Person p = 10 ; Person p1 = p;
将类作为值进行传递,实则调用了一次拷贝构造
class Person { int age; public : Person (){ cout << "无参数构造" << endl; } ~Person (){ cout << "dead program" << endl; } Person (int n) { age = n; cout << "有参数构造" << endl; } Person (const Person &b) { age = b.age; cout << "拷贝构造" << endl; } }; void doWork (Person t) { } void st () { Person p; doWork (p); } int main () { st (); return 0 ; }
以值方式返回局部对象
Person doWork1 () { Person p2; cout << (int *)&p2 << endl; return p2; } void st1 () { Person p1 = doWork1 (); cout << (int *)&p1 << endl; }
现今版本应该是优化过的返回并没有触发拷贝构造