【C++总结】05:封装

封装


C++面向对象的三大特性为:封装、继承、多态。万物皆为对象,对象有其相应的属性和行为。

一、封装:

封装是C++面向对象三大特性之一,

1.封装的意义:
  1. 将属性和行为作为一个整体,表现生活中的事物。
  2. 将属性和行为加以权限控制
#include<iostream>
using namespace std;

const double PI = 3.14;

//设计一个圆类,求圆的周长
class Circle {
public:
    int r;
    double calculate() {
        return 2 * PI * r;
    }
};

int main() {
    //通过Circle类创建具体的对象(对象实例化)
    Circle c1;
    //通过对象给对象的属性赋值
    c1.r = 10;
    //通过对象的方法计算圆的周长
    cout  << "圆的周长为" << c1.calculate() << endl;

    return 0;
}

image-20211207223021713

注意:c中的struct结构体(默认为公有)与cpp中的class类(默认为私有)唯一的区别在于默认的访问权限不同。

2.封装访问权限:

访问权限包括三种:

权限说明
public公共权限成员,类内可以访问、类外可以访问
protected保护权限成员,类内可以访问、类外不可以访问(儿子可以访问父亲中的保护内容)
private私有权限成员,类内可以访问、类外不可以访问(儿子不可以访问父亲中的保护内容)

注意protected权限与private权限之间的区别:继承的子类是否可以访问到父类protected权限中的内容。

3.成员属性私有化:
  • 优点1:将所有成员属性设置为私有,可以自己控制读写权限。
  • 优点2:对于写权限,可以检测数据的有效性。
#include<iostream>
using namespace std;

class Person {
private:
    string name;
    int age;
public:
    void setName(string n) {
        name = n;
    }
    string getName() {
        return name;
    }
    void setAge(int a) {
        //检测数据的有效性
        if (a < 0 || a > 150) {
            cout << "输入数据无效!" << endl;
            return ;
        }
        age = a;
    }
    int getAge() {
        return age;
    }
};

int main() {
    Person person;
    person.setName("luochenhao");
    person.setAge(-3);
    person.setAge(20);

    cout << "姓名为:" << person.getName() << endl;
    cout << "年龄为:" << person.getAge() << endl;
    system("pause");
    return 0;
}

image-20220111105450529

4.封装案例—点与圆的关系判断:
#include <iostream>
using namespace std;

//1.设计点类
class Point{
public:
    void setX(int m){
        x = m;
    }
    int getX(){
        return x;
    }
    void setY(int n){
        y = n;
    }
    int getY(){
        return y;
    }
private:
    int x;
    int y;
};

//2.设计圆类
class Circle{
public:
    //(1)设置&获取半径
    void setR(int z) {
        r = z;
    }
    int getR() {
        return r;
    }
    //(2)设置&获取圆心
    void setCenter(Point p) {
        c = p;
    }
    Point getCenter(){
        return c;
    }
private:
    int r;
    Point c;
};

//3.设计判断点与圆的关系类
void isInCircle(Circle &c, Point &p){
    //(1)计算两点之间距离的平方
    int distance =
    (c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) +
    (c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY());
    cout << distance << endl;
    //(2)计算半径的平方
    int rDistance = c.getR() * c.getR();
    cout << rDistance << endl;
    //(3)判断点在圆的位置关系
    if(distance == rDistance) {
        cout << "点在圆上" << endl;
    } else if(distance > rDistance) {
        cout << "点在圆外" << endl;
    } else {
        cout << "点在圆内" << endl;
    }
}

int main() {
    //模拟测试
    //(1)创建圆
    Point center;
    center.setX(10);
    center.setY(0);
    Circle c;
    c.setR(10);
    c.setCenter(center);
    //(2)创建点
    Point p;
    p.setX(10);
    p.setY(10);
    //(3)判断关系
    isInCircle(c, p);

    system("pause");
    return 0;
}

image-20220115222155859

5.封装后类的分文件编写:

创建一个project文件,对封装案例进行分文件编写:

报错处理:redefinition of class xxx,了解关于#ifndef#define#endif的实际作用。

文件结构:

image-20220115231921186

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

void isInCircle(Circle &c, Point &p){
    //(1)计算两点之间距离的平方
    int distance =
    (c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) +
    (c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY());
    cout << distance << endl;
    //(2)计算半径的平方
    int rDistance = c.getR() * c.getR();
    cout << rDistance << endl;
    //(3)判断点在圆的位置关系
    if(distance == rDistance) {
        cout << "点在圆上" << endl;
    } else if(distance > rDistance) {
        cout << "点在圆外" << endl;
    } else {
        cout << "点在圆内" << endl;
    }
}

int main() {
    //模拟测试
    //(1)创建圆
    Point center;
    center.setX(10);
    center.setY(0);
    Circle c;
    c.setR(10);
    c.setCenter(center);
    //(2)创建点
    Point p;
    p.setX(10);
    p.setY(10);
    //(3)判断关系
    isInCircle(c, p);

    system("pause");
    return 0;
}
#ifndef POINT_H_INCLUDED
#define POINT_H_INCLUDED

#include <iostream>
using namespace std;

class Point{
public:
    void setX(int m);
    int getX();
    void setY(int n);
    int getY();
private:
    int x;
    int y;
};

#endif // POINT_H_INCLUDED
#ifndef CIRCLE_H_INCLUDED
#define CIRCLE_H_INCLUDED

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

class Circle{
public:
    void setR(int z);
    int getR();
    void setCenter(Point p);
    Point getCenter();
private:
    int r;
    Point c;
};

#endif // CIRCLE_H_INCLUDED
#include "point.h"

//注意"Point::"用于声明该函数为Point作用域下的一个成员函数
void Point::setX(int m){
    x = m;
}
int Point::getX(){
    return x;
}
void Point::setY(int n){
    y = n;
}
int Point::getY(){
    return y;
}
#include "circle.h"

void Circle::setR(int z) {
    r = z;
}
int Circle::getR() {
    return r;
}
void Circle::setCenter(Point p) {
    c = p;
}
Point Circle::getCenter(){
    return c;
}

image-20220115232124743

二、友元:

在程序中有些私有属性也想让类外特殊的一些函数 or 类进行访问,就需要使用到友元技术。

友元的目的就是让一个函数 or 类访问另一个类中的私有成员,友元的关键字为friend

友元的三种实现包括:全局函数做友元、类做友元、成员函数做友元

1.全局函数做友元:

全局函数做友元的关键实现:friend void 全局函数名();

#include<iostream>
using namespace std;

//1.建筑物类
class Building{
    friend void goodGay(Building *building);//关键语句:将全局函数设置为友元
public:
    Building(){
        sittingRoom = "客厅";
        bedRoom = "卧室";
    }
    string sittingRoom;
private:
    string bedRoom;
};

//2.全局函数
void goodGay(Building *building){
    cout << "好基友的全局函数正在访问:" << building->sittingRoom << endl;
    cout << "好基友的全局函数正在访问:" << building->bedRoom << endl;
}

void test01(){
    Building building;
    goodGay(&building);
}

int main(){
    test01();

    system("pause");
    return 0;
}

image-20220124000952739

2.类做友元:

类做友元的关键实现:friend class 友元类名;

#include<iostream>
using namespace std;

class Building;
class GoodGay{
public:
    GoodGay();
    void visit();//参观函数访问Building中的属性
private:
    Building *building;
};

class Building{
    friend class GoodGay;//设置GoodGay类可以访问Buiding类中的私有成员
public:
    Building();
    string sittingRoom;
private:
    string beddingRoom;
};

//1.类外实现构造函数Building进行初始化操作,初始化string字符串操作
Building::Building(){
    sittingRoom = "客厅";
    beddingRoom = "卧室";
}

//2.类外实现构造函数GoodGay进行初始化操作,初始化指针指向堆区的一块内存
GoodGay::GoodGay(){
    building = new Building;
}

