阶段三:C++核心编程
C++面向对象的三大特性为:封装、继承、多态
C++认为:万事万物都皆为对象,对象上有其属性和行为
例如:
人可以作为对象,属性有姓名、年龄、身高、体重…,行为有走、跑、跳、吃饭、唱歌…
车也可以作为对象,属性有轮胎、方向盘、车灯…,行为有载人、放音乐、放空调…
具有相同性质的 对象,我们可以抽象称为 类,人属于人类,车属于车类
Chapter4:类和对象-封装
封装是C++面向对象三大特性之一
封装的意义:
1.将属性和行为作为一个整体,表现生活中的事物
2.将属性和行为加以权限控制
在设计类的时候,属性和行为写在一起,表现事物
语法:class 类名{ 访问权限: 属性 / 行为 };
4.1 属性和行为作为整体
示例1:设计一个圆类,求圆的周长
圆求周长的公式: 2 * PI * 半径
#include "iostream"
using namespace std;
const double PI = 3.14; //圆周率
//封装意义一:在设计类的时候,属性和行为写在一起,表现事物
//封装一个圆类,求圆的周长
class Circle //class代表设计一个类,后面跟着的是类名
{
public: //访问权限 公共的权限
//属性
int m_r; //半径
//行为
double calculateZC()//获取到圆的周长 行为通常可以用一个函数表示
{
return 2 * PI * m_r;
}
};
int main()
{
Circle c1; //通过圆类,创建圆的对象,这就是用类创建了一个具体的对象
//通过一个类,创建一个对象的过程,这就是实例化
//c1就是一个具体的圆
c1.m_r = 10; //给圆对象的半径,进行赋值操作
cout << "圆的周长为: " << c1.calculateZC() << endl;
system("pause");
return 0;
}
输出结果如下:
4.2 案例-设计学生类
示例2:设计一个学生类,属性有姓名和学号,可以给姓名和学号赋值,可以显示学生的姓名和学号
#include "iostream"
using namespace std;
#include <string>
class Student //学生类
{
public: //访问权限,公共权限
//属性
void setName(string name) //给姓名赋值
{
m_name = name;
}
void setID(int id) //给学号赋值
{
m_id = id;
}
//行为
void showStudent() //显示姓名和学号
{
cout << "name:" << m_name << " ID:" << m_id << endl;
}
public: //访问权限,公共权限
//属性
string m_name; //姓名
int m_id; //学号
};
int main()
{
//方式一:
Student s1; //创建一个具体的学生 实例化对象
s1.m_name = "张三"; //给s1对象 进行属性赋值操作
s1.m_id = 1;
s1.showStudent();
Student s2;
s2.m_name = "李四"; //给s2对象 进行属性赋值操作
s2.m_id = 2;
s2.showStudent();
//方式二:
Student stu;
stu.setName("德玛西亚");
stu.setID(250);
stu.showStudent();
system("pause");
return 0;
}
/*
对上面的示例进行补充剖析:
*1.类中的属性和行为统一称为成员
类中的属性:也被称为 成员属性、成员变量
类中的行为:也被称为 成员函数、成员方法
*2.封装意义二:类在设计时,可以把属性和行为放在不同的权限下,加以控制
访问权限有三种:
1.public 公共权限
2.protected 保护权限
3.private 私有权限
*/
输出结果如下:
4.3 访问权限
三种权限
公共权限 public 类内可以访问 类外可以访问
保护权限 protected 类内可以访问 类外不可以访问
私有权限 private 类内可以访问 类外不可以访问
其中保护权限和私有权限的区别在后面学到继承那里会很清晰
这里简单提一下,就是说:
保护权限 :子类可以访问父类中的保护内容
私有权限 :子类不可以访问父类中的私有内容
#include "iostream"
using namespace std;
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 p; //实例化具体对象
p.m_Name = "李四"; //刚才是张三,现在更改为李四,说明在类外是可以访问的 因为是公共权限
//p.m_Car = "奔驰"; //保护权限类外访问不到
//p.m_Password = 123; //私有权限类外访问不到
p.func(); //可以访问,是因为func是公共权限,如果函数func更改权限为protected/private在这里(类外)都是无法访问的
system("pause");
return 0;
}
输出结果如下:
4.4 C++中class和struct的区别
在C++中 struct和class唯一的区别就在于 默认的访问权限不同
区别:
struct 默认权限为公共 pubic
class 默认权限为私有 private
#include "iostream"
using namespace std;
class C1
{
int m_A; //默认是私有权限 这里上面没有写三种权限中的任一种 就是默认权限 私有权限
};
struct C2
{
int m_A; //默认是公共权限
};
int main()
{
C1 c1; //实例化对象
//c1.m_A = 10; //错误,访问权限是私有,私有权限外部不可以访问
C2 c2; //实例化对象
c2.m_A = 10; //正确,访问权限是公共,公共权限外部可以访问
system("pause");
return 0;
}
输出结果如下:
4.5成员属性私有化
优点1:将所有成员属性设置为私有,可以自己控制读写权限
优点2:对于写权限,我们可以检测数据的有效性
#include "iostream"
using namespace std;
class Person
{
public:
void setName(string name) //可写,姓名设置为可读可写
{
m_Name = name;
}
string getName() //可读
{
return m_Name;
}
int getAge() //获取年龄 只读
{
return m_Age;
}
void setAge(int age) //设置年龄 只写
{
if (age < 0 || age > 150)
{
cout << "你个老妖精!" << endl;
m_Age = 0;
return;
}
m_Age = age;
}
void setLover(string lover) //情人设置为只写
{
m_Lover = lover;
}
private:
string m_Name; //可读可写 姓名
int m_Age; //只读 年龄
string m_Lover; //只写 情人
};
int main()
{
Person p; //实例化对象
p.setName("张三"); //姓名设置
cout << "姓名: " << p.getName() << endl;
p.setAge(50); //年龄设置
cout << "年龄: " << p.getAge() << endl;
p.setLover("李四"); //情人设置
//cout << "情人: " << p.m_Lover << endl; //只写属性,不可以读取
system("pause");
return 0;
}
/*
对上面的示例进行补充剖析:
因为 私有权限 在类外是不可以访问的,因此,我们可以在类内再创建一个 public 接口
该接口就对 private 私有权限的属性进行 可读可写操作 读:获取 写:设置
这里将这部分接口写到private权限之前
*/
输出结果如下:
4.6 设计案例1-立方体类
示例:设计立方体类(Cube)
求出立方体的面积和体积
分别用全局函数和成员函数判断两个立方体是否相等。
判断是否相等:两个立方体的 长 宽 高 均相等
思路 流程
立方体类设计
1、创建立方体类
2、设计属性
3、设计行为 获取立方体面积和体积
4、分别利用全局函数和成员函数判断两个立方体是否相等
#include "iostream"
using namespace std;
class Cube
{
public:
//行为 设置获取长宽高
void setL(int l) //设置长
{
m_L = l;
}
int getL() //获取长
{
return m_L;
}
void setW(int w) //设置宽
{
m_W = w;
}
int getW() //获取宽
{
return m_W;
}
void setH(int h) //设置高
{
m_H = h;
}
int getH() //获取高
{
return m_H;
}
int calculateS() //获取立方体面积
{
return 2 * (m_L * m_W + m_L * m_H + m_H * m_W);
}
int calculateV() //获取立方体体积
{
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;
}
private:
//属性
int m_L; //长
int m_W; //宽
int m_H; //高
};
//利用全局函数来判断两个立方体是否相等
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(10);
c1.setW(10);
c1.setH(10);
cout << "c1的面积为:" << c1.calculateS() << endl;
cout << "c1的体积为:" << c1.calculateV() << endl;
Cube c2;
c2.setL(10);
c2.setW(10);
c2.setH(10);
//方式一:利用全局函数判断是否相等
bool ret = isSame(c1,c2);
if (ret)
{
cout << "全局函数判断结果:c1和c2是相等的" << endl;
}
else
{
cout << "全局函数判断结果:c1和c2是不相等的" << endl;
}
//方式二:利用成员函数判断是否相等
ret = c1.isSameByClass(c2);
if (ret)
{
cout << "成员函数判断结果:c1和c2是相等的" << endl;
}
else
{
cout << "成员函数判断结果:c1和c2是不相等的" << endl;
}
system("pause");
return 0;
}
输出结果如下:
4.7 设计案例2-点和圆关系
设计一个圆形类(Circle),和一个点类(Point),计算点和圆的关系
思路:
计算点和圆心的距离l,该距离L和半径R去比较
L<R: 圆内
L=R: 圆上
L>R: 圆外
点到圆心的距离:(x1-x2)^2 + (y1-y2)^2然后开根号
或者 ((x1-x2)^2 + (y1-y2)2)2 与 r^2 对比
#include "iostream"
using namespace std;
class Point //点类
{
public:
void setX(int x) //设置x
{
m_X = x;
}
int getX() //获取x
{
return m_X;
}
void setY(int y) //设置y
{
m_Y = y;
}
int getY() //获取y
{
return m_Y;
}
private:
int m_X; //点的x坐标
int m_Y; //点的y坐标
};
class Circle //圆类
{
public:
void serR(int r) //设置半径
{
m_R = r;
}
int getR() //获取半径
{
return m_R;
}
void setCenter(Point center)//设置圆心
{
m_Center = center;
}
Point getCenter() //获取圆心
{
return m_Center;
}
private:
int m_R; //半径
Point m_Center; //圆心 在一个类中,我们可以让另一个类作为我们这个类的成员
};
void isInCircle(Circle& c, Point& p)//判断点和圆关系
{
//计算两点之间的距离 平方 即:((x1-x2)^2 + (y1-y2)^2)^2
int distance =
(c.getCenter().getX() - p.getX()) ^ 2 + (c.getCenter().getY() - p.getY()) ^ 2;
//计算半径的平方
int rDisatance = (c.getR()) ^ 2;
//判断关系
if (distance == rDisatance)
{
cout << "点在圆上" << endl;
}
else if (distance > rDisatance)
{
cout << "点在圆外" << endl;
}
else
{
cout << "点在圆内" << endl;
}
}
int main()
{
Circle c; //创建圆
c.serR(10);
Point center; //创建圆心
center.setX(10);
center.setY(0);
c.setCenter(center);
Point p; //创建点
p.setX(10);
p.setY(9);
isInCircle(c,p);//判断关系
system("pause");
return 0;
}
输出结果如下:
在实际的工程应用中,我们不会这样去写代码,因为这样显得代码比较臃肿
接下来用一种新的方式展现这个示例
创建三个文件,这里引入作用域的概念 “::”
#1:将类存放于新的cpp中 -> point.cpp,
#2:point.h中存放point.cpp相关声明
#3:主文件
点类和圆类的cpp文件
#include "point.h"
//点类
void Point::setX(int x) //设置x
{
m_X = x;
}
int Point::getX() //获取x
{
return m_X;
}
void Point::setY(int y) //设置y
{
m_Y = y;
}
int Point::getY() //获取y
{
return m_Y;
}
//圆类
void Circle::serR(int r) //设置半径
{
m_R = r;
}
int Circle::getR() //获取半径
{
return m_R;
}
void Circle::setCenter(Point center)//设置圆心
{
m_Center = center;
}
Point Circle::getCenter() //获取圆心
{
return m_Center;
}
点类和圆类的cpp头文件
#pragma once//防止重复包含
#include <iostream>
using namespace std;
//点类
class Point
{
public:
void setX(int x); //设置x
int getX(); //获取x
void setY(int y); //设置y
int getY(); //获取y
private:
int m_X; //点的x坐标
int m_Y; //点的y坐标
};
//圆类
class Circle
{
public:
void serR(int r); //设置半径
int getR(); //获取半径
void setCenter(Point center);//设置圆心
Point getCenter(); //获取圆心
private:
int m_R; //半径
Point m_Center; //圆心 在一个类中,我们可以让另一个类作为我们这个类的成员
};
/*
对上面的示例进行补充剖析:
就拿这个例子来讲:void Point::setX(int x) //设置x
这里的 Point::表明setX()是Point作用域下的函数
*/
主文件
#include "iostream"
using namespace std;
#include "point.h" //这里包含
//判断点和圆关系
void isInCircle(Circle& c, Point& p)
{
//计算两点之间的距离 平方 即:((x1-x2)^2 + (y1-y2)^2)^2
int distance =
(c.getCenter().getX() - p.getX()) ^ 2 + (c.getCenter().getY() - p.getY()) ^ 2;
//计算半径的平方
int rDisatance = (c.getR()) ^ 2;
//判断关系
if (distance == rDisatance)
{
cout << "点在圆上" << endl;
}
else if (distance > rDisatance)
{
cout << "点在圆外" << endl;
}
else
{
cout << "点在圆内" << endl;
}
}
int main()
{
//创建圆
Circle c;
c.serR(10);
Point center;
center.setX(10);
center.setY(0);
c.setCenter(center);
//创建点
Point p;
p.setX(10);
p.setY(9);
//判断关系
isInCircle(c, p);
system("pause");
return 0;
}