c++学习
- c++学习——By Xie
- VS使用技巧
- sizeof关键字
- float 单精度浮点型
- 字符型
- 转义字符
- 字符串
- 布尔型
- 除法
- 取模(取余)运算
- 递增
- 逻辑运算符
- 三目运算符
- switch语句
- rand( )生成伪随机整数
- srand( )生成真随机数
- 取出各位上的数字
- 指数函数
- for循环的省略
- 循环嵌套
- 一维数组
- 删除数组中的一个元素
- 求数组元素个数
- 数组前后依次交换元素值
- 冒泡排序
- 数组作为参数传递给函数
- 二维数组名称
- 二维数组加法
- 字符串数组
- 函数的参数传递
- 函数分文件编写
- 指针
- 指针常量和常量指针
- 值传递
- 地址传递
- 指针+冒泡排序(升序)
- 结构体
- 结构体数组
- 结构体指针
- 结构体嵌套
- 结构体数组嵌套
- 根据某项元素对结构体数组排序
- 无参数调用
- 实例——通讯录管理系统
- 变量(常量)都在哪
- 堆区
- 堆区创建数组
- 引用
- 引用做函数参数(形参)
- 引用做返回值
- 常量引用
- 函数默认参数
- 类和结构体
- 类成员的访问权限
- 中途退出函数
- 成员函数和全局函数
- 类的嵌套
- 分文件编写
- 构造函数什么时候被调用
- 析构函数执行堆区数据的释放
- 浅拷贝的问题
- 深拷贝解决堆区重复释放的问题
- 初始化列表
- 静态成员变量
- 静态成员函数
- 只有非静态成员变量属于类的对象上
- 成员变量和形参名称冲突 this指针
- *this返回该对象
- this 指针本质是指针常量
- 成员函数后加const 常函数
- 构造和析构函数上不允许使用类型限定符(如const)
- 友元(可以访问类中的私有成员)
- 运算符重载(加法)
- 运算符重载(左移运算符)
- 编译器默认提供的类的函数
- 运算符重载(赋值运算)
- 继承
- 继承方式
- 利用开发人员命令提示工具查看对象模型
- 子类中同名属性的访问
- 多继承
- 父类的引用指向子类的对象
- 动态多态(父类函数前加virtual)
c++学习——By Xie
以下均为学习b站黑马程序员C++所做笔记,以及简单的学习心得
黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难
VS使用技巧
注释: 先CTRL+K,然后CTRL+C 或者加//
取消注释: 先CTRL+K,然后CTRL+U 或者删除//
调试:F5
单步执行:F10
设置或者删除断点:F9
查找:CTRL+Shift+F
跳转到变量/函数的定义:F12
system("pause") //显示按任意键继续
system("cls") //清屏程序执行到return,会直接跳出该函数
sizeof关键字
sizeof(数据类型/变量名)
int arr[10]={、、、};
int a= sizeof(arr)/sizeof(arr[0]); //常用来求数组元素个数float 单精度浮点型
float f1 = 3.14f; //常在末尾加上f,表示单精度
double f2 = 3.14; //在double中常省略字符型
字符型变量用于显示单个字符
char ch = 'a'; //单引号中只能有一个字母查看对应的ASCII码值
cout << (int)ch << endl; //强制类型转换
//A——65;a——97转义字符
\n 换行
\t 水平制表符 和前面的总共构成8个空格,整齐地输出后面的内容
\\ 反斜杠字符字符串
char str[] = "hello world";
string str2 = "hello world"; //两种创建方式 第二种方式要加头文件 #include <string>布尔型
/*
true (本质是数字1)
false (本质是数字0)
*/
bool flag = true除法
两个整数相除,结果依然为整数,直接舍弃小数(没有四舍五入)
int a = 10;
int b = 20;
cout << a/b << endl //结果为0
double d1 = 0.5;
double d2 = 0.22;
cout << d1/d2 << endl; //2.27273取模(取余)运算
%
//小数不能做取模运算递增
int a1 =10;
int a2 = ++a1 * 10; //前置递增,先让变量+1,然后进行表达式的计算 a1=11,a2=110
int b1 = 10;
int b2 = b1++ *10; //后置递增,先进行表达式的计算,再让变量+1 b1=11,b2=100逻辑运算符
// !非 &&与 ||或三目运算符
int a=10;
int b=100;
int c=0;
c = ( a<b ? a:b); //将较小值赋值给c
//三目运算符返回的是变量,可以继续赋值
(a<b ? a:b) = 100; //a=100switch语句
switch(表达式(变量) 字符型/整型)
{
case1:
case2:
、、、; //1和2执行相同的语句
break; //没有break,会一直执行后面的语句
、、、
default:
、、、; //没有对应的case则执行default
}rand( )生成伪随机整数
//通用公式: a + rand()% n,a为起始整数,n为能取到的整数个数
/*例如:[1,100]生成随机数:1+rand()%100;
(1,100]生成随机数:2+rand()%99;
(1,100)生成随机数:2+rand()%98;srand( )生成真随机数
//根据当前系统时间生成随机数
#include <ctime>
srand((unsigned int)time(NULL));
int a = 1+rand()%100;取出各位上的数字
/*从多位数(例如:n=2456)取出各个位数上的数字
个位:对10取模 int a = n%10;
最高位:除以10的位数-1次方 int b = n/1000;
其他位:除以10的对应次方,再对10取模 取出十位数字: int c = n/10%10;
取出百位数字: int d = n/100%10; 间接变成取出个位数字
*/ 指数函数
pow(10.0,3); //10的3次方`for循环的省略
//输出0到9所有整数
int i = 0;
for(; ; ;)
{
if(i>9)
{
break;
}
、、、;
i++;
}for ( 0int i=0; 1 i<10; 3 i++)
{
2、、、;
} //执行顺序为0 1 2 3 1 2 3……..
循环嵌套
难点是在循环条件的书写,循环嵌套需要做的大体都是一个方形(可能不完整),行用 i 来控制,列用 j 来控制,且每一次 j 循环时 i 为定值,for( ) 循环常用计算需要循环的次数来确定循环条件,特别需要注意 j 关于 i 的通式的书写。
一维数组
//三种定义方式
/* 数组类型 数组名[数组长度]; int a[4];
数组类型 数组名[数组长度] = {、、、}; int a[4]={1,2,3,4};
数组类型 数组名[] ={、、、}; int a[]={1,2,3,4};
数组中每个元素类型相同
数组名是首元素的地址,是个常量
*/
int arr[5]= {10,20,30,40,50};
cout << arr<<endl; //输出为第一个元素地址 等同于 cout<< &arr[0] <<endl;
cout<<(int)arr<<endl; //以十进制输出删除数组中的一个元素
//遍历数组,如果某个元素和输入的相同,则删除该元素。可以分成两部分,第一个函数实现查找功能,变量a返回该元素在数组中的序号,没找到则返回-1
//实现删除功能的函数接收返回变量,删除可以用后一个元素覆盖前一个来实现,for循环变量i从a开始到元素数(或者元素数-1)
//最后数组元素数-1
int is_exist(int* arr,int len)
{
for (int i = 0; i < len; i++)
{
if (arr[i] == 6)
{
return i;
}
}
return -1;
} //一定要在for循环遍历整个数组发现没有该值后,再return -1求数组元素个数
int arr[]={1,2,3,4,5};
int a = sizeof(arr)/sizeof(arr[0]);数组前后依次交换元素值
//从下标的角度思考,下标来移动,循环条件为 start < end
int arr[5]={1,2,3,4,5};
int start =0; //首下标
int end = sizeof(arr)/sizeof(arr[0])-1; //尾下标
int a = 0; //存储中间变量
// 、、、、;冒泡排序
//6个数升序排列,进行5轮(外层循环 i=0,1,2,3,4),每轮比较的次数n-i-1 (j的表达式)
//输入回车开始排序
#include<iostream>
#include<string>
using namespace std;
void maopao(int* p, int len) //冒泡排序
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - i - 1; j++)
{
if (p[j] < p[j + 1])
{
int a = p[j];
p[j] = p[j + 1];
p[j + 1] = a;
}
}
}
}
int main()
{
int i = 0;
int arr[20] ; //预先指定数组大小
while (cin.peek() != '\n') //键入回车跳出循环
{
cin >> arr[i];
i++;
}
int len = i;
cout << i<<endl;
maopao(arr, len);
for (int j = 0; j < len; j++)
{
cout << arr[j] << " ";
}
cout << endl;
system("pause");
return 0;
}数组作为参数传递给函数
#include<iostream>
#include<string>
using namespace std;
void aaa(int arr[], int len) //第一种方式 值传递
{
for (int i = 0; i < len; i++)
{
cout << arr[i]<<" ";
}
cout << endl;
}
int main()
{
int arr[] = { 1,2,3,4,5 };
int len = sizeof(arr) / sizeof(arr[0]);
aaa(arr, len);
system("pause");
return 0;
}
#include<iostream>
#include<string>
using namespace std;
void aaa(int *arr, int len) //第二种方式 地址传递
{
for (int i = 0; i < len; i++)
{
cout << arr[i]<<" ";
}
cout << endl;
}
int main()
{
int arr[] = { 1,2,3,4,5 };
int len = sizeof(arr) / sizeof(arr[0]);
aaa(arr, len);
system("pause");
return 0;
}二维数组名称
//查看内存空间
int arr[2][3]= {{1,2,3},{4,5,6}}
cout << sizeof(arr) <<endl; //数组占用的总内存空间
cout << sizeof(arr[0]) << endl; //第一行所占内存空间
cout << sizeof(arr)/sizeof(arr[0]); //二维数组行数
cout << sizeof(arr[0])/sizeof([0][0]); //二维数组列数
//首元素地址
cout << (int)arr <<endl; //数组首地址
cout << (int)arr[0] <<endl; //第一行首地址
cout << &(int)arr[0][0] << endl; //第一个元素首地址二维数组加法
做加法时,不要用arr[i] [j]+arr[i] [j+1],而是
int sum =0;//定义一个变量作为和
for(int i=0;i<、、、;i++)
{
for(int j=0;j<、、、;j++)
{
sum +=arr[i][j];
}
}字符串数组
数组的每一个元素为一个字符串,且不要求长度相同
string arr[3]={"张三","李四","王五"};函数的参数传递
void test(int a,int b) //形参接收实参时,int a=c,int b=d;
{
cout<<a+b<<endl;
}
int main()
{
int c=10;
int d=20;
test(c,d);
system("pause");
return 0;
}函数分文件编写
1、创建 .h 的头文件,在其中写函数声明
2、创建 .cpp 的源文件,在其中写函数的定义
.h文件
#include<iostream>
using namespace std;
void swap(int a, int b); //函数声明.cpp文件
#include "swap.h"
void swap(int a, int b) //函数定义
{
int c = a;
a = b;
b = c;
cout << "a的值为" << a << endl;
cout << "b的值为" << b << endl;
}在主.cpp文件中再加上#include “swap.h” ,即可调用函数
指针
int a=10; //整型变量要定义整型
int * p = &a; //p中存的是a的地址
*p = 100; //解引用,修改指针所指向的内存中的数据 a=100;
//指针也是一种数据类型,表示为int *、float *等,变量名为p,和整型、字符型、字符串一样。sizeof(int *),sizeof(p)。指针常量和常量指针
const int * p = &a; //常量指针 与int const *p = &a完全相同
*p =10; //错误 值只能读取,不能修改,防止误操作
p = &b; //正确
const struct student *s;
s->age = 18; //错误,结构体变量中的值不能修改
int * const p = &a; //指针常量
p = &a; //错误
*p = 10; //正确值传递
形参的改变不影响实参的值
地址传递
用指针接收变量的地址,修改以后值会发生改变
结构体作为函数参数时,地址传递以指针来接收有利于减少内存空间
指针+冒泡排序(升序)
#include<iostream>
#include<string>
using namespace std;
void swap(int* p,int N)
{
int* p2 = p;
for (int i = 0; i < N - 1; i++)
{
for (int j = 0; j < N - i-1; j++)
{
if (*p2 > * (p2 + 1))
{
int c = *p2;
*p2 = *(p2 + 1);
*(p2 + 1) = c;
}
p2++;
}
p2 =p;
}
}
int main()
{
int arr[] = { 4,3,1,2,8,7,10,9,5,6 };
int N = sizeof(arr) / sizeof(arr[0]); //数组长度
swap(arr,N);
for (int k = 0; k < N; k++)
{
cout << arr[k]<<" "<<endl;
}
system("pause");
return 0;
}
//指针的两种访问数组值的方式
int *p =arr;
cout << p[2];
int *p =arr;
cout << *(p+2); //且这两种方式使用后并不改变 p 指向首地址
#include<iostream>
#include<string>
using namespace std;
void swap(int* p,int N)
{
for (int i = 0; i < N - 1; i++)
{
for (int j = 0; j < N - i-1; j++)
{
if (p[j] > p[j+1])
{
int c = p[j];
p[j] = p[j + 1];
p[j + 1] = c;
}
}
}
}
int main()
{
int arr[] = { 4,3,1,2,8,7,10,9,5,6 };
int N = sizeof(arr) / sizeof(arr[0]);
swap(arr,N);
for (int k = 0; k < N; k++)
{
cout << arr[k]<<" "<<endl;
}
system("pause");
return 0;
}结构体
struct student
{
string name; //姓名
int age; //年龄
int score; //分数
}; //结构体定义 定义时struct关键字不可省略 定义好之后类似于一个数据类型,后面跟变量名可以直接赋值
//结构体变量创建 struct关键字可省略
student s1;
s1.name = "lalala";
s1.age = 16;
s1.score = 87;
struct student s2={"lalalala", 17, 98};结构体数组
结构体定义没有区别,变量名变成了一个数组名,数组中的每个元素类型是一个结构体
//创建结构体数组
struct student arr[3]=
{
{"张三",16,90},
{"李四",18,70},
{"王五",19,80}
};
arr[0].age =20; //仍用变量名. 来访问,用for循环来遍历结构体指针
结构体定义没有区别
//结构体变量创建
struct student s ={"张三", 17, 90};
struct student *p = &s;
cout << "姓名:"<< p->name << endl;结构体嵌套
//定义
struct student
{
string name;
int age;
int score;
}
struct teacher
{
int id;
string name;
struct student stu;
}
//创建变量
struct teacher t;
t.id = 1000;
t.name = "啦啦啦";
t.stu.name ="哦哦哦";
t.stu.age = 17;
t.stu.score =90;结构体数组嵌套
三个老师每个人带三个学生
#include<iostream>
#include<string>
using namespace std;
struct student
{
string name; //姓名
int score; //分数
};
struct teacher
{
string name;
struct student arr[3];
};
int main()
{
struct teacher arr1[3]; //难点
for (int k = 0; k < 3; k++)
{
cout << "请输入第"<<k+1<<"个老师姓名:" << endl;
cin >> arr1[k].name;
for(int i=0;i<3;i++)
{
cout << "请输入他第" << i + 1 << "个学生的姓名" << endl;
cin >> arr1[k].arr[i].name;
cout << "请输入他第" << i + 1 << "个学生的成绩" << endl;
cin >> arr1[k].arr[i].score;
}
}
for (int j = 0; j < 3; j++)
{
cout << "第" << j + 1 << "个老师是:" << arr1[j].name << endl;
for (int b = 0; b < 3;b++)
{
cout << "他的第" << b + 1 << "个学生是:" <<arr1[j].arr[b].name<< " "
<< "成绩为:" << arr1[j].arr[b].score << endl;
}
}
system("pause");
return 0;
}根据某项元素对结构体数组排序
#include<iostream>
#include<string>
using namespace std;
struct hero
{
string name;
int age;
string gender;
};
void bubblesort(hero *arr, int len) //按年龄对英雄排序
{
for (int i = 0; i < len-1; i++)
{
for (int j = 0; j < len-1 - i; j++)
{
if (arr[j].age > arr[j + 1].age)
{
hero a = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = a;
}
}
}
for (int k = 0; k < 5; k++)
{
cout << "姓名:" << arr[k].name << " " << "年龄" <<
arr[k].age << " " << "性别" << arr[k].gender << endl;
}
}
int main()
{
struct hero arr[] =
{
{"刘备",23,"男"},
{"关羽",22,"男"},
{"张飞",20,"男"},
{"赵云",21,"男"},
{"貂蝉",19,"女"}
}; //五个数冒泡排序
int len = sizeof(arr) / sizeof(arr[0]);
bubblesort(arr, len);
system("pause");
return 0;
}无参数调用
void showMenu()
{
cout << "1、添加联系人" << endl;
cout << "2、显示联系人" << endl;
cout << "3、删除联系人" << endl;
cout << "4、查找联系人" << endl;
cout << "5、修改联系人" << endl;
cout << "6、清空联系人" << endl;
cout << "0、退出该系统" << endl;
}
int main()
{
showMenu(); //括号不能省略
system("pause");
return 0;
}实例——通讯录管理系统
#include<iostream>
using namespace std;
struct aaa //联系人结构体
{
string name;
string sex;
int age;
string phonenumber;
string address;
};
struct bbb //通讯录结构体
{
struct aaa arr[1000];
int size; //当前通讯录中人员个数
};
void showMenu()
{
cout << "1、添加联系人" << endl;
cout << "2、显示联系人" << endl;
cout << "3、删除联系人" << endl;
cout << "4、查找联系人" << endl;
cout << "5、修改联系人" << endl;
cout << "6、清空联系人" << endl;
cout << "0、退出该系统" << endl;
}
void add_people(bbb *t)
{
int z = t->size;
cout << "请输入姓名:" << endl;
cin >> t->arr[z].name;
cout << "请输入性别:" << endl;
cin >> t->arr[z].sex;
cout << "请输入年龄:"<<endl;
cin >> t->arr[z].age;
cout << "请输入电话:" << endl;
cin >> t->arr[z].phonenumber;
cout << "请输入地址:" << endl;
cin >> t->arr[z].address;
t->size++;
}
void show_people(bbb t)
{
if (t.size == 0)
{
cout << "当前联系人为空" << endl;
}
else
{
for (int i = 0; i < t.size; i++)
{
cout << "姓名:" << t.arr[i].name << " " << "性别:" << t.arr[i].sex << " " << "年龄:" << t.arr[i].age
<< " " << "电话:" << t.arr[i].phonenumber << " " << "地址:" << t.arr[i].address << endl;
}
}
}
int is_exist(bbb* t, string name)
{
int i = 0;
for (; i < t->size; i++)
{
if (t->arr[i].name == name)
{
return i;
}
}
return -1;
} //多个功能都涉及到查找,返回数组元素下标
void delete_people(bbb* t)
{
string name;
cout << "请输入想要删除的联系人姓名:";
cin >> name;
int a = is_exist(t, name);
if (a == -1)
{
cout << "查无此人!" << endl;
}
else
{
for (int i = a; i < t->size; i++)
{
t->arr[i] = t->arr[i + 1];
}
t->size--;
}
}
void find_people(bbb *t)
{
string name;
cout << "请输入想查找的联系人:" << endl;
cin >> name;
int a = is_exist(t, name);
if (a == -1)
{
cout << "查无此人!" << endl;
}
else
{
cout<<"姓名:"<<t->arr[a].name<<" " << "性别:" << t->arr[a].sex << " " << "年龄:" << t->arr[a].age
<< " " << "电话:" << t->arr[a].phonenumber << " " << "地址:" << t->arr[a].address << endl;
}
}
void modify_people(bbb *t)
{
string name;
cout << "请输入想修改的联系人姓名:" << endl;
cin >> name;
int a = is_exist(t, name);
if (a == -1)
{
cout << "查无此人!" << endl;
}
else
{
cout << "请重新输入姓名:" << endl;
cin >> t->arr[a].name;
cout << "请输入性别" << endl;
cin >> t->arr[a].sex;
cout << "请输入年龄" << endl;
cin >> t->arr[a].age;
cout << "请输入电话:" << endl;
cin >> t->arr[a].phonenumber;
cout << "请输入地址" << endl;
cin >> t->arr[a].address;
}
}
void clean_out(bbb* t)
{
cout << "您是否确认要清空通讯录 1——是 2——否" << endl;
int s;
cin >> s;
if (s == 1)
{
t->size = 0;
cout << "通讯录已清空!" << endl;
}
}
int main()
{
struct bbb t;
t.size = 0;
int select;
while (1)
{
showMenu();
cin >> select;
string abc;
switch (select)
{
case 1:
add_people(&t);
break;
case 2:
show_people(t);
break;
case 3:
delete_people(&t);
break;
case 4:
find_people(&t);
break;
case 5:
modify_people(&t);
break;
case 6:
clean_out(&t);
break;
case 0:
cout << "再见!" << endl;
system("pause");
return 0;
default:
break;
}
system("pause");
system("cls");
}
system("pause");
return 0;
}变量(常量)都在哪
const int c_g_a=10; //const修饰的全局变量——全局常量——全局区
int g_a=10; //全局变量——全局区
int main()
{
int l_a=10; //局部变量——非全局区(栈区)
static a=10; //静态变量——全局区
"hello"; //字符串常量——全局区
const int c_l_a=10; //const修饰的局部变量——局部常量——非全局区(栈区)
system("pause");
return 0;
}
//栈区数据(局部变量和形参)由编译器管理开辟和释放,该函数执行完自动释放,故不要返回局部变量的地址堆区
//由程序员管理开辟和释放
int * func()
{
int * p = new int(10);
//该指针是局部变量,存放在栈区,指针中地址存放的数在堆区,new将数据开辟到堆区,返回其地址
return p;
}
int main()
{
int *p =func();
cout<<*p<<endl;
delete p; //释放
}堆区创建数组
int* func()
{
int *p = new int[5];
for(int i=0;i<5;i++)
{
cin>>p[i];
}
return p;
}
int main()
{
int *arr=func();
for(int j=0;j<5;j++)
{
cout<<arr[j];
}
cout<<endl;
delete[] arr; //释放堆区的数组,且不是delete[] p
system("pause");
return 0;
}引用
//引用必须初始化,且之后不可改变
int a=10;
int &b=a; //引用的本质是指针常量 int *const b=&a; b中存放的始终是a的地址,且可以通过*b去改变a的值引用做函数参数(形参)
//以引用的方式接收实参,让形参可以修饰实参
void exchange(int &a, int &b)
{
int c = a;
a = b;
b = c;
}
int main()
{
int a = 10;
int b = 20;
exchange(a, b); //int &a=a; 别名也叫a
cout << "a=" << a << endl;
cout << "b=" << b << endl; //a=20,b=10
system("pause");
return 0;
}引用做返回值
int& test()
{
static int a = 10;
return a; //返回a的引用,才能用别名去接收,且不要返回局部变量的引用
}
int main()
{
int &b = test(); //b是a的引用
test() = 1000; //函数做左值,则必须返回引用;对原名进行操纵
cout << "b=" << b << endl; //别名的值也会改变
//b=1000
system("pause");
return 0;
}
//错误案例
int test()
{
static int a = 10;
return a;
}
int main()
{
test() = 1000; //返回原值,函数不能直接做左值
//cout << "b=" << b << endl;
system("pause");
return 0;
}常量引用
void test(const int &b)
{
//b=40; 错误的,不允许通过别名再修改 const int &b=30,只给只读权限,防止误操作
cout << "b=" << b<<endl;
}
int main()
{
int a = 30;
test(a);
system("pause");
return 0;
}
//cont int &b=30 相当于int a=30; const int &b=a;函数默认参数
void test(int a,int b,int c); //函数的声明和实现只能有一个有默认参数
void test(int a, int b = 10, int c = 30) //默认参数必须放在最后,就是有默认参数的形参右侧的形参必须都有默认参数
{
cout << a + b + c << endl;
}
int main()
{
test(10, 20); //使用用户提供的值,10+20+30
system("pause");
return 0;
}类和结构体
//二者唯一的区别是结构体在默认情况下成员是公共的,类在默认情况下成员是私有的(但是都可以自定义)
#include<iostream>
#include<string>
using namespace std;
struct student //学生结构体
{
string name;
string number;
void show()
{
cout << "姓名为:" << name << endl;
cout << "学号为:" << number << endl;
}
};
int main()
{
student s1;
s1.name = "张三";
s1.number = "123456";
s1.show();
system("pause");
return 0;
}
#include<iostream>
#include<string>
using namespace std;
class student //学生类
{
public:
string name;
string number; //两个属性:姓名和学号
void show() //行为:打印出姓名和学号
{
cout << "姓名为:" << name << endl;
cout << "学号为:" << number << endl;
}
};
int main()
{
student s1; //通过类创建出一个具体的学生
s1.name = "张三";
s1.number = "123456";
s1.show();
system("pause");
return 0;
}
//构造一个类,相当于一个新的数据类型,它下面又包含一系列基本数据类型(int/string能存在的地方,它基本都能在)类成员的访问权限
1、public
类内可访问、类外可访问
2、protected
类内可访问、类外不可访问,继承该类的子类可以访问
3、private
类内可访问、类外不可访问,继承该类的子类不可访问
中途退出函数
//函数遇到return关键字会直接退出,不再执行剩下的语句
void test(int age)
{
if(age<0 || age>150)
{
cout<<"输入有误!"<<endl;
return; //直接退出函数
}
else
{
//、、、;
}
//、、、;
}成员函数和全局函数
#include<iostream>
#include<string>
using namespace std;
class cube //学生结构体
{
public:
//设置长
void set_l(double l) //成员函数(行为)
{
m_l = l;
}
//获取长
double get_l()
{
return m_l;
}
//设置宽
void set_w(double w)
{
m_w = w;
}
//获取宽
double get_w()
{
return m_w;
}
//设置高
void set_h(double h)
{
m_h= h;
}
//获取高
double get_h()
{
return m_h;
}
//获得表面积
double get_square()
{
double square = (m_l * m_h + m_l * m_w + m_h * m_w) * 2;
return square;
}
//获得体积
double get_volume()
{
double volume = m_l * m_h * m_w;
return volume;
}
//利用成员函数比较两个立方体是否完全相同
bool panduan(cube &c)
{
if (m_l == c.get_l() && m_h == c.get_h() && m_w == c.get_w())
{
return true;
}
else
{
return false;
}
}
private:
double m_l; //成员变量(属性)
double m_w;
double m_h;
};
//全局函数判断是否相等
bool issame(cube &c1,cube &c2)
{
if (c1.get_l() == c2.get_l() && c1.get_h()== c2.get_h() && c1.get_w() == c2.get_w())
{
return true;
}
else
{
return false;
}
}
int main()
{
cube c1; //定义对象
c1.set_l(2.0);
c1.set_w(3.0);
c1.set_h(4.0);
double s = c1.get_square();//表面积
cout << "表面积为:" << s << endl;
double v = c1.get_volume();
cout << "体积为:" << v << endl;
cube c2;
c2.set_l(2.0);
c2.set_w(3.0);
c2.set_h(3.0);
bool b = issame(c1, c2);
if (b)
{
cout << "两个立方体完全相同" << endl;
}
else
{
cout << "两个立方体不相同" << endl;
}
bool d = c1.panduan(c2); //关键点,c1结构体去调用函数,传入参数为c2,比较c1和c2的长、宽、高
cout << d;
system("pause");
return 0;
}类的嵌套
//判断点和圆的位置关系
#include<iostream>
#include<string>
using namespace std;
class Point
{
public:
//设置点x坐标
void set_p_x(int x)
{
p_x = x;
}
//设置点y坐标
void set_p_y(int y)
{
p_y = y;
}
//获取点x坐标
int get_p_x()
{
return p_x;
}
//获取点y坐标
int get_p_y()
{
return p_y;
}
private:
int p_x; //点x坐标
int p_y; //点y坐标
};
class Circle //圆类
{
public:
//设置圆心坐标
void set_c_p(Point p)
{
c_p = p;
}
//获取圆心
Point get_c_p()
{
return c_p;
}
//设置半径
void set_r(int r)
{
c_r = r;
}
//获取半径
int get_r()
{
return c_r;
}
private:
Point c_p; //圆心坐标
int c_r; //半径
};
//全局函数确定点和圆的位置关系
void panduan(Circle& c, Point& p)
{
int c_x = c.get_c_p().get_p_x(); // 圆心x
int c_y = c.get_c_p().get_p_y();//圆心y
int r = c.get_r(); //半径
int p_x = p.get_p_x();
int p_y = p.get_p_y();
int d2 = (c_x - p_x) * (c_x - p_x) + (c_y - p_y) * (c_y - p_y);
if (d2 == (r*r))
{
cout << "点在圆上" << endl;
}
else if (d2 < (c.get_r() * c.get_r()))
{
cout << "点在圆内" << endl;
}
else
{
cout << "点在圆外" << endl;
}
}
int main()
{
Point p; //点
p.set_p_x(3);
p.set_p_y(0);
Circle c; //圆
c.set_r(3);
Point c_p;
c_p.set_p_x(0);
c_p.set_p_y(0);
c.set_c_p(c_p);
panduan(c, p);
system("pause");
return 0;
}分文件编写
//circle.h
#pragma once
#include<iostream>
#include<string>
#include"point.h"
using namespace std;
class Circle //圆类
{
public:
//设置圆心坐标 //只保留函数声明和成员声明
void set_c_p(Point p);
//获取圆心
Point get_c_p();
//设置半径
void set_r(int r);
//获取半径
int get_r();
private:
Point c_p; //圆心坐标
int c_r; //半径
};
//circle.cpp
#include "circle.h"
#include<iostream>
#include<string>
using namespace std;
//设置圆心坐标
void Circle::set_c_p(Point p) //函数作用域 Circle类下
{
c_p = p;
}
//获取圆心
Point Circle::get_c_p()
{
return c_p;
}
//设置半径
void Circle::set_r(int r)
{
c_r = r;
}
//获取半径
int Circle::get_r()
{
return c_r;
}
//point.h
#pragma once
#include<iostream>
#include<string>
using namespace std;
class Point
{
public:
//设置点x坐标
void set_p_x(int x);
//设置点y坐标
void set_p_y(int y);
//获取点x坐标
int get_p_x();
//获取点y坐标
int get_p_y();
private:
int p_x; //点x坐标
int p_y; //点y坐标
};
//point.cpp
#include "point.h"
#include<iostream>
#include<string>
using namespace std;
//设置点x坐标
void Point::set_p_x(int x)
{
p_x = x;
}
//设置点y坐标
void Point::set_p_y(int y)
{
p_y = y;
}
//获取点x坐标
int Point::get_p_x()
{
return p_x;
}
//获取点y坐标
int Point::get_p_y()
{
return p_y;
}
//主程序
#include<iostream>
#include<string>
#include"circle.h"
#include"point.h"
using namespace std;
//全局函数确定点和圆的位置关系
void panduan(Circle& c, Point& p)
{
int c_x = c.get_c_p().get_p_x(); // 圆心x
int c_y = c.get_c_p().get_p_y();//圆心y
int r = c.get_r(); //半径
int p_x = p.get_p_x();
int p_y = p.get_p_y();
int d2 = (c_x - p_x) * (c_x - p_x) + (c_y - p_y) * (c_y - p_y);
if (d2 == (r*r))
{
cout << "点在圆上" << endl;
}
else if (d2 < (c.get_r() * c.get_r()))
{
cout << "点在圆内" << endl;
}
else
{
cout << "点在圆外" << endl;
}
}
int main()
{
Point p; //点
p.set_p_x(3);
p.set_p_y(0);
Circle c; //圆
c.set_r(3);
Point c_p;
c_p.set_p_x(0);
c_p.set_p_y(0);
c.set_c_p(c_p);
panduan(c, p);
system("pause");
return 0;
}构造函数什么时候被调用
//构造函数调用测试
#include<iostream>
#include<string>
using namespace std;
class Point //创建一个类,会自动生成 默认构造、默认析构、拷贝构造(值拷贝)三个函数
{
public:
Point()
{
cout << "默认构造调用" << endl;
}
Point(int a,int b) //写了有参构造函数,则编译器不再提供默认构造函数,会提供拷贝构造函数
{ //写了拷贝构造函数,则编译器不再提供其他构造函数
p_x = a;
p_y = b;
cout << "有参构造调用" << endl;
}
Point(const Point& a)
{
p_x = a.p_x;
p_y = a.p_y;
cout << "拷贝构造调用" << endl;
}
~Point()
{ //析构函数,将堆区(程序员自己开辟)数据释放
cout << "默认析构调用" << endl;
}
int p_x; //点x坐标
int p_y;
};
void test()
{
Point p; //会调用默认构造
Point b(0,2); //调用有参构造
cout << "b的横坐标为" << b.p_x << endl;
cout << "b的纵坐标为" << b.p_y << endl;
Point a(b); //调用拷贝构造
cout << "a的横坐标为" << a.p_x << endl;
cout << "a的纵坐标为" << a.p_y << endl;
}
int main()
{
test(); //执行完后会调用默认析构
system("pause");
return 0;
}
/*运行结果为:
默认构造调用
有参构造调用
b的横坐标为0
b的纵坐标为2
拷贝构造调用
a的横坐标为0
a的纵坐标为2
默认析构调用
默认析构调用
默认析构调用
请按任意键继续. . .
*/析构函数执行堆区数据的释放
//构造函数调用测试
#include<iostream>
#include<string>
using namespace std;
class Point
{
public:
Point()
{
cout << "默认构造调用" << endl;
}
Point(int a)
{
p_x = a;
p_y = new int(2); //创建在堆区,由指针去接收
cout << "有参构造调用" << endl;
}
~Point()
{
if (p_y != NULL) //指针不指向空,则释放堆区数据
{
delete p_y;
p_y = NULL;
}
cout << "默认析构调用" << endl;
}
int p_x; //点x坐标
int *p_y;
};
void test()
{
Point p; //会调用默认构造
Point b(0); //调用有参构造
cout << "b的横坐标为" << b.p_x << endl;
cout << "b的纵坐标为" << *b.p_y << endl;
}
int main()
{
test(); //执行完后会调用默认析构
system("pause");
return 0;
}浅拷贝的问题
//浅拷贝带来的问题
#include<iostream>
#include<string>
using namespace std;
class Point
{
public:
Point()
{
cout << "默认构造调用" << endl;
}
Point(int a)
{
p_x = a;
p_y = new int(2); //创建在堆区
cout << "有参构造调用" << endl;
}
Point(const Point& a)
{
p_x = a.p_x;
p_y = a.p_y; //指向同一块堆区内存
cout << "拷贝构造调用" << endl;
}
~Point()
{
if (p_y != NULL)
{
delete p_y;
p_y = NULL;
}
cout << "默认析构调用" << endl;
}
int p_x; //点x坐标
int *p_y;
};
void test()
{
Point p; //会调用默认构造
Point b(0); //调用有参构造
cout << "b的横坐标为" << b.p_x << endl;
cout << "b的纵坐标为" << *b.p_y << endl;
Point a(b); //浅拷贝
cout << "a的横坐标为" << a.p_x << endl;
cout << "a的纵坐标为" << *a.p_y << endl;
//Point a 后定义,但是先被释放,执行析构函数,堆区数据被释放;同样b也会执行相同操作,同一块内存被释放两次,引起错误
}
int main()
{
test(); //执行完后会调用默认析构
system("pause");
return 0;
}深拷贝解决堆区重复释放的问题
//深拷贝测试
#include<iostream>
#include<string>
using namespace std;
class Point
{
public:
Point()
{
cout << "默认构造调用" << endl;
}
Point(int a) //有参构造
{
p_x = a;
p_y = new int(2); //创建在堆区
cout << "有参构造调用" << endl;
}
Point(const Point& a)
{
p_x = a.p_x;
//编译器默认的浅拷贝 p_y = a.p_y;
p_y = new int(*a.p_y); //指针解引用,重新开辟堆区内存——深拷贝
cout << "拷贝构造调用" << endl;
}
~Point()
{
if (p_y != NULL)
{
delete p_y;
p_y = NULL;
}
cout << "默认析构调用" << endl;
}
int p_x; //点x坐标
int *p_y;
};
void test()
{
Point p; //会调用默认构造
Point b(0); //调用有参构造
cout << "b的横坐标为" << b.p_x << endl;
cout << "b的纵坐标为" << *b.p_y << endl;
Point a(b);
cout << "a的横坐标为" << a.p_x << endl;
cout << "a的纵坐标为" << *a.p_y << endl; //执行各自的析构函数,不再报错
}
int main()
{
test(); //执行完后会调用默认析构
system("pause");
return 0;
}初始化列表
//通过初始化列表给类属性赋值
#include<iostream>
#include<string>
using namespace std;
class Phone
{
public:
Phone(string name) //有参构造
{
p_name = name;
}
string p_name;
};
class Student
{
public:
Student(string name,int age,Phone phone):s_name(name),s_age(age),s_phone(phone) //初始化列表
{
}
string s_name;
int s_age;
Phone s_phone; //类的嵌套(一个类作为另一个类的成员变量)
};
void test()
{
Phone p("SAMSUNG");
Student s("张三", 18, p);
cout << "姓名:" << s.s_name << " 年龄:" << s.s_age << " 手机品牌:" << s.s_phone.p_name << endl;
}
int main()
{
test();
system("pause");
return 0;
}
//构造时,先构造Phone(内层),再构造Student(外层),析构的顺序与之相反静态成员变量
1、所有对象共享同一份数据
2、编译阶段就分配内存
3、类内声明,内外初始化
静态成员函数
1、通过对象来访问
2、通过类名来访问
3、只能访问静态成员变量
#include<iostream>
#include<string>
using namespace std;
class Point
{
public:
static void function()
{
cout << "lalall" << endl;
a = 100; //静态成员函数只能访问静态成员变量 非静态成员函数、静态成员函数和静态成员变量,不属于类的对象上,大家共享一份(只有非静态成员变量属于类的对象上)
}
static int a;
};
int Point::a = 0; //静态成员变量,类内声明,类外初始化
void test()
{
Point p;
p.function(); //通过对象访问
Point::function(); //通过类名访问,只有静态成员函数可以,是所有对象共享一份成员函数的体现
}
int main()
{
test(); //执行完后会调用默认析构
system("pause");
return 0;
}只有非静态成员变量属于类的对象上
#include<iostream>
#include<string>
using namespace std;
class Point
{
int a;
int b;
};
void test()
{
Point p;
cout << sizeof(p) << endl; //8
}
int main()
{
test(); //执行完后会调用默认析构
system("pause");
return 0;
}成员变量和形参名称冲突 this指针
#include<iostream>
#include<string>
using namespace std;
class Point
{
public:
Point(int a)
{
a = a; //和成员变量a无关 ,修改方式:1、改名称 2、this->a=a; this指针指向成员函数被调用的对象(该处为p)
//cout << a << endl;
}
int a;
};
void test()
{
Point p(2);
cout << p.a << endl; //乱码
}
int main()
{
test(); //执行完后会调用默认析构
system("pause");
return 0;
}*this返回该对象
#include<iostream>
#include<string>
using namespace std;
class Point
{
public:
Point(int a)
{
this->a = a;
}
Point& ptop(Point& p) //返回类的引用, 如果返回值的话(Point),会新创建类,不再是p2
{
this->a += p.a;
return *this;
}
int a;
};
void test1()
{
Point p1(10);
Point p2(10);
p2.ptop(p1).ptop(p1).ptop(p1); //链式编程
cout << p2.a << endl;
}
int main()
{
test1();
system("pause");
return 0;
}this 指针本质是指针常量
P *const this 即this是指向P的一个指针常量
//指针常量 int * const p = &a; p=&b表达式是错误的,*p = 20是允许的 故:
//P *const this 即this是指向P的一个指针常量
class P
{
public:
P(int a)
{
this->m_a=a; //指针常量所指向的内存地址的值是可以修改的
//this =NULL; //所指向的内存地址是不允许修改的
}
int m_a;
};成员函数后加const 常函数
class Point
{
public:
void print_a(int a) const //常函数,const修饰this指针,this指向内存的值不允许修改
{
//this->m_a = a;
this ->m_b = 100; //允许,mutable定义特殊变量,允许修改
cout << m_a << endl;
}
int m_a;
mutable int m_b;
};
void test()
{
const Point p; //常对象 常对象只能调用常函数,不能调用普通的成员函数
//p.m_a = 100; 不允许修改
p.m_b=100; //允许
}
int main()
{
test();
system("pause");
return 0;
}构造和析构函数上不允许使用类型限定符(如const)
友元(可以访问类中的私有成员)
全局函数做友元
#include<iostream>
#include<string>
using namespace std;
class Building
{
friend void test(Building* building); //全局函数做友元,可以访问私有成员
public:
Building()
{
m_s = "啦啦啦啦";
m_b = "不不不不不不";
}
string m_s;
private:
string m_b;
};
void test(Building* building)
{
string a = building->m_s;
cout << a << endl;
string b = building->m_b;
cout << b << endl;
}
int main()
{
Building building; //默认构造
test(&building);
system("pause");
return 0;
}类做友元
#include<iostream>
#include<string>
using namespace std;
class Building
{
friend class goodguy; //goodguy类做友元
public:
Building();
string m_s;
private:
string m_b;
};
class goodguy
{
public:
void visit();
Building building; //类的嵌套
};
Building::Building() //类外写成员函数(构造函数)
{
m_s = "lallalal";
m_b = "bbbbbbb";
}
void goodguy::visit()
{
cout << building.m_s << endl;
cout << building.m_b << endl;
}
int main()
{
goodguy guy;
guy.visit();
system("pause");
return 0;
}
//不用类的嵌套
#include<iostream>
#include<string>
using namespace std;
class Building
{
friend class goodguy; //类做友元
public:
Building(); //构造函数声明,类外实现
string m_s;
private:
string m_b;
};
class goodguy
{
public:
goodguy();
void visit();
Building* building; //指针
};
Building::Building()
{
m_s = "lallalal";
m_b = "bbbbbbb";
}
goodguy::goodguy() //构造函数实现
{
building = new Building; //堆区开辟一个Building,赋给指针building
}
void goodguy::visit()
{
cout << building->m_s << endl;
cout << building->m_b << endl;
}
int main()
{
goodguy guy;
guy.visit();
system("pause");
return 0;
}成员函数做友元
//(类中的某个成员函数做友元)
#include<iostream>
#include<string>
using namespace std;
class Building;
class goodguy //要把该类写在Building类前面,否则第x行还是会报错
{
public:
goodguy();
void visit();
void visit2();
Building* building;
};
class Building
{
friend void goodguy::visit();
public:
Building();
string m_s;
private:
string m_b;
};
Building::Building()
{
m_s = "lallalal";
m_b = "bbbbbbb";
}
goodguy::goodguy()
{
building = new Building;
}
void goodguy::visit()
{
cout << building->m_s << endl;
cout << building->m_b << endl; //第x行
}
void goodguy::visit2()
{
cout << building->m_s << endl;
}
int main()
{
goodguy guy;
guy.visit();
guy.visit2();
system("pause");
return 0;
}运算符重载(加法)
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
Person operator+(Person& a); //重载运算符-也是类似
int m_a;
int m_b;
};
Person Person::operator+(Person& a) //成员函数重载+号
{
Person c;
c.m_a = this->m_a + a.m_a;
c.m_b = this->m_b + a.m_b;
return c;
}
//Person operator+(Person& a, Person& b) //全局函数重载+号
//{
// Person c;
// c.m_a = a.m_a + b.m_a;
// c.m_b = a.m_b + b.m_b;
// return c;
//}
Person operator+(Person &a,int b) //函数重载,函数名相同,但是参数不同
{
Person c;
c.m_a = a.m_a + b;
c.m_b = a.m_b + b;
return c;
}
void test()
{
Person a;
a.m_a = 10;
a.m_b = 20;
Person b;
b.m_a = 10;
b.m_b = 20;
Person c = a + b; //本质上是 Person c = a.operator+(b); Person c = operator+(a,b)
cout << c.m_a << endl;
cout << c.m_b << endl;
Person d = a+10; //Person + int
cout<<d.m_a<<endl; //20
cout<<d.m_b<<endl; //30
}
int main()
{
test();
system("pause");
return 0;
}运算符重载(左移运算符)
//(直接输出类的成员变量的值)
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
Person(int a, int b) //有参构造函数可以解决私有成员访问问题
{
m_a = a;
m_b = b;
}
friend ostream& operator<<(ostream& cout, Person a);
private:
int m_a;
int m_b;
};
ostream& operator<<(ostream &cout, Person a) //cout 数据类型为标准输出流ostream,且cout唯一所以要用引用
{
cout << a.m_a << " " << a.m_b;
return cout;
}
void test()
{
Person a(10, 20);
cout << a << endl; //本质上是operator<<(cout,a)
}
int main()
{
test();
system("pause");
return 0;
}编译器默认提供的类的函数
1、默认构造
2、默认析构
3、拷贝构造
4、赋值运算符 operator=,(类可以直接进行赋值运算)
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
Person(int age)
{
m_age = new int(age); //将age数据开辟到堆区
}
int* m_age;
};
void test()
{
Person p1(18);
cout << "p1的年龄为:" << *p1.m_age << endl;
Person p2(20);
p2 = p1; //直接进行赋值运算
cout << "p2的年龄为:" << *p2.m_age << endl;
}
int main()
{
test();
system("pause");
return 0;
}运算符重载(赋值运算)
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
Person(int age)
{
m_age = new int(age); //将age数据开辟到堆区
}
Person& operator=(Person& a)
{
if (m_age != NULL)
{
delete m_age;
m_age = NULL;
}
this->m_age = new int(*a.m_age); //深拷贝,解决堆区重复释放的问题,返回Person的引用是为了连续赋值
return *this;
}
int* m_age;
};
void test()
{
Person p1(18);
cout << "p1的年龄为:" << *p1.m_age << endl;
Person p2(20);
Person p3(30);
p3 =p2 = p1; //直接进行赋值运算
cout << "p2的年龄为:" << *p2.m_age << endl;
cout << "p3的年龄为:" << *p3.m_age << endl;
}
int main()
{
test();
system("pause");
return 0;
}继承
class 子类 : 继承方式 父类
#include<iostream>
#include<string>
using namespace std;
class basepage
{
public:
void header()
{
cout << "aaaaaa" << endl;
}
void footer()
{
cout << "bbbbbb" << endl;
}
void left()
{
cout << "ccccccc" << endl;
}
void right()
{
cout << "dddddddd" << endl;
}
};
class java:public basepage
{
public:
void content()
{
cout << "this is java" << endl;
}
};
void test()
{
java ja;
ja.header();
ja.footer();
ja.left();
ja.right();
ja.content();
}
int main()
{
test();
system("pause");
return 0;
}继承方式
父类中的private,子类不可访问
1、公共继承
class 子类 : public 父类
public——public
protected—— protected
2、保护继承
class 子类 : protected 父类
public、protected——protected
3、私有继承
class 子类 : private 父类
public、protected——private
利用开发人员命令提示工具查看对象模型
C:\Users\xx\source\repos\Project1\Project1>cl /d1 reportSingleClassLayoutbasepage 源.cpp
//C:\Users\xx\source\repos\Project1\Project1>为cpp文件所在路径 basepage为类名子类中同名属性的访问
#include<iostream>
#include<string>
using namespace std;
class base
{
public:
base()
{
m_a = 100;
}
int m_a;
};
class son :public base
{
public:
son()
{
m_a = 200;
}
int m_a ;
};
void test()
{
son s;
cout << s.m_a << endl; //直接访问为子类的属性
cout << s.base::m_a << endl; //父类中同名属性访问需要加上作用域
}
int main()
{
test();
system("pause");
return 0;
}
#include<iostream>
#include<string>
using namespace std;
class base
{
public:
base()
{
m_a = 100;
}
void aaaa()
{
m_a = 200;
}
void aaaa(int b)
{
m_a = 500;
}
int m_a;
};
class son :public base
{
public:
son()
{
m_a = 300;
}
void aaaa()
{
m_a = 400;
}
int m_a ;
};
void test()
{
son s;
s.aaaa();
cout << s.m_a << endl; //400
s.base::aaaa();
cout << s.base::m_a << endl; //200
s.base::aaaa(10); //只要出现同名,父类中的函数都会被隐藏必须加作用域才能访问
cout << s.base::m_a << endl; //500
}
int main()
{
test();
system("pause");
return 0;
}多继承
class 子类 :public 父类1,public 父类2……
#include<iostream>
#include<string>
using namespace std;
class base1
{
public:
base1()
{
m_a = 100;
}
int m_a;
};
class base2
{
public:
base2()
{
m_b = 200;
}
int m_b;
};
class son :public base1,public base2 //多继承
{
public:
son()
{
m_c = 300;
}
int m_c ;
};
void test()
{
son s;
cout << s.m_a << endl;
cout << s.m_b << endl;
cout << s.m_c << endl;
}
int main()
{
test();
system("pause");
return 0;
}父类的引用指向子类的对象
class Animal
{
public:
void speak()
{
cout << "动物在说话" << endl;
}
};
class cat:public Animal
{
public:
void speak()
{
cout << "猫在说话" << endl;
}
};
void dospeak(Animal &animal)
{
animal.speak(); //编译的时候提前分配空间,输出一定是“动物在说话”
}
void test()
{
cat a;
dospeak(a); //允许父类的引用指向子类的对象 Animal &animal = cat,不需要做类型转换
}动态多态(父类函数前加virtual)
满足条件
1、有类的继承关系
2、子类重写父类的虚函数(函数返回类型、函数名、参数条件都相同)
3、全局函数中父类通过指针或引用指向子类对象
class Calculator
{
public:
virtual int get_result()=0;
//纯虚函数
//有纯虚函数的类称为抽象类
//1、不能实例化对象;2、子类需重写纯虚函数,否则仍为抽象类
int a;
int b;
}; //抽象的计算器类
class ADDCalculator : public Calculator
{
public:
int get_result()
{
int c = this->a + this->b;
return c;
}
};
class MULCalculator : public Calculator
{
public:
int get_result()
{
int c = this->a * this->b;
return c;
}
};
class SUBCalculator : public Calculator
{
public:
int get_result()
{
int c = this->a - this->b;
return c;
}
};
void test()
{
//多态的两种实现方式
//1、父类的指针指向子类的对象
Calculator* abc = new SUBCalculator;
abc->a = 10;
abc->b = 20;
int c = abc->get_result();
cout << c << endl;
delete abc;
//2、父类的引用指向子类的对象
SUBCalculator A;
Calculator& cal = A;
cal.a = 10;
cal.b = 10;
int d = cal.get_result();
cout << d << endl;
}
文章标题:c++学习
本文作者:Echo
发布时间:2020-11-17, 22:55:06
最后更新:2020-11-27, 22:34:26
原始链接:http://dmzecho.github.io/2020/11/17/c++%E5%AD%A6%E4%B9%A0/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。