C++面向对象三大特征:封装、继承、多态
C++认为万事万物皆对象,对象有其属性和行为,具有相同性质的对象可以抽象称为类
4.1 封装
4.1.1 封装的意义
- 将属性和行为作为一个整体,表现生活中的事物
- 将属性和行为加以权限控制
在设计类的时候,属性和行为写在一起,表现事物
语法:class 类名{ 访问权限: 属性/行为}
示例一:设计一个圆类,求圆的周长
#include <iostream>
using namespace std;
// 设计一个圆类,求圆的周长
// 圆周率:3.14
const double PI = 3.14;
class Circle {
public:
// 属性
int m_r; // 半径
// 行为
// 获取圆的周长
double calculateZC() {
return 2*PI*m_r;
}
};
int main() {
// 通过圆类创建一个具体的圆(对象)
// c就是一个具体的圆(对象)
Circle c;
c.m_r = 10; // 给圆对象的半径赋值
cout << c.calculateZC() << endl;
return 0;
}
示例二:设计一个学生类,属性有姓名和学号,可以给姓名和学号进行赋值,可以显示学生的姓名和学号
#include <iostream>
using namespace std;
class Student {
public:
// 属性
string s_name;
int m_id;
// 行为
// 给姓名和学号进行赋值操作
void setName(string name) {
s_name = name;
}
void setId(int id) {
m_id = id;
}
// 显示姓名和学号
void showInfo() {
cout << s_name << " " << m_id << endl;
}
};
int main() {
Student s1{"张三", 001};
s1.showInfo();
Student s2;
s2.setName("homo");
s2.setId(111);
s2.showInfo();
}
4.1.2 访问权限
- public: 公有属性,类外可以访问
- private: 私有属性,类外不可以访问
- protected: 保护属性,类外不可以访问,类内可以访问,子类可以访问
示例:
#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;
}
void showInfo() {
cout << "姓名:" << m_name << endl;
cout << "汽车:" << m_car << endl;
cout << "密码:" << m_password << endl;
}
};
int main() {
Person p1;
p1.m_name = "homo";
cout << p1.m_name << endl;
// p1.m_car = "拖拉机"; 报错,保护权限类外无法访问
// cout << p1.m_car << endl;
// p1.m_password = 987654; 报错,私有权限类外无法访问
// cout << p1.m_password << endl;
Person p2;
p2.func();
cout << p2.m_name << endl;
// cout << p2.m_car << endl; 同样报错,只能通过公开函数访问
// cout << p2.m_password << endl; 同样报错,只能通过公开函数访问
p2.showInfo(); // 正确,通过公开函数访问
}
4.1.3 C++中class和struct的区别
在C++中 struct和class唯一的区别就在于默认的访问权限不同
区别:
- struct 默认属性是public
- class 默认属性是private
示例:
#include <iostream>
using namespace std;
class c1 {
int m_a; // 默认是私有变量
};
struct s1 {
int m_a; // 默认是公共变量
};
int main() {
c1 c;
s1 s;
// c.m_a = 1; 错误,私有变量不能被访问
s.m_a = 2; // 正确,公共变量可以被访问
// cout << c.m_a << endl; 错误,私有变量不能被访问
cout << s.m_a << endl; // 正确,公共变量可以被访问
return 0;
}
4.1.4成员属性设置为私有
- 优点1:可以自己控制读写权限
- 优点2:对于写权限,我们可以检测数据的有效性
示例:
#include <iostream>
#include <string>
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)
m_Age = age;
else {
cout << "年龄需要在0-150之间" << endl;
return; // 年龄输入有误,返回
}
}
// 情人设置可写
void setLover(string lover) {
m_lover = lover;
}
private:
string m_Name; // 姓名 可读可写
int m_Age = 18; // 年龄 可读可写,但只能在0-150之间
string m_lover; // 情人 只写
};
int main() {
Person p;
// 写姓名
p.setName("aj");
// 读姓名
cout << "姓名:" << p.getName() << endl;
// 写年龄
p.setAge(20);
// 读年龄
cout << "年龄:" << p.getAge() << endl;
return 0;
}
4.1.5 设计案例1 立方体类
设计立方体类(Cube),求出立方体的面积和体积。
分别用全局函数和成员函数判断两个立方体是否相等。
示例:
//
// 设计立方体类(Cube),求出立方体的面积和体积。
// 分别用全局函数和成员函数判断两个立方体是否相等。
//
#include <iostream>
using namespace std;
class Cube
{
// 属性
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 Volume() {
return m_L*m_W*m_H;
}
// 成员函数判断两个立方体是否相等
bool isEqualByClass(Cube & c) {
if (m_L == c.getL() && m_W == c.getW() && m_H == c.getH())
return true;
else
return false;
}
};
// 全局函数:判断两个立方体是否相等
// 思路:分别比较两个立方体的长宽高是否相等,如果相等则认为两个立方体相等
bool isEqual(Cube & c1, Cube & c2) {
if (c1.getL() == c2.getL() && c1.getW() == c2.getW() && c1.getH() == c2.getH())
return true;
else
return false;
}
int main()
{
// 实例化两个立方体
Cube c1;
c1.setL(10);
c1.setW(20);
c1.setH(30);
cout << "c1的面积为:" << c1.getArea() << endl;
cout << "c1的体积为:" << c1.Volume() << endl;
cout << "--------------------" << endl;
Cube c2;
c2.setL(10);
c2.setW(20);
c2.setH(30);
cout << "c2的面积为:" << c2.getArea() << endl;
cout << "c2的体积为:" << c2.Volume() << endl;
cout << "--------------------" << endl;
// 全局函数判断两个立方体是否相等
bool a = isEqual(c1, c2);
if (a)
cout << "两个立方体相等" << endl;
else
cout << "两个立方体不相等" << endl;
cout << endl;
// 成员函数判断两个立方体是否相等
bool b = c1.isEqualByClass(c2);
if (b)
cout << "成员函数判断:两个立方体相等" << endl;
else
cout << "成员函数判断:两个立方体不相等" << endl;
}
4.1.6 设计案例2 点和圆关系
设计一个圆形类(Circle),和一个点类(Point),计算点和圆的关系。
示例:
//
// 设计一个圆形类(Circle),和一个点类(Point),计算点和圆的关系。
//
#include <iostream>
using namespace std;
// 点类
class Point {
private:
int m_X;
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 Circle {
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 isInCircle(Circle &c, Point &p) {
// 点到圆心距离计算公式:sqrt((x1-x2)^2 + (y1-y2)^2)
// 简化代码:既然只要我们比较点到圆心的距离与半径,那么可以省去点到远近距离计算的根号,用左侧和右侧同时平方进行比较。
// 计算两点之间距离的平方
int 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 (distance < rDistance) {
cout << "点在圆内" << endl;
}
else if (distance > rDistance) {
cout << "点在圆外" << endl;
}
else {
cout << "点在圆上" << endl;
}
}
int main() {
// 创建圆
Circle c;
c.setR(10);
Point center; // 创建圆心
center.SetX(10);
center.SetY(0);
c.setCenter(center);
cout << "圆的半径为:" << c.getR() << endl;
cout << "圆的圆心为:" << c.getCenter().GetX() << " " << c.getCenter().GetY() << endl;
// 创建点
Point p;
p.SetX(10);
p.SetY(10);
// 判断关系
isInCircle(c, p);
return 0;
}