1.属性和行为作为整体
C++面向对象的三大特性:封装、继承、多态
C++认为万事万物都皆为对象,对象上有其属性
和行为
人可以作为对象,属性有姓名、年龄、身高、体重…行为有走、跑、跳、吃饭、睡觉…
车也可以作为对象,属性有车牌、车灯、轮胎…行为有载人、放音乐…
具有相同性质的对象,我们可以抽象称为类,人属于人类,车属于车类
…
封装是C++面向对象三大特性之一
封装的意义
:
- 将属性和行为作为一个整体,表现生活中的事物
- 将属性和行为加以权限控制
语法
: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.访问权限
封装意义二: 类在设计时,可以把属性和行为放在不同的权限下,加以控制
访问权限
有三种:
public 公共权限
(类内可以访问 类外也可以访问)protected 保护权限
(类内可以访问 类外不可以访问 子类可以访问父类)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唯一的区别
在于默认的访问权限不同
- struct默认权限为公共权限
- 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.成员属性私有化
成员属性设置为私有的优点:
- 将所有成员属性设置为私有,可以控制读写权限
- 对于写权限,我们可以检测数据的有效性
优点一:将所有成员属性设置为私有,可以控制读写权限
- 优点一代码演示:
#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 ¢er)
{
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 ¢er)
{
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;
}
- 输出结果:
点与圆的位置关系为:点在圆内
请按任意键继续. . .