【C++第二阶段】封装之类访问权限 & struct class区别&成员设置私有&案例

内容包括 : 访问权限,class,struct区别,成员属性设置为私有,设计案例。

访问权限

C++中的访问权限有3种,对于成员属性/变量及成员函数/方法,都一样。

public的成员属性/变量及成员函数/方法,无论是在类内还是在类外(main()函数或其他函数中),都可以访问(我理解为更改==编辑==赋值)。

protected的成员属性/变量及成员函数/方法,类内可以访问,类外不可以访问。

private的成员属性/变量及成员函数/方法,类内可以访问,类外不可以访问。

protectedprivate都是类内可以访问,类外不可以访问,区别是什么?前者在继承时,可以被子类访问(更改==编辑==赋值),而后者不可以。

设计实验,说明以上的语法。

①所有成员属性和成员函数都设置为public,进行类内和类外的访问。

#include<iostream>
#include<string>
#include"BlackHorseFunctions.h"
using namespace std;

class Father{
public:
    string class_father_name;

    void set_class_father_name(string name){
        class_father_name = name;
    }
    void print(){
        cout<<"父类名字为:"<<class_father_name<<"。"<<endl;
    }
};

int main(){
    Father washton;
    washton.class_father_name = "Washton";
    washton.print();
    return 0;
}

此时没有报错,运行结果为:

D:\Program\C++\BlackHorse\Clion\cmake-build-debug\BlackHorse.exe
父类名字为:Washton。

进程已结束,退出代码0

实验设计②

所有成员属性及成员函数设置为protected,在类外访问。

#include<iostream>
#include<string>
#include"BlackHorseFunctions.h"
using namespace std;

class Father{
protected:
    string class_father_name;

    void set_class_father_name(string name){
        class_father_name = name;
    }
    void print(){
        cout<<"父类名字为:"<<class_father_name<<"。"<<endl;
    }
};

int main(){
    Father washton;
    washton.class_father_name = "Washton";
    washton.print();
    return 0;
}

结果为:

image-20240129111108399

但若仅将成员变量设置为私有,可以运行:

class Father{
protected:
    string class_father_name;
public:
    void set_class_father_name(string name){
        class_father_name = name;
    }
    void print(){
        cout<<"父类名字为:"<<class_father_name<<"。"<<endl;
    }
};

int main(){
    Father washton;
    washton.set_class_father_name("Washton");
    washton.print();
    return 0;
}

运行结果:

D:\Program\C++\BlackHorse\Clion\cmake-build-debug\BlackHorse.exe
父类名字为:Washton。

进程已结束,退出代码0

说明可以通过public权限的成员函数将值传递给成员变量。

③将成员属性设置为private,但成员函数仍然是public。

运行结果仍然如上。

C++中,struct和class有什么区别?

①前者默认权限为public,后者默认权限是private

②前者能定义方法吗?我不知道。后者可以定义方法。

以实验代码说明两者权限。分别创建结构体和类,及成员变量,并在主函数中访问。看是否会报错。

#include<iostream>
#include<string>
#include"BlackHorseFunctions.h"
using namespace std;

class ClassVSStruct{
    int variable;
};

struct StructVSClass{
    int variable;
};


int main(){
    ClassVSStruct cvss;
    StructVSClass svsc;
    cvss.variable = 100;
    svsc.variable = 100;
	return 0;
	}
	

可以看到编译器提示,类的默认权限为private

image-20240129113355087

说明类的默认权限是私有。

成员属性设置为私有

优点①:将所有成员属性设置为私有,可以控制读写权限。

优点②:对于写权限,可以检测数据的有效性。

对于优点①,拿实验来说明,对于一个人,希望昵称是可以读,也可以写的,因为不同平台的昵称可能不同;对于年龄,希望是可以读的,因为短期内不会突然长老;对于idol,希望只是可以写的,因为是独属于自己的idol。

对于优点②,进行年龄的验证,如果年龄输入的有点离谱,返回默认年龄。

根据这个思路,来进行代码编写。

//对于优点①,拿实验来说明,对于一个人,希望昵称是可以读,也可以写的,因为不同平台的昵称可能不同;
// 对于年龄,希望是可以读的,因为短期内不会突然长老;
// 对于idol,希望只是可以写的,因为是独属于自己的idol。
class Person{
    string person_name;
    short int person_age = 18;
    string person_idol;
public:
    void setName(string name){
        person_name = name;
    }
    string getName(){
        return person_name;
    }

    int getAge(){
        return person_age;
    }

//    年龄验证
    void setAge(short int age){
        if (age < 0 || age > 150){
            cout<<"年龄为:"<<age<<",是修仙了吗?"<<endl;
            return;
        }
        person_age = age;
    }

    void setIdol(string idol){
        person_idol = idol;
    }
};


int main(){
    Person jack;
    string jack_name;
    short int jack_age;
    string jack_idol;

    jack_name = "Jack.Smith";
    jack.setName(jack_name);
    cout<<"获取Jack名称为:"<<jack.getName()<<endl;

    jack_age = 1000;
    jack.setAge(jack_age);
    cout<<"获取jack年龄为;"<<jack.getAge()<<endl;

    jack_idol = "张艺兴";
    jack.setIdol(jack_idol);
    
    return 0;
}

