【C++】C++核心编程(四)---类与对象(封装)

1.属性和行为作为整体

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

C++认为万事万物都皆为对象,对象上有其属性行为
人可以作为对象,属性有姓名、年龄、身高、体重…行为有走、跑、跳、吃饭、睡觉…
车也可以作为对象,属性有车牌、车灯、轮胎…行为有载人、放音乐…
具有相同性质的对象,我们可以抽象称为类,人属于人类,车属于车类

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

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

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

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

案例:设计一个圆类,求圆的周长和面积

  • 代码实现:
#include <iostream>
using namespace std;
// #define PI 3.14 (宏常量)
const double PI = 3.14;
class Circle
{
// 访问权限:公共权限
public:
	// 属性 半径
	int c_R;
	// 行为1 返回圆的周长
	double circleL()
	{
		return 2 * PI * c_R;
	}
	// 行为2 返回圆的面积
	double circleS()
	{
		return PI * c_R * c_R;
		//return PI * (c_R ^ 2); //写成这样为啥返回25.12???
	}
};

int main() {
	// 创建一个圆类对象c1
	// 实例化(通过一个类,创建一个对象的过程)
	Circle c1;
	c1.c_R = 10; //给对象c1半径属性赋值
	
	cout << "圆对象c1的周长为: " << c1.circleL() << endl;
	cout << "圆对象c1的面积为: " << c1.circleS() << endl;

	system("pause");
	return 0;
}
  • 输出结果:
圆对象c1的周长为: 62.8
圆对象c1的面积为: 314
请按任意键继续. . .

注意:在C++中^符号表示按位异或运算符。参与运算的两个值,如果两个相应位相同,则结果为0,否则为1。如:10^2=8(10转化为二进制为0000 1010,2转化为二进制为0000 0010,运算后得到的结果为:0000 1000)。在这里也就可以解释为什么PI * (c_R ^ 2) = 25.12了。

2.案例-设计学生类

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

  • 代码实现:
#include <iostream>
using namespace std;
#include <string>

// 创建一个学生类
class Student
{
// 权限设置
public:
	// 属性 姓名和学号
	string s_Name;
	int s_Id;

	// 行为1 姓名赋值
	void setName(string name)
	{
		s_Name = name;
	}
	// 行为2 姓名获取
	string getName()
	{
		return s_Name;
	}
	// 行为3 学号赋值
	void setId(int id)
	{
		s_Id = id;
	}
	// 行为4 学号获取
	int getId()
	{
		return s_Id;
	}
};

void test()
{
	// 创建一个学生对象s1
	Student s1;
	// 给对象的属性赋值(利用赋值函数)
	s1.setName("张三李四");
	s1.setId(20221120);
	// 获取对象的属性信息(利用获取函数)
	cout << "学生s1的姓名为:" << s1.getName() << endl;
	cout << "学生s1的学号为:" << s1.getId() << endl;
}

int main() {

	test();

	system("pause");
	return 0;
}
  • 输出结果:
学生s1的姓名为:张三李四
学生s1的学号为:20221120
请按任意键继续. . .

知识点补充:
类中的属性和行为 我们统一称为 成员
属性:又称为成员属性或者成员变量
行为:又称为成员函数或者成员方法

3.访问权限

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

访问权限有三种:

  1. public 公共权限(类内可以访问 类外也可以访问)
  2. protected 保护权限(类内可以访问 类外不可以访问 子类可以访问父类)
  3. private 私有权限(类内可以访问 类外不可以访问 子类不能访问父类)
  • 代码演示:
#include <iostream>
using namespace std;
#include <string>

class Person
{
// 1、公共权限
public:
	string p_Name;
	int p_Age;
	void getNameAge()
	{
		cout << "姓名:" << p_Name << "\t" << "年龄:" << p_Age << endl;
	}
// 2、保护权限
protected:
	int p_Height;
	void getHeight()
	{
		cout << "身高:" << p_Height << endl;
	}
// 3、私有权限
	int p_Idcard;
	void getIdcard()
	{
		cout << "身份证号:" << p_Idcard << endl;
	}
};

int main() {

	// 实例化具体对象
	Person p1;

	// 1、访问公共权限类信息
	p1.p_Name = "张三李四";
	p1.p_Age = 18;
	p1.getNameAge();

	// 2、访问保护权限类信息。类外不能访问
	//p1.p_Height = 160;
	//p1.getHeight();

	// 3、访问私有权限类信息。类外不能访问
	//p1.p_Idcard = 1234567890;
	//p1.getIdcard();

	system("pause");
	return 0;
}
  • 输出结果:
姓名:张三李四  年龄:18
请按任意键继续. . .

4.C++中struct和class的区别

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

  1. struct默认权限为公共权限
  2. class默认权限为私有权限
  • 代码演示:
#include <iostream>
using namespace std;

// struct默认为公共权限
struct Person
{
	// 属性
	int p_Age;
	// 行为
	void getAge()
	{
		cout << "年龄:" << p_Age << endl;
	}
};

// class默认为私有权限
class Car
{
	// 属性
	int c_Id;
	// 行为
	void getId()
	{
		cout << "车牌号:" << c_Id << endl;
	}
};

int main() {

	// 创建类对象
	Person p1;
	Car c1;
	p1.p_Age = 18;
	p1.getAge();
	// class创建的类默认权限为私有权限,内外不能访问
	//c1.c_Id;
	//c1.getId();


	system("pause");
	return 0;
}
  • 输出结果:
年龄:18
请按任意键继续. . .

5.成员属性私有化

成员属性设置为私有的优点:

  1. 将所有成员属性设置为私有,可以控制读写权限
  2. 对于写权限,我们可以检测数据的有效性

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

  • 优点一代码演示:
#include <iostream>
using namespace std;
#include <string>

class Person
{
public:
	// 姓名可读可写
	void setName(string name)
	{
		p_Name = name;
	}
	void getName()
	{
		cout << "姓名:" << p_Name << endl;
	}
	// 年龄只读
	void getAge()
	{
		p_Age = 0;
		cout << "年龄:" << p_Age << endl;
	}
	// 身份证信息只写
	void setIdcard(int idcard)
	{
		p_Idcard = idcard;
	}

private:
	string p_Name;
	int p_Age;
	int p_Idcard;
};

int main() {

	Person p1;
	// 姓名可读可写
	p1.setName("张三李四");
	p1.getName();

	// 年龄只读
	p1.getAge();
	// p1.p_Age = 18; // 年龄只读不能写

	// 身份证号只写不可读
	p1.setIdcard(1234567890);
	// p1.setIdcard(); //身份证号只可写不可读

	system("pause");
	return 0;
}
  • 输出结果:
姓名:张三李四
年龄:0
请按任意键继续. . .

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

  • 代码演示:
#include <iostream>
using namespace std;
#include <string>

class Person
{
public:
	void setAge(int age)
	{
		if (age < 0 || age > 120) // 写权限,用来检测数据的有效性
		{
			cout << "年龄超过正常人范围!" << endl;
			return;
		}
		p_Age = age;
	}
	void getAge()
	{
		//p_Age = 0;
		cout << "年龄:" << p_Age << endl;
	}
private:
	int p_Age;
};

int main() {

	Person p1;
	p1.setAge(100);
	p1.getAge();

	system("pause");
	return 0;
}
  • 输出结果:
年龄:100
请按任意键继续. . .

【注】:若年龄超过120岁或者小于0岁,将会输出“年龄超过正常人的范围!,并且年龄出现乱码”

6.设计案例1-立方体类

案例描述:设计立方体类(Cube)求出立方体的面积和体积,分别用全局函数和成员函数判断两个立方体是否相等。

实现分析:立方体相等,通过条件长宽高都相等即可判断出来,一种是利用全局函数来进行判断;另一种是利用成员函数来进行判断。

  • 代码实现:
#include <iostream>
using namespace std;

class Cube
{
public:
	void setL(int l) //设置长宽高
	{
		c_L = l;
	}
	void setW(int w)
	{
		c_W = w;
	}
	void setH(int h)
	{
		c_H = h;
	}
	int getL() //获取长宽高
	{
		return c_L;
	}
	int getW()
	{
		return c_W;
	}
	int getH()
	{
		return c_H;
	}
	int getZC()  //获取周长
	{
		return 2*(c_L * c_W + c_L * c_H + c_W * c_H);
	}
	int getV() //获取体积
	{
		return c_L * c_W * c_H;
	}
	
	// 2、利用成员函数来判断立方体是否相等(只需要传入一个参数)
	bool isSample0(Cube &c_l_1)
	{
		cout << "2、调用成员函数来判断两个立方体是否相等!" << endl;
		if (c_l_1.getL() == getL() && c_l_1.getW() == getW() && c_l_1.getH() == getH())
		{
			cout << "(1)两个立方体相等!" << endl;
			return true;
		}
		cout << "(2)两个立方体不相等!" << endl;
		return false;
	}

private:
	int c_L; //长
	int c_W; //宽
	int c_H; //高
};

