目录

前言

一、属性的行为作为整体

1.封装的意义:

1.1封装的意义一——基本语法

1.2案例(设计一个学生类)

1.3封装的意义二——访问权限

二、class和struct的区别

三、成员属性私有化

1.好处1:控制属性的读写权限

​2.好处2:检测数据的有效性

四、案例

1.立方体类

2.点和圆的关系


前言

C++面向对象的三大特性是:封装,继承,多态(本文讲的是封装)

在C++的眼里,万事万物均为对象,对象都有属性和行为

例如:

人可以作为一个对象

属性有:姓名、年龄、身高、体重......;

行为有:跑,跳,吃饭,睡觉,唱歌,生气,开心,哭泣等......

花也可以作为一个对象

属性有:颜色,高度,种类......

行为有:发芽,生长,开花,释放花香,枯萎.......

人有各自所处的环境,包括职业,所在区域,我们都被封装在这一个存在变化的特定区域内,和一个集体一起表现出这个集体的特性,且其他集体对我们这个集体有访问权限限制

花也被封装在一个特定的环境里,或温室,或野外

这就是封装

具有相同性质的对象,我们把它归之为类,比如人属于人类,花属于花类

而人又归属于灵长类动物,所以继承自父类(灵长类)

而花又属于父类(植物类)的继承

人可以分为很多种,根据属性和行为可以分出年轻的正在跑的人,矮的正在睡觉的人......

花也可以分为很多种,红色的释放玫瑰香的花,白色的释放栀子香的花......

这就是多态

一、属性的行为作为整体

1.封装的意义:

- 将属性作为一个整体,表现生活中的事物

- 将属性和行为加以权限控制

1.1封装的意义一——基本语法

在设计类时,属性和行为写在一起,表现事物

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

实例:

把圆类的属性和行为作为一个整体来体现Circle这个类

设计一个圆类,求圆的周长,代码有注释,跟着敲一遍就懂了

类和对象的关系就是,类是建筑物的蓝图,而对象是具体建造出来的建筑物,类不是一个具体的内容,我们得创建一个类的对象来获取具体的内容(获得一些实质性的东西)

类中的属性通常是一些变量比如这个例子中的double r;

类中的行为通常是一些函数比如这个例子中的:

double cirLen(r)
    {
        return 2 * pi*r;
    }

#include<iostream>
using namespace std;
#define pi 3.14//宏定义pi的值是3.14
//const double pi 3.14//也可以在main外的全局区域定义一个常量pi
class Circle//定义了一个圆类
{
public://访问权限是公开的//属性,半径double r;double cirLen(r)//传入半径方便计算周长{return 2 * pi*r;//返回值是周长}
};
int main()
{//实例化Circle类//在调用时先创建一个类变量,通过圆类创建一个具体的对象Circle c;//再用创建好的对象来访问类里面的行为(函数)或属性(double r;)double r = 7.777;int result= c.cirLen(r);cout << "圆的周长是:" << result << endl;//输出圆的周长//当然我们也可以让用户输入半径,然后执行自动调用计算出周长cout << "请输入圆的半径:" << endl;cin >> r;//录入用户输入的数据cout << "用户输入的半径计算出来的圆的周长是:"<<c.cirLen(r) << endl;system("pause");return 0;
}

输出结果是:

1.2案例(设计一个学生类)

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

如果报错说:没有与XXX相匹配的运算符,那么多半是没有包含头文件,比如我们在用到string的时候要包含一个也叫string的头文件,这样才不会报错

#include<iostream>
#include<string>
using namespace std;
class Student
{
public://学生类的属性string stuNum;//学号,用字符串类型,要加上头文件#include<string>string stuName;//学生姓名//学生类的行为void SetInfor()//设置学生信息,给学生的属性赋值的函数{cout << "请输入学生姓名:" << endl;cin >> stuName;cout << "请输入学生学号:" << endl;cin >> stuNum;}void showInfor()//显示学生信息(姓名学号)的函数{cout << "学生的姓名:" << stuName << endl;cout << "学生的学号:" << stuNum << endl;}
};int main()
{//创建学生类的对象Student stu;//利用对象访问其中的行为stu.SetInfor();//设置学生的姓名学号stu.showInfor();//展示用户设置的学生的姓名学号system("pause");return 0;
}

