2021自学C++核心编程之类和对象特性之一封装(四)

4 类和对象

C++面向对象的三大特性为:封装、继承、多态

C++以万事万物都皆为对象,对象上有其属性和行为

例如:

人可以作为对象,其属性有姓名、年龄、身高、体重…,行为有走、跑、跳、吃饭、唱歌…

车也可以作为对象,其属性有轮胎、方向盘、车灯…,行为有载人、放音乐、放空调…

具有相同性质的对象,我们可以抽象称为,人属于人类,车属于车类

4.1 封装

4.1.1 封装的意义

封装是C++面向对象三大特性之一

封装的意义:

  • 将属性和行为作为一个整体,表现生活中的事物
  • 将属性和行为加以权限控制

封装意义一: 在设计类的时候,属性和行为写在一起,表现事物

语法格式:

 class 类名{   
 	访问权限: 
        属性;
     访问权限: 
     	行为;  
 };

示例1: 设计一个圆类,求圆的周长

示例代码:

#include<iostream>
using namespace std;
//定义一个常量PI来代表圆周率
const double PI = 3.14;

//封装一个圆类,class代表设计一个类,类名为Circle
class Circle{
public:  //访问权限:代表公共的权限,即所有其他类都可以创建园类实例化对象之后,获取园类的属性和调用园类的方法

	//属性列表
	//半径
	int m_r;

	//行为列表
	//获取到圆的周长
	double calculateZC(){
		//获取圆的周长公式:2 * pi  * r,并返回计算结果!
		return  2 * PI * m_r;
	}
};

int main() {

	//通过圆类,创建圆的实例化对象c1,就是一个真实的园,简而言之,园类是一个模具,c1是模具制作出来的实物
	Circle c1;
	//注意:给圆对象c1属性半径进行赋值通过对象.属性方式操作
	c1.m_r = 10; 
	//注意:给圆对象c1方法调用通过对象.方法方式操作获取计算结果
	cout << "圆的周长为: " << c1.calculateZC() << endl;

	system("pause");
	return 0;
}

示例2: 设计一个学生类,属性有姓名和学号,可以给姓名和学号赋值,可以显示学生的姓名和学号

代码示例:

#include<iostream>
using namespace std;
class Student {

//属性:类中属性即为成员属性,也可以称为成员变量
public://访问权限:代表公共的权限
	//姓名
	string m_Name;
	//学号
	int m_Id;

//方法列表:类中方法即为成员方法,也可以称为成员函数
public:
	//定义一个showStudent方法来展示学生姓名和学号
	void showStudent() {
		cout << "学生姓名:" << m_Name << " 学号:" << m_Id << endl;
	}
	//定义一个无返回值方法setName来给Student类中m_Name属性进行赋值
	void setName(string name) {
		m_Name = name;
	}
	//定义一个有返回值类型方法getName来获取Student类中m_Name属性中的值,注意:返回值类型需要和返回的属性值的类型对应
	string getName() {
		return m_Name;
	}
	//定义一个无返回值方法setId来给Student类中m_Id属性进行赋值
	void setId(int id) {
		m_Id = id;
	}
	//定义一个有返回值类型方法getId来获取Student类中m_Id属性中的值
	int getId() {
		return m_Id;
	}
};
int main() {
	//通过Student类,创建实例化对象stu
	Student stu;
	//注意:给对象stu属性进行赋值通过对象.属性方式操作
	stu.m_Name = "qzp";
	stu.m_Id = 1001;
	//注意:给圆对象stu1方法调用通过对象.方法方式操作来展示学生姓名和学号
	stu.showStudent();

	//注意:通过Student类中方法给实例化对象stu属性进行赋值通过对象.setxxx(value)方式操作
	stu.setName("QZP");
	stu.setId(1111);
	//注意:通过Student类中方法给实例化对象stu属性进行获取值通过对象.getxxx()方式操作
	cout << "学生姓名:" << stu.getName() << " 学号:" << stu.getId() << endl;

	system("pause");
	return 0;
}