// 1、利用全局函数来判断两个立方体是否相等(需要传入两个参数)
bool isSample(Cube &c_g_1,Cube &c_g_2)
{
	cout << "1、调用全局函数来判断两个立方体是否相等!" << endl;
	if (c_g_1.getL() == c_g_2.getL() && c_g_1.getW() == c_g_2.getW() && c_g_1.getH() == c_g_2.getH())
	{
		cout << "(1)两个立方体相等!" << endl;
		return true;
	}
	cout << "(2)两个立方体不相等!" << endl;
	return false;
}

void test()
{
	Cube c1;
	c1.setL(10);
	c1.setW(10);
	c1.setH(10);
	cout << "正方体c1的周长为:" << c1.getZC() << endl;
	cout << "正方体c1的体积为:" << c1.getV() << endl;

	Cube c2;
	c2.setL(10);
	c2.setW(9);
	c2.setH(11);
	cout << "正方体c2的周长为:" << c2.getZC() << endl;
	cout << "正方体c2的体积为:" << c2.getV() << endl;

	Cube c3;
	c3.setL(10);
	c3.setW(9);
	c3.setH(11);
	cout << "正方体c3的周长为:" << c3.getZC() << endl;
	cout << "正方体c3的体积为:" << c3.getV() << endl;

	isSample(c1,c2); //调用全局函数
	c2.isSample0(c3); //调用成员函数
}

int main() {

	test();

	system("pause");
	return 0;
}
  • 输出结果:
正方体c1的周长为:600
正方体c1的体积为:1000
正方体c2的周长为:598
正方体c2的体积为:990
正方体c3的周长为:598
正方体c3的体积为:990
1、调用全局函数来判断两个立方体是否相等!
(2)两个立方体不相等!
2、调用成员函数来判断两个立方体是否相等!
(1)两个立方体相等!
请按任意键继续. . .

此案例实现的关键在于第二步,分别利用全局函数与局部函数来判断两个立方体是否相等。利用全局函数实现与利用局部函数实现两者是有差别的。

7.设计案例2-点和圆的关系

案例描述:设计圆形类(Circle),和一个点类(Point)求出点和圆的关系

实现分析:
(p_x,p_y)到圆心(c_x,c_y)的距离pc_l
pc_l == c_r 点在圆上;
pc_l < c_r 点在圆内;
pc_l > c_r 点在圆外;
代码实现思路:
1、常规思路,写两个类(点类和圆类),写成员属性和行为,然后进行位置关系的判断
2、在圆类中写入点类作其成员,然后进行位置关系的判断【在类中可以让另一个类 作为本类中的成员

  • 思路一代码实现:
#include<iostream>
using namespace std;
// 创建圆类
class Circle
{
public:
	// 设置属性
	void setR(int r)
	{
		c_R = r;
	}
	void setX(int x)
	{
		c_X = x;
	}
	void setY(int y)
	{
		c_Y = y;
	}
	// 获取属性
	int getR()
	{
		return c_R;
	}
	int getX()
	{
		return c_X;
	}
	int getY()
	{
		return c_Y;
	}

private:
	int c_R;
	int c_X;
	int c_Y;
};

// 创建点类
class Point
{
public:
	// 设置属性
	void setX(int x)
	{
		p_X = x;
	}
	void setY(int y)
	{
		p_Y = y;
	}
	// 获取属性
	int getX()
	{
		return p_X;
	}
	int getY()
	{
		return p_Y;
	}

private:
	int p_X;
	int p_Y;
};

void getCirclePoint(Circle &c, Point &p)
{
	if ((c.getX() - p.getX()) * (c.getX() - p.getX()) + (c.getY() - p.getY()) * (c.getY() - p.getY()) 
		== c.getR() * c.getR())
	{
		cout << "点与圆的位置关系为:点在圆上" << endl;
	}
	else if ((c.getX() - p.getX()) * (c.getX() - p.getX()) + (c.getY() - p.getY()) * (c.getY() - p.getY())
		< c.getR() * c.getR())
	{
		cout << "点与圆的位置关系为:点在圆内" << endl;
	}
	else
	{
		cout << "点与圆的位置关系为:点在圆外" << endl;
	}
}

int main() {

	Circle c1;
	Point p1;
	c1.setR(10);
	c1.setX(10);
	c1.setY(10);
	p1.setX(10);
	p1.setY(-1);

	getCirclePoint(c1, p1);

	system("pause");
	return 0;
}
  • 输出结果:
点与圆的位置关系为:点在圆外
请按任意键继续. . .
  • 思路二代码实现:
#include<iostream>
using namespace std;
//创建点类
class Point
{
public:
	//设置属性
	void setX(int x)
	{
		p_X = x;
	}
	void setY(int y)
	{
		p_Y = y;
	}
	// 获取属性
	int getX()
	{
		return p_X;
	}
	int getY()
	{
		return p_Y;
	}

private:
	int p_X;
	int p_Y;
};