我们可以给类里面的属性(变量)赋值后show出来

#include<iostream>
#include<string>
using namespace std;
class Student
{
public://学生类的属性string stuNum;//学号,用字符串类型,要加上头文件#include<string>string stuName;//学生姓名//学生类的行为void SetInfor()//设置学生信息,给学生的属性赋值的函数{cout << "请输入学生姓名:" << endl;cin >> stuName;cout << "请输入学生学号:" << endl;cin >> stuNum;}void showInfor()//显示学生信息(姓名学号)的函数{cout << "学生的姓名:" << stuName << endl;cout << "学生的学号:" << stuNum << endl;}
};int main()
{//创建学生类的对象Student stu;//利用对象访问其中的行为//用户输入的情况下的输出showInforstu.SetInfor();//设置学生的姓名学号stu.showInfor();//展示用户设置的学生的姓名学号//程序员设定(赋值的情况下的showInfor输出)cout << "---------------**---------------" << endl;stu.stuNum = "20170911";stu.stuName = "罗马星星";stu.showInfor();system("pause");return 0;
}

通过类里面的函数也可以给相应属性赋值(比如在函数里面改名字,改学号)

    //通过函数更改属性void setNewInfo(string name, string num){stuName = name;stuNum = num;}
    //通过函数进行赋值的操作调用cout << "---------------**---------------" << endl;cout << "通过类中的函数进行赋值的调用显示" << endl;stu.setNewInfo("张三", "20808089");stu.showInfor();

如果我们像把它做成一个学生信息管理系统,让用户可以多次录入学生信息那么只需要参考之前写的博文通讯录管理系统,依葫芦画瓢就好了(甚至此处会更简单至少不用case那么多个选项,直接用if语句)

1.3封装的意义二——访问权限

三种访问权限(作用域)

publiuc:公有权限,成员 类内可以访问,类外也可以访问

protected:保护权限,成员 类内可以访问,类外不可以访问

private:私有权限,成员 类内可以访问,类外不可以访问

protected和private的区别在继承中会有所体现

父类的protected权限,子类可以访问(这个算是家族秘密,你作为家庭中的一员,可以知道)

而父类的private权限,子类不可以访问(这个相当于私生活)

#include<iostream>
using namespace std;
#include<string>
class Person
{
public://作用域公有权限,类内,类外都可以访问//公有权限string name;//公有权限成员的属性,姓名是共有权限
protected://保护权限,类内可以访问,类外不可以访问int age;//年龄是保护权限
private://私有权限,类内可以访问,类外不可以访问string address;//家庭住址,私有权限
public://公有,类外可以访问void setInfo(string p_name, int p_age, string p_address){name = p_name;age = p_age;address = p_address;}void showInfo(){cout << "姓名" << name << endl;//name是公有权限,在类内访问,可以允许cout << "年龄" << age << endl;//age是保护权限,在类内可以访问cout << "住址:" << address << endl;//address是私有权限,在类内可以访问}
};
int main()
{//创建Person类的对象Person p;p.name = "张三";//name是Person的公有权限成员可以在类外访问并修改赋值p.age = 12;//age是保护权限,在类外访问报错p.address = "北京海淀";//address是私有成员,类外不可以访问//调用赋值函数setInfop.setInfo("李四", 22, "四川");p.showInfo();//显示信息system("pause");return 0;
}

p.name = "张三";//name是Person的公有权限成员可以在类外访问并修改赋值
    p.age = 12;//age是保护权限,在类外访问报错
    p.address = "北京海淀";//address是私有成员,类外不可以访问

只有把在类外错误访问的部分注释掉才能正常运行

在继承中的访问权限差异

继承的语法是class <子类名(比如Lisa)>:权限比如public 父类名字比如Person {  };

class Lisa:public Person
{

};