两个案例

案例①

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

我的思路:首先面积和体积是由长宽高算出来的,这个长宽高是私有的,所以只能写入,不能得到。接着就是计算它的表面积和体积。

代码:

#include<iostream>
#include<string>
using namespace std;

struct CubeArray{
    double Array[3];
    short int len = 3;
};


CubeArray Sort(double number1 , double number2 , double number3 , CubeArray &cube_array){
    cube_array.Array[0] = number1;
    cube_array.Array[1] = number2;
    cube_array.Array[2] = number3;

    for(int i = 0 ; i<cube_array.len; i++){
        for(int j = 0; j<cube_array.len - i -1 ; j++){
            if (cube_array.Array[j] > cube_array.Array[j+1]){
                double temp = cube_array.Array[j];
                cube_array.Array[j] = cube_array.Array[j+1];
                cube_array.Array[j+1] = temp;
            }
        }
    }

    for (int i = 0 ; i< cube_array.len;i++){
        cout<<"第"<<i<<"个元素为:"<<cube_array.Array[i]<<endl;
    }

    return cube_array;
}

class Cube {
    double length = 0;
    double width = 0;
    double depth = 0;
public:
    void set_length(double len) {
        if (len < 0) {
            cout << "这长度超出我认知了,dude!" << endl;
            return;
        }
        length = len;
    }

    double get_length() {
        return length;
    }

    void set_width(double wid) {
        if (wid < 0) {
            cout << "这宽度超出我认知了,dude!" << endl;
            return;
        }
        width = wid;
    }

    double get_width() {
        return width;
    }

    void set_depth(double dep) {
        if (dep < 0) {
            cout << "这高度超出我认知了,dude!" << endl;
            return;
        }
        depth = dep;
    }

    double get_depth() {
        return depth;
    }

    double get_superficial_area() {
        return 2 * (length * width + length * depth + width * depth);
    }

    double get_bulk() {
        return length * width * depth;
    }

//        利用成员函数判断,应该传入另一个立方体的数据
    void distinguish(Cube &cube) {


        CubeArray res_array , ult_array;
//    cout<<"res数组排序"<<endl;
        res_array = Sort(get_length(),get_width(),get_depth()  , res_array );
//    for (int i = 0 ; i< res_array.len;i++){
//        cout<<"res_array中第"<<i<<"个元素为:"<<res_array.Array[i]<<endl;
//    }

//    cout<<"ult数组排序"<<endl;
        ult_array = Sort(cube.get_length() ,cube.get_width() , cube.get_depth() ,  ult_array );
//    for (int i = 0 ; i< res_array.len;i++){
//        cout<<"ult_array中第"<<i<<"个元素为:"<<ult_array.Array[i]<<endl;
//    }

        for(int i = 0 ; i<res_array.len; i++){
            if(res_array.Array[i] != ult_array.Array[i]){
//            cout<<"此时res_array值为:"<<res_array.Array[i]<<"。"<<endl;
//            cout<<"此时ult_array值为:"<<ult_array.Array[i]<<"。"<<endl;
                cout<<"两者不一致了。"<<endl;
                break;
            }else{

            }
            if(i == 2){
                cout<<"两者一致。"<<endl;
            }
        }
    }
};

double Calculate_Superficial_Area(double &length , double &width , double &depth){
    return 2*(length * width + length*depth + width*depth);
}
double Calculate_Bulk(double &length , double &width , double &depth){
    return length*width*depth;
}




void Distinguish(Cube &res , Cube &ult){
    CubeArray res_array , ult_array;
//    cout<<"res数组排序"<<endl;
    res_array = Sort(res.get_length(),res.get_width(),res.get_depth()  , res_array );
//    for (int i = 0 ; i< res_array.len;i++){
//        cout<<"res_array中第"<<i<<"个元素为:"<<res_array.Array[i]<<endl;
//    }

//    cout<<"ult数组排序"<<endl;
    ult_array = Sort(ult.get_length() ,ult.get_width() , ult.get_depth() ,  ult_array );
//    for (int i = 0 ; i< res_array.len;i++){
//        cout<<"ult_array中第"<<i<<"个元素为:"<<ult_array.Array[i]<<endl;
//    }

    for(int i = 0 ; i<res_array.len; i++){
        if(res_array.Array[i] != ult_array.Array[i]){
//            cout<<"此时res_array值为:"<<res_array.Array[i]<<"。"<<endl;
//            cout<<"此时ult_array值为:"<<ult_array.Array[i]<<"。"<<endl;
            cout<<"两者不一致了。"<<endl;
            break;
        }else{

        }
        if(i == 2){
            cout<<"两者一致。"<<endl;
        }
    }

}
int main(){

	Cube cu,be;
    double cu_length = 2.3;
    double cu_width = 2.2;
    double cu_depth = 1.1;
    cu.set_length(cu_length);
    cu.set_width(cu_width);
    cu.set_depth(cu_depth);

    double be_length = 2.2;
    double be_width = 1.1;
    double be_depth = 2.3;
    be.set_length(be_length);
    be.set_width(be_width);
    be.set_depth(be_depth);


    double cube_superficial_area = cu.get_superficial_area();
    double cube_bulk = cu.get_bulk();

    double global_superficial_area = Calculate_Superficial_Area(cu_length , cu_width , cu_depth);
    double global_bulk = Calculate_Bulk(cu_length , cu_width , cu_depth);

    cu.distinguish(be);

    Distinguish(cu , be);
    
}