//创建圆类
class Circle
{
public:
	// 设置属性
	void setR(int r)
	{
		c_R = r;
	}
	void setCenter(Point &center)
	{
		c_Center = center;
	}

	// 获取属性
	int getR()
	{
		return c_R;
	}
	Point getCenter()
	{
		return c_Center;
	}

private:
	int c_R;
	Point c_Center;
};

void getCirclePoint(Circle &c, Point &p)
{
	int centerpoint_distance = (c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) +
		(c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY());
	int rdistance = c.getR() * c.getR();
	if (centerpoint_distance == rdistance)
	{
		cout << "点与圆的位置关系为:点在圆上" << endl;
	}
	else if (centerpoint_distance < rdistance)
	{
		cout << "点与圆的位置关系为:点在圆内" << endl;
	}
	else
	{
		cout << "点与圆的位置关系为:点在圆外" << endl;
	}
}

int main() {
	设置半径和圆心
	Circle c1;
	Point center; 
	c1.setR(10);
	center.setX(10); //点center为(10,0)
	center.setY(0);
	c1.setCenter(center); //将点center设置为圆的圆心
	//设置点
	Point p1;
	p1.setX(10); //点为(10,9)
	p1.setY(9);
	getCirclePoint(c1,p1);

	system("pause");
	return 0;
}
  • 输出结果:
点与圆的位置关系为:点在圆内
请按任意键继续. . .

当以后完成一个大型的开发时候,类比较多,不可能将所有的类都写在一个文件中,这样代码量太大了,因此可以将类进行分文件编写,这样方便管理。
1..h头文件存放成员属性和行为的申明;
2..cpp文件存放类函数的实现;
【注意】:
1.#pragma once是一个比较常用的C/C++预处理指令,只要在头文件的最开始加入这条预处理指令,就能够保证头文件只被编译一次,防止头文件被重复引用。
2. Point::Circle:: 用于申明函数的作用域,为Point类和Circle类下的成员函数

  • 代码演示:

Point.h文件

#pragma once //防止头文件重复包含
#include <iostream>
using namespace std;
class Point
{
public:
	//设置属性
	void setX(int x);
	void setY(int y);
	// 获取属性
	int getX();
	int getY();
private:
	int p_X;
	int p_Y;
};

Point.cpp文件

#include "Point.h"
//设置属性
void Point::setX(int x)
{
	p_X = x;
}
void Point::setY(int y)
{
	p_Y = y;
}
// 获取属性
int Point::getX()
{
	return p_X;
}
int Point::getY()
{
	return p_Y;
}

Circle.h文件

#pragma once
#include <iostream>
using namespace std;
#include "Point.h" //包含Point类,因此需要包含Point类的头文件
class Circle
{
public:
	// 设置属性
	void setR(int r);
	void setCenter(Point& center);
	
	// 获取属性
	int getR();
	Point getCenter();
	
private:
	int c_R;
	Point c_Center;
};

Circle.cpp文件

#include "Circle.h"

// 设置属性 
void Circle::setR(int r)
{
	c_R = r;
}
void Circle::setCenter(Point &center)
{
	c_Center = center;
}

	// 获取属性
int Circle::getR()
{
	return c_R;
}
Point Circle::getCenter()
{
	return c_Center;
}

点与圆位置关系的分文件编写代码实现
设计案例2的分文件编写(主要为类的分文件编写)
.h文件写类属性、行为的申明
.cpp文件写类函数的实现

#include <iostream>
using namespace std;
#include "Circle.h"
#include "Point.h"

void getCirclePoint(Circle& c, Point& p)
{
	int centerpoint_distance = (c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) +
		(c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY());
	int rdistance = c.getR() * c.getR();
	if (centerpoint_distance == rdistance)
	{
		cout << "点与圆的位置关系为:点在圆上" << endl;
	}
	else if (centerpoint_distance < rdistance)
	{
		cout << "点与圆的位置关系为:点在圆内" << endl;
	}
	else
	{
		cout << "点与圆的位置关系为:点在圆外" << endl;
	}
}

int main() {

	Circle c1;
	Point center;
	c1.setR(10);
	center.setX(10);
	center.setY(0);
	c1.setCenter(center);

	Point p1;
	p1.setX(10);
	p1.setY(9);
	getCirclePoint(c1, p1);

	system("pause");
	return 0;
}
  • 输出结果:
点与圆的位置关系为:点在圆内
请按任意键继续. . .
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值