//把Lisa作为Person的子类(继承)
//可以访问父类Person中的age 保护权限,但是不可以访问父类的私有权限成员address
class Lisa:public Person//子类Lisa公有继承父类(也可以叫基类)Person
{
public:void showInfo(){cout<< "父类Person的公有权限成员:name" << name << endl;//可以访问cout << "父类Person的保护权限成员:age" << age << endl;//可以访问cout << "父类Person的私有权限成员:address" << address << endl;//报错,不可以访问}
};

#include<iostream>
using namespace std;
#include<string>
class Person
{
public://作用域公有权限,类内,类外都可以访问//公有权限string name;//公有权限成员的属性,姓名是共有权限
protected://保护权限,类内可以访问,类外不可以访问int age;//年龄是保护权限
private://私有权限,类内可以访问,类外不可以访问string address;//家庭住址,私有权限
public://公有,类外可以访问void setInfo(string p_name, int p_age, string p_address){name = p_name;age = p_age;address = p_address;}void showInfo(){cout << "姓名" << name << endl;//name是公有权限,在类内访问,可以允许cout << "年龄" << age << endl;//age是保护权限,在类内可以访问cout << "住址:" << address << endl;//address是私有权限,在类内可以访问}
};
//把Lisa作为Person的子类(继承)
//可以访问父类Person中的age 保护权限,但是不可以访问父类的私有权限成员address
class Lisa:public Person//子类Lisa公有继承父类(也可以叫基类)Person
{
public:void showInfo(){cout<< "父类Person的公有权限成员:name" << name << endl;//可以访问cout << "父类Person的保护权限成员:age" << age << endl;//可以访问cout << "父类Person的私有权限成员:address" << address << endl;//报错,不可以访问}
};
int main()
{//创建Person类的对象Person p;//p.name = "张三";//name是Person的公有权限成员可以在类外访问并修改赋值//p.age = 12;//age是保护权限,在类外访问报错//p.address = "北京海淀";//address是私有成员,类外不可以访问//调用赋值函数setInfop.setInfo("李四", 22, "四川");p.showInfo();//显示信息system("pause");return 0;
}

这就是protected和private在继承中的差异

二、class和struct的区别

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

- struct的默认访问权限是共有的

- class默认访问权限是私有的

#include<iostream>
#include<string>
using namespace std;
struct student//默认权限是公有在其他地方可以访问
{string stu_name;
};
class teacher//类的默认全是是私有,类内没有加上public字眼,只有一段语句就属于默认的私有权限
{string tea_name;
};
int main()
{//试图访问struct的成员student stu;//创建结构对象//用结构对象访问结构体中的成员变量stu.stu_name = "罗马";//可以在结构体外访问//试图访问类中的成员teacher tea;tea.tea_name="星星";//无法访问,验证了类的默认权限是私有system("pause");return 0;
}

三、成员属性私有化

1.好处1:控制属性的读写权限

把类内成员属性(变量划入私有权限区域)在类内公开一个可以连接内外的访问函数,控制私有属性的读写权限(读:获取,写:设置)

创建一个Person类,把成员属性姓名,年龄,地址,全部设为私有private

然后再Person开放一个public权限set函数和get函数进行访问类内的私有属性,再在类外调用这两个函数,间接访问private属性

#include<iostream>
#include<string>
using namespace std;
class Person
{
public://开放权限void setName(string set_name)//name的写(设置)权限{name = set_name;}string getName()//name的读权限(获取权限){return name;//返回私有权限的成员name}//void setAge(int set_age)//age的写(设置权限),注释掉,不开放//{//    age = set_age;//}int getAge()//age的只读权限,获取age{return age;//返回私有权限中的成员属性age}//住址的只写权限(设置权限)void setAddress(string set_address){address = set_address;}
private:string name;//姓名 开放读写权限int age = 20;//给年龄设置一个默认参数   年龄 开放只读权限string address;//住址 开放只写权限
};
int main()
{Person p;//创建Person类对象//在类外用对象访问开放权限的读写函数权限,控制相应私有成员属性的读写p.setName("王二");//修改姓名为王二cout << "输出获取到的姓名:" << p.getName() << endl;cout << "输出获取到的年龄:" << p.getAge() << endl;//此时输出的是默认值20岁p.setAddress("北京海淀");//address只开放了写权限//由于setAddress没有返回值,所以呢我们是不能进行输出的system("pause");return 0;
}

2.好处2:检测数据的有效性

我们可以对用户输入的年龄一栏加以控制,首先给age开放一个可写(set)的权限,再控制用户可以写的年龄范围(0~150岁),超出范围则提示用户输入超出范围,并且返回一个默认值0,说明用户年龄设置不成功

#include<iostream>
#include<string>
using namespace std;
class Person
{
public://开放权限void setName(string set_name)//name的写(设置)权限{name = set_name;}string getName()//name的读权限(获取权限){return name;//返回私有权限的成员name}void setAge(int set_age)//开放age的写权限,并且控制用户的输入{//用if语句控制用户设置的年龄范围在0~150岁之间if (set_age < 0 || set_age>150){//若发生超限情况,把private中的age强制改为0,并输出age = 0;//设置一个默认返回值,确保程序安全运行cout << "您输入的年龄超出正常人类的范围啦!"  << endl;return;//返回0,错误值}//用户输入正常数据则返回用户输入的数据age = set_age;}int getAge()//age的只读权限,获取age{return age;//返回私有权限中的成员属性age}//住址的只写权限(设置权限)void setAddress(string set_address){address = set_address;}
private:string name;//姓名 开放读写权限int age ;//给年龄设置一个默认参数   年龄 开放只读权限string address;//住址 开放只写权限
};
int main()
{Person p;//创建Person类对象//在类外用对象访问开放权限的读写函数权限,控制相应私有成员属性的读写//p.setName("王二");//修改姓名为王二//cout << "输出获取到的姓名:" << p.getName() << endl;p.setAge(11000);//超出范围会输出报错结果cout << "p.setAge(11000)的输出:" << (int)p.getAge() << endl;p.setAge(19);//正常输出cout << "p.setAge(19)的输出" << p.getAge() << endl;//cout << "输出获取到的年龄:" << p.getAge() << endl;//p.setAddress("北京海淀");//address只开放了写权限//由于setAddress没有返回值,所以呢我们是不能进行输出的system("pause");return 0;
}

p.setAge(11000);//超出范围会报错
    cout << "p.setAge(11000)的输出:" << p.getAge() << endl;
    p.setAge(19);//正常输出
    cout << "p.setAge(19)的输出" << p.getAge() << endl;

四、案例

1.立方体类

设计立方体类,求出立方体的面积和体积,分别用全局函数和成员函数判断两个立方体是否相等

#include<iostream>
#include<string>
using namespace std;class Cube//立方体的英文是the cube
{
public://共有权限double L;//立方体的长 成员属性double W;//立方体的宽 成员属性double H;//立方体的高 成员属性
//public://开放权限
//  //double set_L;//外界供用户输入的长
//  //double set_W;//外界供用户输入的宽
//  //double set_H;//外界供用户输入的高void setLWH(double set_L, double set_W, double set_H)//设置长宽高的函数,便于外部对私有属性的写(设置set){cout << "请输入立方体的长:" << endl;cin >> set_L;L = set_L;cout << "请输入立方体的宽:" << endl;cin >> set_W;W = set_W;cout << "请输入立方体的高:" << endl;cin >> set_H;H = set_H;}double calArea()//立方体表面积计算函数{//长方体的表面积=(长×宽+宽×高+长×高)×2//判断,如果是正方体,长宽高相等//正方体表面积计算公式=棱长×棱长×6,长*宽*6if (L == W == H){return L * W * 6;//如果是正方体}else//否则可判定为长方体,执行长方体面积计算结果{double area = (L*W + W * H + L * H) * 2;return area;}}double calV()//立方体的体积计算函数(成员函数){if (L == W == H)//正方体的体积计算公式V=a×a×a,L*W*H{return L * L*L;}else//长方体体积计算公式长×宽×高{return L * W*H;}}//成员函数判断两个立方体是否相等//class Cube类内,只需要传入一个外部类对象再跟类内部的做对比就可以判断了void isEqualityClass(Cube & cu3){if (L == cu3.L&&W == cu3.W&&H == cu3.H){cout << "成员函数判断出两个立方体相等" << endl;}else{cout << "成员函数判断出两个立方体相等" << endl;}}
};
//全局函数判断两个立方体是否相等
void isEquality(Cube & cu, Cube &cu2)//传入两个对象的引用
{if (cu.L == cu2.L&&cu.W == cu2.W&&cu.H == cu2.H)//如果两个对象的LWH都相等{cout << "全局函数判断出两个立方体相等" << endl;}else{cout << "全局函数判断出两个立方体不相等" << endl;}
}
int main()
{Cube cu;//一键输入立方体的长宽高cu.setLWH(10, 20, 30);//参数可以随便输入,因为我们在成员函数体内设置了由用户输入,会由用户输入的数据替代原始数据输出cout << "面积" << cu.calArea() << endl;cout << "体积" << cu.calV() << endl;Cube cu2;cu2.setLWH(1, 2, 3);cout << "cu2的面积" << cu2.calArea() << endl;cout << "cu2的体积" << cu2.calV() << endl;isEquality(cu, cu2);cu.isEqualityClass(cu2);system("pause");return 0;
}

输出结果,可以设置,计算也可以用全局函数和成员函数判断

2.点和圆的关系

设计一个圆类(Circle)和一个点类(Point),计算圆和点之间的关系

圆和点有什么关系?

点在圆内,点在圆边上,点在圆外

假设圆的半径为r,点到圆心的距离为d,则有:d<r点在圆内,d=r点在圆上,d>r点在圆外

点与圆的位置关系 点P(x1,y1) 与圆(x-a)²+(y-b)²=r²的位置关系:

(1)当(x1-a)²+(y1-b)²>r²时,则点P在圆外。

(2)当(x1-a)²+(y1-b)²=r²时,则点P在圆上。

(3)当(x1-a)²+(y1-b)²<r²时,则点P在圆内。

圆的标准方程(x-a)²+(y-b)²=r²中,有三个参数a、b、r,即圆心坐标为(a,b),只要求出 a、b、r,这时圆的方程就被确定,因此确定圆方程,须三个独立条件,其中圆心坐标是圆 的定位条件,半径是圆的定形条件。

#include<iostream>
#include<string>
using namespace std;
class Circle//圆类
{
public:double cX;//圆心的x坐标double cY;//圆心的Y坐标double r;//圆半径
public:void setR(double set_r,double set_cX,double set_cY){cout << "请输入圆的半径" << endl;cin >> set_r;r = set_r;cout << "请输入圆心的x坐标" << endl;cin >> set_cX;cX = set_cX;cout << "请输入圆心的y坐标" << endl;cin >> set_cY;cY = set_cY;}
};
class Point//点类
{
public:double pX;//点的x坐标double pY;//点的y坐标
public:void setXY(double set_x, double set_y)//设置点的xy坐标{cout << "请输入点的x坐标" << endl;cin >> set_x;pX = set_x;cout << "请输入点的y坐标" << endl;cin >> set_y;pY = set_y;}
};
//用全局函数判断点和圆的关系
void isLocation(Circle c,Point p)
{double d = ((p.pX - c.cX)*(p.pX - c.cX) + (p.pY - c.cY)*(p.pY - c.cY));double sqrtR = c.r*c.r;if (d > sqrtR)//距离大于半径{cout << "点在圆外" << endl;}if (d == sqrtR)//距离等于半径{cout << "点在圆上" << endl;}if (d < sqrtR)//距离小于半径的平方{cout << "点在圆内" << endl;}
}
int main()
{Circle c;//创建圆的对象c.setR(1, 2, 3);//这里的参数可以随便传,结果以用户输入的为准Point p;//创建点的对象p.setXY(1, 2);//这里的参数可以随便传,结果以用户输入的为准//调用全局函数判断点和圆的关系isLocation(c, p);system("pause");return 0;
}

程序的运行结果如下

费曼学习法,边学习,边cout

C++类与对象——封装相关推荐

