【C++核心编程】4 类和对象-封装


黑马程序员匠心之作|C++教程从0到1入门编程
学习笔记
本阶段主要针对C++ 面向对象编程技术做详细讲解,探讨C++中的核心和精髓

C++面向对象的三大特性为:封装、继承、多态
C++认为万事万物都可以称为对象,对象有其属性和行为
例如:
人,属性:姓名、年龄…,行为:走、跑、跳…
车,属性:轮胎、方向盘…,行为:载人、放音乐…
具有相同性质的对象,我们可以抽象称为

4.1 封装

4.1.1 封装的意义

封装的意义:
意义1 :将属性和行为作为一个整体,表现生活中的事物
语法:class 类名{ 访问权限:属性/行为};
示例1:
创建一个圆类,求圆的周长

#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*3.14*10=62.8
	cout << "圆的周长为:" << c1.calculateZC() << endl;

	system("pause");
	return 0;

}

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

#include<iostream>
using namespace std;
#include<string>
class Student {
public://公共权限
	//属性
	string name;
	string number;
	
	//行为
	//显示姓名和学号
	void showStudent() {
		cout << "学生姓名:" << name << " 学号:" << number << endl;
	}
	//给姓名赋值
	void setName(string setname) {
		name = setname;
	}
	//给学号赋值
	void setNumber(string setnumber) {
		number = setnumber;
	}

};
int main() {

	//实例化对象
	Student std1;
	std1.name = "张三";
	std1.number = "20170001";
	//显示学生信息
	std1.showStudent();

	Student std2;
	std2.setName("李四");
	std2.setNumber("20170002");
	//显示学生信息
	std2.showStudent();

	system("pause");
	return 0;

}

输出:

学生姓名:张三 学号:20170001
学生姓名:李四 学号:20170002

补充:
专业术语:
类中的属性和行为,我们统一称为:成员
属性:也称为成员属性,成员变量
行为:也称为成员函数,成员方法

意义2:将属性和行为加以权限控制
类在设计时,可以把属性和行为放在不同的权限下,加以控制
访问权限有三种:

  1. public 公共权限
    成员 类内可以访问,类外也可以访问
  2. protected 保护权限
    成员 类内可以访问,类外不可以访问,后面学继承的时候,儿子也可以访问父亲中的保护内容
  3. private 私有权限
    成员 类内可以访问,类外不可以访问,继承中,儿子不可以访问父亲私有内容
    示例:
#include<iostream>
using namespace std;
#include<string>

//1. public 公共权限 成员 类内可以访问,类外也可以访问
//2. protected 保护权限 成员 类内可以访问,类外不可以访问,后面学继承的时候,儿子也可以访问父亲中的保护内容
//3. private 私有权限 成员 类内可以访问,类外不可以访问,继承中,儿子不可以访问父亲私有内容

class Person{
	
public:
	//公共权限
	string m_Name;//姓名
protected:
	//保护权限
	string m_Car;//汽车
private:
	//私有权限
	int m_Password;//银行卡密码
	
public:
	void func() {
		m_Name = "张三";
		m_Car = "拖拉机";
		m_Password = 123456;
	}
};

int main() {

	//实例化具体对象
	Person p1;
	p1.m_Name = "李四";
	//p1.m_Car = "宝马";//类外访问不了
	//p1.m_Password="11"//类外不可以访问


	system("pause");
	return 0;

}

4.1.2 struct和class区别

区别:
struct默认权限是公共public
class默认权限是私有private
示例:

#include<iostream>
using namespace std;
#include<string>

//1. public 公共权限 成员 类内可以访问,类外也可以访问
//2. protected 保护权限 成员 类内可以访问,类外不可以访问,后面学继承的时候,儿子也可以访问父亲中的保护内容
//3. private 私有权限 成员 类内可以访问,类外不可以访问,继承中,儿子不可以访问父亲私有内容

class C1{
	int m_A;//默认是私有权限
};