总结:

  • 使用对象属性:对象名.成员变量
  • 使用对象方法:对象名.方法名
  • 同一个类的每一个对象有不同的成员变量的存储空间
  • 同一个类中成员方法中可以定义set方法来来使用对象属性进行赋值以及get方法来获取对象属性的值
  • 同一个类的每个对象共享该类的方法

封装意义二: 类在设计时,可以把属性和行为放在不同的权限下,加以控制

访问权限权限含义权限范围
public公共权限类内可以访问 类外可以访问
protected保护权限类内可以访问 类外不可以访问
private私有权限类内可以访问 类外不可以访问

代码示例:

#include<iostream>
using namespace std;
//定义一个Person类
class Person {
//成员变量
public://公共权限
	//姓名,简单理解:在公共场合,所有人都可以称呼你的姓名
	string m_Name;
protected://保护权限
	//汽车之主,简单理解:在手续完成后,你对该车就有了保护权限,任何其他人使用都需要经过你的允许
	string m_Car_Owner;
private://私有权限
	//银行卡密码,简单理解:你的经济收入都在这个卡里,任何其他人都无权使用
	int m_Bank_Card_Password;

//成员方法
public:
	void setPersonFormation() {
		//所有权限的成员变量均可以在本类中访问
		m_Name = "qzp";
		m_Car_Owner = "qzp";
		m_Bank_Card_Password = 123456;
		cout << "姓名: " << m_Name << " 车主:" << m_Car_Owner << " 银行卡密码:" << m_Bank_Card_Password << endl;
	}
};

int main() {
	//创建一个Person实例化对象p
	Person p;
	//使用对象属性:对象名.成员变量
	p.m_Name = "qzy";//公共权限可以访问
	//p.m_Car_Owner = "qzy";//保护权限类外访问不到
	//p.m_Bank_Card_Password = 999999;//私有权限类外访问不到

	//使用对象方法:对象名.方法名
	p.setPersonFormation();
	system("pause");
	return 0;
}
4.1.2 struct和class区别

在C++中 struct和class唯一的区别就在于 默认的访问权限不同

区别:

  • struct默认为公共权限
  • class默认为私有权限
#include<iostream>
using namespace std;
//定义一个C1类
//注意:当类中的成员变量和成员方法没有用关键字权限来控制,默认为私有权限,类外不可访问
class C1 {
	int m_A; //默认是私有权限
	void function() {
		m_A = 1000;
		cout << m_A <<endl;
	}
};
//定义一个C2结构体
//注意:当结构体中的成员变量和成员方法没有用关键字权限来控制,默认为公共权限,均可访问
struct C2 {
	int m_A;  //默认是公共权限
	void function() {
		m_A = 1000;
		cout << m_A << endl;
	}
};

int main() {
    //创建一个C1类实例化对象c1
	C1 c1;
	//c1.m_A = 10; //错误,不可访问,访问权限默认是私有权限
	//c1.function();//错误,不可访问,访问权限默认是私有权限
    //结构体变量创建,注意:struct 关键字可以省略
	struct C2 c2;
	c2.m_A = 10; //正确,访问权限默认是公共权限
	c2.function();//正确,访问权限默认是公共权限
	system("pause");
	return 0;
}
4.1.3 成员属性设置为私有

优点1: 将所有成员属性设置为私有,可以自己控制读写权限

优点2: 对于写权限,我们可以检测数据的有效性

代码示例:

#include<iostream>
using namespace std;
class People {
//成员变量均为私有权限,类外无法访问,在公共权限下通过set方法和get成员方法来控制对私有属性的访问
private:
	//姓名(可读可写) 
	string m_Name; 
	//年龄(可读可写) 
	int m_Age = 0; 
	//爱人(只写)
	string m_Lover; 
//成员方法均为公共权限
public:
	//定义setName/getName方法对m_Name可读可写
	void setName(string name) {
		m_Name = name;
	}
	string getName(){
		return m_Name;
	}
	//定义setAge/getAge方法对m_Age可读可写
	void setAge(int age) {
		//对于输入的年龄进行校验来判断数据是否有效
		if (age < 0 || age > 150) {
			cout << "你已成仙!" << endl;
			return;
		}
		m_Age = age;
	}
	int getAge() {
		return m_Age;
	}
	//定义setLover方法对m_Lover可写
	void setLover(string lover) {
		m_Lover = lover;
	}
};