  1. python 参数类型的多态_【Python】面向对象:类与对象\封装\继承\多态

    六.Python面向对象--类与对象\封装\继承\多态 1.什么是面向对象编程 1.1 程序设计的范式:程序可控,易于理解 1.2 抽象并建立对象模型 1.3 程序是不同对象相互调用的逻辑.每个对象在 ...

  2. [黑马程序员C++笔记]P99-P104类和对象-封装

    视频地址:黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难_哔哩哔哩_bilibili 目录 P99类和对象-封装-属性和行为作为整体 P100类和对象-封装-案例-设计学生类 P101 ...

  3. 【学习笔记】C++ 核心编程(二)类和对象——封装

    内容来自小破站<黑马程序员C++>复习自用 [学习笔记]C++ 核心编程(二)类和对象--封装 4 类和对象 4.1 封装 4.1.1 封装的意义(一) 4.1.1 封装的意义(二) 4. ...

  4. 装饰器/使用类和对象封装一个工具类

    # coding:utf-8 # 装饰器是以@开头,@结构称为语法糖,装饰器的作用主要是给现有的函数增加一些额外的功能. # @classmethod # @staticmethod # @prope ...

  5. 【黑马程序员 C++教程从0到1入门编程】【笔记4】C++核心编程(类和对象——封装、权限、对象的初始化和清理、构造函数、析构函数、深拷贝、浅拷贝、初始化列表、友元friend、运算符重载)