因为长宽高可能是翻转的关系,所以没有挨个对比,用了排序,来看三者关系。

案例②

点和圆的关系,有3种关系,但是重点在于类内包含类。在这个案例中,就是圆里面要有圆心,这个圆心是一个点,可以作为一个类。

另外一个要掌握的知识点就是分文件编写。

头文件中包括函数和类(成员属性和成员函数)的声明

头文件有两个circle.h和point.h,对应的两个源文件里要有声明,声明时要写输入输出流以及命名空间吗?实现要写输入输出流以及命名空间吗?

问题①:先写#pragma once,要写输入输出流以及命名空间。

问题②:需要写,并且还要写对应的头文件。

在实现源文件中,首先删除class以及大括号以及成员变量。然后,可能会报错,因为写在源文件中编译器会认为这是全局函数,但实际上是成员函数这时需要在 前面写类名::,这样编译器就认为这是某个类名的作用域下的成员函数。
point.h

#pragma once
#include<iostream>
#include<string>
using namespace std;

class Point {
    int point_x;
    int point_y;
public:
    void set_point_x(int x);

    int get_point_x();

    void set_point_y(int y);
    int get_point_y();
};

circle.h

#pragma once
#include<iostream>
#include<string>
#include"point.h"
using namespace std;

class Circle {
    int circle_radius;
    Point circle_center;
public:
    void set_circle_radius(int radius);
    int get_circle_radius();

    int get_center2point_distance(Point& circle_center, Point& point);

    void in_or_equal_or_out(int distance, int radius);
};

Point.cpp

#include<iostream>
#include<string>
#include"point.h"
using namespace std;


void Point::set_point_x(int x) {
    point_x = x;
}

int Point::get_point_x() {
    return point_x;
}

void Point::set_point_y(int y) {
    point_y = y;
}
int Point::get_point_y() {
    return point_y;
}

Circle.cpp

#include<iostream>
#include<string>
using namespace std;
#include"point.h"
#include"circle.h"

void Circle::set_circle_radius(int radius) {
    circle_radius = radius;
}
int Circle::get_circle_radius(){
    return circle_radius;
}

int Circle::get_center2point_distance(Point& circle_center, Point& point) {
    int distance22 = (circle_center.get_point_x() - point.get_point_x()) * (circle_center.get_point_x() - point.get_point_x())
        + (circle_center.get_point_y() - point.get_point_y()) * (circle_center.get_point_y() - point.get_point_y());
    return distance22;
}

void Circle::in_or_equal_or_out(int distance, int radius) {
    if (radius * radius == distance) {
        cout << "点在圆上" << endl;
    }
    else if (radius * radius < distance) {
        cout << "点在圆外" << endl;
    }
    else {
        cout << "点在圆内" << endl;
    }
}

section-2.cpp

#include<iostream>
#include<string>
#include"point.h"
#include"circle.h"
using namespace std;

int main() {

	Circle circle;
	Point in_point, equal_point, out_point, center;

	int circle_center_x = 0;
	int circle_center_y = 0;
	int radius = 2;

	int in_x = 1;
	int in_y = 1;

	int equal_x = 0;
	int equal_y = 2;

	int out_x = 3;
	int out_y = 3;

	center.set_point_x(circle_center_x);
	center.set_point_y(circle_center_y);

	in_point.set_point_x(in_x);
	in_point.set_point_y(in_y);

	equal_point.set_point_x(equal_x);
	equal_point.set_point_y(equal_y);

	out_point.set_point_x(out_x);
	out_point.set_point_y(out_y);

	circle.set_circle_radius(radius);

	cout << "假设是圆内helsdof是否结束了" << endl;
	int in_distance = circle.get_center2point_distance(center, in_point);
	circle.in_or_equal_or_out(in_distance, circle.get_circle_radius());

	cout << "假设是圆上helsdof是否结束了" << endl;
	int equal_distance = circle.get_center2point_distance(center, equal_point);
	circle.in_or_equal_or_out(equal_distance, circle.get_circle_radius());

	cout << "假设是圆外helsdof是否结束了" << endl;
	int out_distance = circle.get_center2point_distance(center, out_point);
	circle.in_or_equal_or_out(out_distance, circle.get_circle_radius());
	system("pause");
	return 0;
	}

运行结果:

image-20240129181407709

  • 20
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HelpFireCode

随缘惜缘不攀缘。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值