int main() {
	//创建一个实例化对象
	People p;
	//姓名设置
	p.setName("qzp");
	cout << "姓名: " << p.getName() << endl;
	//年龄设置
	p.setAge(25);
	cout << "年龄: " << p.getAge() << endl;
	//爱人设置
	p.setLover("FL");
	//cout << "爱人: " << p.getLover() << endl;  //报错,无getLover方法,只写属性,不可以读取
	system("pause");
	return 0;
}

练习案例1:设计立方体类

设计立方体类(Cube)

求出立方体的面积和体积

分别用全局函数和成员函数判断两个立方体是否相等。

在这里插入图片描述

代码示例:

#include<iostream>
using namespace std;
//立方体类设计
//1.创建一个立方体类
//2.设计属性:长、宽、高
//3.设计行为:获取立方体的面积和体积
//4.分别利用全局函数和成员函数,判断两个立方体是否相等
class Cube {
//成员变量
private:
	//长
	int m_Length;
	//宽
	int m_Width;
	//高
	int m_Height;
//成员方法
public:
	//设置长度
	void setLength(int length) {
		m_Length = length;
	}
	//获取长度
	int getLength() {
		return m_Length;
	}
	//设置宽度
	void setWidth(int width) {
		m_Width = width;
	}
	//获取宽度
	int getWidth() {
		return m_Width;
	}
	//设置高度
	void setHeight(int height) {
		m_Height = height;
	}
	//获取高度
	int getHeight() {
		return m_Height;
	}
	//获取立方体的表面积
	int surface_Area() {
		return 2 * m_Length + 2 * m_Width + 2 * m_Height;
	}
	//获取立方体的体积
	int volume() {
		return  m_Length * m_Width * m_Height;
	}
	//利用成员函数判断两个立方体是否相等
	bool isSameByClass(Cube &otherCube) {
		if (m_Length == otherCube.m_Length && m_Width == otherCube.m_Width && m_Height == otherCube.m_Height) {
			return 1;
		}
		return 0;
	}
};
//利用全局函数判断两个立方体是否相等
bool isSame(Cube &c1,Cube &c2) {
	return (c1.getLength() == c2.getLength() ? 1 : 0) && (c1.getWidth() == c2.getWidth() ? 1 : 0) && (c1.getHeight() == c2.getHeight() ? 1 : 0);
}
int main() {
	//创建第一个立方体
	//Cube类实例化对象c1
	Cube c1;
	//因对象的属性是私有权限,通过公共权限的成员方法set给对象的属性赋值
	c1.setLength(10);
	c1.setWidth(10);
	c1.setHeight(10);
	//获取c1的表面积和体积
	cout << "c1的表面积为:" << c1.surface_Area() << endl;
	cout << "c1的体积为:" << c1.volume() << endl;

	//创建第二个立方体
	//Cube类实例化对象c2
	Cube c2;
	//因对象的属性是私有权限,通过公共权限的成员方法set给对象的属性赋值
	c2.setLength(10);
	c2.setWidth(11);
	c2.setHeight(10);
	//获取c1的表面积和体积
	cout << "c1的表面积为:" << c2.surface_Area() << endl;
	cout << "c1的体积为:" << c2.volume() << endl;

	bool flag1 = isSame(c1,c2);
	string result1 = flag1 ? "相等" : "不相等";
	cout << "全局函数判断c1和c2" << result1 << endl;

	bool flag2 = c1.isSameByClass(c2);
	string result2 = flag2 ? "相等" : "不相等";
	cout << "成员函数判断c1和c2" << result2 << endl;
	system("pause");
	return 0;
}

练习案例2:点和圆的关系

设计一个圆形类(Circle),和一个点类(Point),计算点和圆的关系。

在这里插入图片描述

代码示例:

