C++类与对象——封装

目录

前言

一、属性的行为作为整体

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
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++类与对象——封装

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

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

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

#include
#include
using namespace std;
class Student
{
public:
    //学生类的属性
    string stuNum;//学号,用字符串类型,要加上头文件#include
    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;
}

C++类与对象——封装

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

#include
#include
using namespace std;
class Student
{
public:
    //学生类的属性
    string stuNum;//学号,用字符串类型,要加上头文件#include
    string stuName;//学生姓名
    //学生类的行为
    void SetInfor()//设置学生信息,给学生的属性赋值的函数
    {
        cout << "请输入学生姓名:" << endl;
        cin >> stuName;
        cout << "请输入学生学号:" << endl;
        cin >> stuNum;
    }
    void showInfor()//显示学生信息(姓名学号)的函数
    {
        cout << "学生的姓名:" << stuName << endl;
        cout << "学生的学号:" << stuNum << endl;
    }
};

int main()
{
    //创建学生类的对象
    Student stu;
    //利用对象访问其中的行为
    //用户输入的情况下的输出showInfor
    stu.SetInfor();//设置学生的姓名学号
    stu.showInfor();//展示用户设置的学生的姓名学号
    //程序员设定(赋值的情况下的showInfor输出)
    cout << "---------------**---------------" << endl;
    stu.stuNum = "20170911";
    stu.stuName = "罗马星星";
    stu.showInfor();
    system("pause");
    return 0;
}

C++类与对象——封装

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

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

C++类与对象——封装

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

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

三种访问权限(作用域)

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

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

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

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

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

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

#include
using namespace std;
#include
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是私有成员,类外不可以访问
    //调用赋值函数setInfo
    p.setInfo("李四", 22, "四川");
    p.showInfo();//显示信息
    system("pause");
    return 0;
}

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

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

C++类与对象——封装

在继承中的访问权限差异

继承的语法是 class

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;//报错,不可以访问
    }
};

C++类与对象——封装
#include
using namespace std;
#include
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是私有成员,类外不可以访问
    //调用赋值函数setInfo
    p.setInfo("李四", 22, "四川");
    p.showInfo();//显示信息
    system("pause");
    return 0;
}

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

二、class和struct的区别

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

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

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

#include
#include
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;
}

C++类与对象——封装

三、成员属性私有化

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

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

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

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

#include
#include
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;
}

C++类与对象——封装

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

#include
#include
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;

C++类与对象——封装

四、案例

1.立方体类

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

#include
#include
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,长*宽*6
        if (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;
}

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

C++类与对象——封装

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
#include
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;
}

程序的运行结果如下

C++类与对象——封装

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

Original: https://blog.csdn.net/qq_58619891/article/details/127819679
Author: 洛里斯不学习
Title: C++类与对象——封装

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/660807/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球