    黑马程序员C++教程 文章目录 4 类和对象(类属性[成员属性],类函数[成员函数]) 4.1 封装 4.1.1 封装的意义(三种权限:public公共.protected保护.private私有)( ...

  6. C++阶段03笔记02【类和对象(封装、对象的初始化和清理、对象模型和this指针、友元、运算符重载、继承、多态)】

    C++| 匠心之作 从0到1入门学编程[视频+课件+笔记+源码] 目录 1.内存分区模型 2.引用 3.函数提高 4.类和对象 4.1.封装 4.1.1.封装的意义 --实例1:设计圆类 --实例2: ...

  7. python类与对象 封装继承与多态 0308

    类与对象 初始化方法 init方法 带参实例化类 del方法 str方法 私有 继承 方法的重写 super 父类名称调父类方法 调用父类私有 间接调用 多继承 新式类经曲类 多态 类属性 类方法 静 ...

  8. 【JavaSE】类与对象--封装性

    文章目录 一.面向对象的三大特性 二.封装性 1.什么是封装性? 2.为什么要有封装性? 3.封装性的作用 4.封装性的实现步骤 5.访问限定修饰符 一.面向对象的三大特性 面向对象的三个基本特征是: ...

  9. 面向对象 详解笔记 方法 类 对象 封装 继承 重写 多态 接口

    文章目录 面向过程&面向对象 面向过程 面向对象 什么是面向对象 回顾方法及加深 方法的定义 修饰符 返回类型 break:跳出switch,结束循环和return的区别 方法名:注意规范就o ...

最新文章

  1. python详细安装教程3.7.0-python 3.7.0 安装配置方法图文教程
  2. C++里如何使用功能键(F1、F2·····)进行操纵?
  3. TensorFlow 调用预训练好的模型—— Python 实现
  4. 面试题24. 反转链表
  5. 微信小程序 drawImage 问题
  6. CentOS安装vim
  7. kaggle无法注册(含解决方案)
  8. 阿里云大学:百度贴吧自动签到实现
  9. web前端面试题-1
  10. Linux C编程(五) 之 gdb详解
  11. 使用auto.js模拟手动点击芭芭农场任务(芭芭农场自动脚本2022.8.1更新)
  12. vue自定义翻页组件
  13. 运维工程师主要做什么_网络工程师和网络运维工程师到底有什么不同?
  14. 什么是悲观锁和乐观锁,及分布式锁的实现方式
  15. melodic 奥比中光(orbbec)相机安装
  16. 小白如何学习操作系统?
  17. XZ_Swift 之输入框的各种限制,看这一篇就够了:输入框只能输入字母、数字和中文,控制输入特殊字符和表情
  18. 京东金融信贷需求预测机器学习竞赛--代码重构--特征工程
  19. 霍尼韦尔门禁说明书_Honeywell门禁系统简要操作说明.doc
  20. java实现刻录机刻录功能(dom4j+imapi)Windows版

热门文章

  1. Python大学计算机程序设计-通讯录管理系统
  2. vue中的几个动效网站
  3. python 中文排序(按拼音首字母)
  4. Navicat数据备份
  5. 计算机组成原理简答题
  6. PowerDesigner 修改 DBMS
  7. A Brief History of Humankind — 01 the cognitive revolution
  8. 视频直播技术详解之现代播放器原理
  9. ORA-16032: parameter LOG_ARCHIVE_DEST_3 destination string cannot be translated
  10. Timeline 时间线基础用法