void GoodGay::visit(){
    cout << "好基友类正在访问:" << building->sittingRoom << endl;
    cout << "好基友类正在访问:" << building->beddingRoom << endl;
}

void test01(){
    GoodGay goodGay;
    goodGay.visit();
}

int main(){
    test01();
    system("pause");
    return 0;
}

image-20220126192505639

3.成员函数做友元:

成员函数做友元的关键实现:friend 类名::成员函数名();

#include<iostream>
using namespace std;

class Building;
class GoodGay{
public:
    GoodGay();
    void visit1();//成员函数visit1可以访问到Building中的私有内容
    void visit2();//成员函数visit2不可以访问到Building中的私有内容
private:
    Building *building;
};

class Building{
    friend void GoodGay::visit1();//设置GoodGay类中的成员函数visit1可以访问Buiding类中的私有成员
public:
    Building();
    string sittingRoom;
private:
    string beddingRoom;
};

//1.类外实现构造函数Building进行初始化操作,初始化string字符串操作
Building::Building(){
    sittingRoom = "客厅";
    beddingRoom = "卧室";
}

//2.类外实现构造函数GoodGay进行初始化操作,初始化指针指向堆区的一块内存
GoodGay::GoodGay(){
    building = new Building;
}

void GoodGay::visit1(){
    cout << "visit1函数正在访问:" << building->sittingRoom << endl;
    cout << "visit1函数正在访问:" << building->beddingRoom << endl;
}

void GoodGay::visit2(){
    cout << "visit2函数正在访问:" << building->sittingRoom << endl;
    //cout << "visit2函数正在访问:" << building->beddingRoom << endl;
}

void test01(){
    GoodGay goodGay;
    goodGay.visit1();
    goodGay.visit2();
}

int main(){
    test01();
    system("pause");
    return 0;
}

image-20220126194609264

注意:在程序中多个类之间存在相互联系,且需要类外实现构造函数需要特别注意书写顺序,否则容易报错。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的示例,展示了如何使用C语言封装一个INI文件类: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> // 定义INI文件类结构体 typedef struct { char* filename; } IniFile; // 初始化INI文件类 void IniFile_Init(IniFile* ini, const char* filename) { ini->filename = strdup(filename); } // 释放INI文件类 void IniFile_Free(IniFile* ini) { free(ini->filename); } // 读取INI文件中的值 const char* IniFile_GetValue(IniFile* ini, const char* section, const char* key) { FILE* file = fopen(ini->filename, "r"); char line[256]; // 假设每行不超过256个字符 // 遍历文件中的每一行 while (fgets(line, sizeof(line), file)) { // 查找section if (strstr(line, section)) { // 查找key while (fgets(line, sizeof(line), file)) { if (strstr(line, key)) { // 提取value char* value = strchr(line, '='); if (value) { value++; // 跳过等号 value[strcspn(value, "\r\n")] = '\0'; // 去除换行符 fclose(file); return value; } } } } } fclose(file); return NULL; // 未找到对应的section和key } // 示例用法 int main() { IniFile ini; IniFile_Init(&ini, "config.ini"); const char* value = IniFile_GetValue(&ini, "SectionName", "KeyName"); if (value) { printf("Value: %s\n", value); } else { printf("Value not found.\n"); } IniFile_Free(&ini); return 0; } ``` 在上述示例中,我们定义了一个`IniFile`结构体,该结构体包含一个`filename`字段用于存储INI文件的路径。 首先,我们使用`IniFile_Init`函数初始化`IniFile`结构体,并指定INI文件的路径。 然后,我们使用`IniFile_GetValue`函数来读取INI文件中的值。该函数接受两个参数:`section`和`key`,并返回对应的值。在函数内部,我们使用标准C库函数来逐行读取INI文件,查找指定的section和key,并提取对应的value。 最后,我们在示例的`main`函数中展示了如何使用封装的INI文件类。你可以根据实际需求修改和扩展这个示例。 希望这个示例能够帮助你封装一个简单的INI文件类。如果有任何进一步的问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值