struct C2 {
	int m_A;//默认权限是公共权限
};

int main() {

	C1 c1;
//	c1.m_A = 100;//报错,不可访问

	C2 c2;
	c2.m_A = 100;//struct默认是public

	system("pause");
	return 0;

}

4.1.3 成员属性设置为私有

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

#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;
	}
	//学号 可读可写 如果想修改,只能在0-150之间
	void setNumber(int number){
		if (number < 0 || number>150) {
			number = 0;//强制改为0
			cout << "你的输入有误" << endl;
			return;
		}
		m_Number = number;
	}
	//获取学号
	int getNumber() {
		return m_Number;
	}

private:
	//姓名 可读可写
	string m_Name;
	//年龄 可读
	int m_Age;
	//情人 只写
	string m_Lover;
	//学号 可读可写 如果想修改,只能在0-150之间
	int m_Number;

};

int main() {

	Person p;
	p.setName("张三");
	cout << "姓名为:" << p.getName() << endl;
	//p.m_Age = 18//报错 只读
	cout << "年龄为:" << p.getAge() << endl;
	p.setLover("苍井");
	//cout << "情人为" << p.setLover() << endl;//报错,不可以访问
	p.setNumber(50);
	cout << "学号:" << p.getNumber() << endl;
	system("pause");
	return 0;

}

输出:

姓名为:张三
年龄为:0
学号:50

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

#include<iostream>
using namespace std;
#include<string>


class Cube {
private://属性最好设置成private
	double m_L;
	double m_W;
	double m_H;

	
	//行为 

public:
	void setL(double l) {
		m_L = l;
	}
	double getL() {
		return m_L;
	}
	void setW(double w) {
		m_W = w;
	}
	double getW() {
		return m_W;
	}
	void setH(double h) {
		m_H = h;
	}
	double getH() {
		return m_H;
	}

	double getArea() {
		return 2 * (m_L*m_W + m_L*m_H + m_W*m_H);
	}
	double getVolume() {
		return m_L*m_W*m_H;
	}
	//成员函数判读是否相等
	bool isSameByClass(Cube &c) {//传入一个参数
		if (m_L== c.getL()&m_W == c.getW()&m_H == c.getH()) {
			return true;
		}
		return false;
	}
	
};
//全局函数判断是否相等
bool isSame(Cube &c1, Cube &c2) {//传入两个参数
	if (c1.getL() == c2.getL()&c1.getW() == c2.getW()&c1.getH() == c2.getH()) {
		return true;
	}
	return false;
}
int main() {

	Cube c1;
	c1.setL(1);
	c1.setW(2);
	c1.setH(3);
	cout << "立方体c1的面积为:" << c1.getArea() << endl;
	cout << "立方体c1的体积为:" << c1.getVolume() << endl;
	Cube c2;
	c2.setL(1);
	c2.setW(2);
	c2.setH(4);
	cout << "立方体c2的面积为:" << c2.getArea() << endl;
	cout << "立方体c2的体积为:" << c2.getVolume() << endl;
	
	//全局函数判断
	bool ret = isSame(c1, c2);
	if (ret) {
		cout << "运用全局函数得到相等" << endl;

	}
	else {
		cout << "运用全局函数得到不相等" << endl;

	}
	//成员函数判断
	ret = c1.isSameByClass(c2);
	if (ret) {
		cout << "运用成员函数得到相等" << endl;

	}
	else {
		cout << "运用成员函数得到不相等" << endl;

	}
	system("pause");
	return 0;

}

输出:

立方体c1的面积为:22
立方体c1的体积为:6
立方体c2的面积为:28
立方体c2的体积为:8
运用全局函数得到不相等
运用成员函数得到不相等

练习案例2:点和圆的关系
设计一个圆形类(Circle),和一个点类(Point),计算点和圆的关系
示例:

#include<iostream>
using namespace std;
#include<string>