#include<iostream>
using namespace std;
//设置一个点类
class Point {
//成员变量
private:
	//x坐标
	int m_x;
	//y坐标
	int m_y;
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;
	}
};
//设计园类
class Circular {
private:
	//半径
	int m_r;
	//圆心
	//注意:在类中可以引用另一个类作为本类中的成员
	Point m_Center;
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;
	}
};
//判断点和圆的关系
void showPointAndCircleRelation(Circular &c,Point &p) {
	//计算圆心和点之间的距离
	double distance = pow(pow(abs(c.getCenter().getX() - p.getX()), 2) + pow(abs(c.getCenter().getY() - p.getY()), 2),0.5);
	//计算圆的半径
	double radius = c.getR();
	if (distance > radius) {
		cout << "点在圆外" << endl;
	}
	else if (distance == radius) {
		cout << "点在圆上" << endl;
	}
	else {
		cout << "点在圆内" << endl;
	}
}
int main() {
	//创建一个圆
	Circular c;
	//设置圆的半径
	c.setR(5);
	//创建圆心
	Point center;
	center.setX(5);
	center.setY(0);
	c.setCenter(center);
	//创建一个点
	Point spot;
	spot.setX(1);
	spot.setY(3);

	//调用showPointAndCircleRelation函数判断圆和点之间的关系
	showPointAndCircleRelation(c,spot);

	system("pause");
	return 0;
}

针对于上述代码,一个程序中定义了多个类的情况,代码太长,可读性太差,代码不灵活,如何解决呢?

步骤如下:

  1. 在头文件中定义一个point.h文件
#pragma once
//为了防止头文件重复包含
#include<iostream>
using namespace std;
//设置一个点类
class Point {
	//成员变量
private:
	//x坐标
	int m_x;
	//y坐标
	int m_y;
//所有类中成员函数皆为声明,不做具体实现
public:
	//设置x坐标
	void setX(int x);
	//获取x坐标
	int getX();
	//设置y坐标
	void setY(int y);
	//获取y坐标
	int getY();
};
  1. 在源文件中定义一个point.cpp文件
//引入头文件
#include "point.h";
//注意:
// 1.源文件point.cpp只负责Point类中成员函数的实现
// 2.需要使用类名::指明所有函数是Point类中成员函数的实现
//设置x坐标
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;
}

3.同理,对于Circular类,我们也需要这种操作,在头文件中定义一个circular.h文件

#pragma once
#include<iostream>
using namespace std;
#include "point.h"

//设计园类
class Circular {
private:
	//半径
	int m_r;
	//圆心
	//注意:在类中可以引用另一个类作为本类中的成员
	Point m_Center;
public:
	//设置半径
	void setR(int r);
	//获取半径
	int getR();
	//设置圆心
	void setCenter(Point center);
	//获取圆心
	Point getCenter();
};
  1. 在源文件中定义一个circular.cpp文件
#include "circular.h"

//设置半径
void Circular::setR(int r) {
	m_r = r;
}
//获取半径
int Circular::getR() {
	return m_r;
}
//设置圆心
void Circular::setCenter(Point center) {
	m_Center = center;
}
//获取圆心
Point Circular::getCenter() {
	return m_Center;
}
  1. 测试
#include<iostream>
using namespace std;
#include "point.h"
#include "circular.h"

//判断点和圆的关系
void showPointAndCircleRelation(Circular &c,Point &p) {
	//计算圆心和点之间的距离
	double distance = pow(pow(abs(c.getCenter().getX() - p.getX()), 2) + pow(abs(c.getCenter().getY() - p.getY()), 2),0.5);
	//计算圆的半径
	double radius = c.getR();
	if (distance > radius) {
		cout << "点在圆外" << endl;
	}
	else if (distance == radius) {
		cout << "点在圆上" << endl;
	}
	else {
		cout << "点在圆内" << endl;
	}
}
int main() {
	//创建一个圆
	Circular c;
	//设置圆的半径
	c.setR(5);
	//创建圆心
	Point center;
	center.setX(5);
	center.setY(0);
	c.setCenter(center);
	//创建一个点
	Point spot;
	spot.setX(1);
	spot.setY(3);

	//调用showPointAndCircleRelation函数判断圆和点之间的关系
	showPointAndCircleRelation(c,spot);

	system("pause");
	return 0;
}

读万卷书,行万里路,博主会持续更新学习笔记,如有问题,可以留言和私信,我们一起进步!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

QZP51ZX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值