C++学习笔记(十七)——类之封装

一、 封装

作用:
封装(Encapsulation) 是面向对象编程(OOP)的核心特性之一,
把数据和操作数据的函数绑定在一起,并隐藏内部实现细节,防止外部代码直接访问对象的内部数据。

特点:

  1. 保护数据安全:防止外部代码直接修改数据。
  2. 提高代码可维护性:通过接口访问数据,修改实现时不会影响调用代码。
  3. 隐藏实现细节:外部代码无需关心类的内部逻辑,只需使用提供的接口。
  4. 增强可扩展性:可以在不修改接口的情况下改变内部实现。

二、 封装的基本实现

C++ 使用 private、protected、public 访问修饰符实现封装。

访问修饰符 作用
private(默认) 私有成员,只能在类的内部访问
protected 保护成员,可在本类和子类访问
public 公有成员,可被外部访问

示例 ------基本的封装:

cpp 复制代码
#include <iostream>
using namespace std;

class Person {
private:
    string name;  // 私有成员,不能直接访问
    int age;

protected:
    string habit;  // 本类和子类可以访问

public:
    // 构造函数
    Person(string n, int a, string s)
    {
        name = n;
        age = a;
        habit = s;
    }

    // 公有接口(getter 和 setter)
    void setName(string n)
    {
        name = n;
    }
    string getName()
    {
        return name;
    }

    void setAge(int a)
    {
        if (a >= 0) age = a;
    }
    int getAge()
    {
        return age;
    }

    void setHabit(string s)
    {
        habit = s;
    }
    string getHabit()
    {
        return habit;
    }

    void display()
    {
        cout << "姓名: " << name << ", 年龄: " << age << ", 爱好: " << habit << endl;
    }
};

int main() {
    Person p("Alice", 25, "唱歌");

    // p.name = "Bob";  // 错误:name 是 private,不能直接访问
    // p.habit = "跳舞"; // 错误:name 是 protected,不能直接访问
    p.setName("Bob");  // 正确 通过公有接口修改 name
    p.setAge(30);      // 正确 通过公有接口修改 age
    p.setHabit("跳舞"); // 正确 通过公有接口修改 habit

    cout << "姓名: " << p.getName() << endl;
    p.display();

    system("pause");
    return 0;
}

注意:

  • name 和 age 设为 private,habit 设为 protected,外部无法直接访问。
  • 数据成员一般设为 private ,使用公有接口 来间接访问和修改数据。
  • protected 主要用于继承,防止外部访问,但允许子类使用。

三、 getter 和 setter 方法

  • getter(访问器):获取私有成员的值。
  • setter(修改器):设置私有成员的值,同时可以进行数据验证。

示例 ------使用 getter 和 setter:

cpp 复制代码
#include <iostream>
using namespace std;

class Car {
private:
    int speed;

public:
    // 构造函数
    Car() 
    { 
        speed = 0; 
    }

    // getter 方法
    int getSpeed() 
    { 
        return speed; 
    }

    // setter 方法(增加数据验证)
    void setSpeed(int s) 
    {
        if (s >= 0) 
            speed = s;
        else 
            cout << "速度不能为负数!" << endl;
    }
};

int main() {
    Car car;
    car.setSpeed(100);
    cout << "当前速度: " << car.getSpeed() << " km/h" << endl;

    car.setSpeed(-50);  // 错误 触发数据验证

    system("pause");
    return 0;
}

使用 getter 和 setter的作用:

  • 防止直接修改数据,确保数据安全性。
  • 提供数据验证机制,避免非法数据输入。

四、 特殊用法

(1)友元函数(Friend Function)

作用:
友元函数(friend) 允许某些函数访问类的 private 成员,但该函数不属于该类的成员。

示例 ------友元函数访问私有数据:

cpp 复制代码
#include <iostream>
using namespace std;

class Box {
    // 友元函数声明
    friend void printWidth(Box b);

private:
    double width;

public:
    Box(double w) 
    { 
        width = w; 
    }
};

// 友元函数定义
void printWidth(Box b) 
{
    cout << "Box 宽度: " << b.width << endl;  // 访问 private 成员
}

int main() {
    Box box(10.5);
    printWidth(box);  // 友元函数可以访问 private 数据

    system("pause");
    return 0;
}

友元函数的作用:

  • 允许外部函数访问私有数据 ,但仍然保持封装。
  • 不属于类的成员 ,不能用 this 访问对象。

(2)结构体 struct 的封装

在 C++ 中,struct 默认是 public,但也可以使用 private 进行封装。

示例------使用 struct 进行封装:

cpp 复制代码
struct Student {
private:
    string name;

public:
    void setName(string n) 
    { 
    	name = n; 
    }
    string getName() 
    { 
    	return name; 
    }
};

注意:

  • 简单的数据结构使用 struct (如 Point)。
  • 需要封装和继承时,使用 class。
相关推荐
草莓熊Lotso2 小时前
【C++ 基于微服务的即时通讯系统】etcd + brpc 从安装到服务注册发现全链路实战
网络·数据库·c++·redis·微服务·etcd
把我格子衫拿来8 小时前
VTK 9.5 与 Qt 6 联合开发:从嵌入三维窗口到可维护的桌面架构
c++·python·qt·vtk·三维可视化
无忧.芙桃9 小时前
C++语言原理与实践(十六):多态机制讲解
开发语言·c++·多态
优选资源分享9 小时前
PicGo v3.0.3 新版 | 开源免费图床工具
javascript·笔记·electron
星恒随风10 小时前
Linux线程概念详解:从分页存储、页表、MMU与TLB,深入理解线程和进程的区别与联系
linux·运维·笔记·学习·状态模式
qq_2842740510 小时前
数控机床编程基础与坐标系:编程六步流程、程序号/程序段/程序字格式,与右手定则下车床铣床XYZ轴判定(含考点)
笔记·学习·自动化·制造
德林恩宝10 小时前
On-Policy Distillation(OPD)学习文档
人工智能·学习·机器学习·大模型·llm·大模型微调
问心无愧051310 小时前
[SUCTF 2019]EasySQL
笔记
ss27310 小时前
PG实战笔记 | 09 PostgreSQL psql客户端基本操作
数据库·笔记·postgresql
wuminyu10 小时前
JMM学习总结:深入理解happens-before关系
java·linux·c语言·jvm·c++