class Circle {
private:
	double centerX;
	double centerY;
	double m_r;
public:
	void setCenterX(double c_x) {
		centerX = c_x;
	}
	double getCenterX() {
		return centerX;
	}
	void setCenterY(double c_y) {
		centerY = c_y;
	}
	double getCenterY() {
		return centerY;
	}
	void setR(double r) {
		m_r = r;
	}
	double getR() {
		return m_r;
	}
	
	

};
class Point {
private:
	double pointX;
	double pointY;
public:
	void setPointX(double p_x) {
		pointX = p_x;
	}
	double getPointX() {
		return pointX;
	}
	void setPointY(double p_y) {
		pointY = p_y;
	}
	double getPointY() {
		return pointY;
	}

};
void checkLink(Circle &c,Point &p) {
	double d = sqrt((p.getPointX() - c.getCenterX())*(p.getPointX() - c.getCenterX())
		+ (p.getPointY() - c.getCenterY())*(p.getPointY() - c.getCenterY()));
	if (d < c.getR()) {
		cout << "点在圆内" << endl;
	}
	else if(d == c.getR()) {
		cout << "点在圆上" << endl;
	}
	else{
		cout << "点在圆外" << endl;
	}
}
int main() {

	Circle c;
	Point p;
	c.setCenterX(1.5);
	c.setCenterY(2);
	c.setR(3);
	p.setPointX(2.5);
	p.setPointY(4.5);

	checkLink(c, p);

	system("pause");
	return 0;

}

但是,如果项目更为复杂,全部写在一起就很乱,因此我们需要将类写到其他文件里面。

  1. 在头文件中创建一个point.h文件
#pragma once
#include<iostream>
using namespace std;

class Point {
private:
	double pointX;
	double pointY;
public://只需要声明,不需要实现
	void setPointX(double p_x);
	double getPointX();
	void setPointY(double p_y);
	double getPointY();

};
  1. 在头文件中创建一个circle.h文件
#pragma once
#include<iostream>
using namespace std;

class Circle {
private:
	double centerX;
	double centerY;
	double m_r;
public:
	void setCenterX(double c_x);
	double getCenterX();
	void setCenterY(double c_y);
	double getCenterY();
	void setR(double r);
	double getR();
};
  1. 在源文件中创建一个point.cpp文件
#include"point.h"

//Point拆分文件编写
void Point::setPointX(double p_x) {//Point:: Point作用域下的set函数
	pointX = p_x;
}
double Point::getPointX() {
	return pointX;
}
void Point::setPointY(double p_y) {
	pointY = p_y;
}
double Point::getPointY() {
	return pointY;
}
  1. 在源文件中创建一个circle.cpp文件
#include"circle.h"

//Circle拆分文件编写
void Circle::setCenterX(double c_x) {
	centerX = c_x;
}
double Circle::getCenterX() {
	return centerX;
}
void Circle::setCenterY(double c_y) {
	centerY = c_y;
}
double Circle::getCenterY() {
	return centerY;
}
void Circle::setR(double r) {
	m_r = r;
}
double Circle::getR() {
	return m_r;
}
  1. main文件
#include<iostream>
using namespace std;
#include<string>
#include"point.h"
#include"circle.h"


void checkLink(Circle &c,Point &p) {
	double d = sqrt((p.getPointX() - c.getCenterX())*(p.getPointX() - c.getCenterX())
		+ (p.getPointY() - c.getCenterY())*(p.getPointY() - c.getCenterY()));
	if (d < c.getR()) {
		cout << "点在圆内" << endl;
	}
	else if(d == c.getR()) {
		cout << "点在圆上" << endl;
	}
	else{
		cout << "点在圆外" << endl;
	}
}
int main() {

	Circle c;
	Point p;
	c.setCenterX(1.5);
	c.setCenterY(2);
	c.setR(3);
	p.setPointX(2.5);
	p.setPointY(4.5);

	checkLink(c, p);

	system("pause");
	return 0;

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值