跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++

C++ 类与对象:封装特性的实现与实战应用

C++ 类与对象是面向对象编程的基础。本文通过实例讲解类的定义、成员变量与函数的组织方式。重点阐述了访问权限控制(public/private/protected)如何实现数据封装,保护内部状态。深入分析了构造与析构函数在对象生命周期管理中的作用,特别是动态内存的分配与释放。最后通过圆形类实战案例,演示了如何设计高内聚低耦合的代码结构,提升软件的可维护性与安全性。

清心发布于 2026/3/28更新于 2026/10/2190 浏览
C++ 类与对象:封装特性的实现与实战应用

C++ 类与对象:封装特性的实现与实战应用

在面向对象编程中,类和对象是最基础的积木。掌握它们的核心概念、封装机制以及生命周期管理,是写出高质量 C++ 代码的关键。

一、类与对象的核心概念

简单来说,类是对一类事物属性和行为的抽象描述,而对象则是类的具体实例,是内存中实际存在的实体。

1.1 类的组成

一个完整的 C++ 类通常包含两部分:

  • 成员变量:描述类的属性,比如人的姓名、年龄,圆的半径等。
  • 成员函数:描述类的行为,比如人的吃饭、跑步,圆的面积计算等。
1.2 类的定义格式
#include <iostream>
#include <string>
using namespace std;

// 类的定义:以 class 关键字开头
class Person {
    // 访问权限修饰符,后续详细讲解
private:
    // 成员变量:属性
    string name;
    int age;
public:
    // 成员函数:行为
    void setInfo(string n, int a); // 设置属性
    void showInfo(); // 展示属性
};
1.3 对象的实例化与使用

对象是类的具体实例,实例化对象的语法与定义普通变量类似,主要有两种方式:

// 方式 1:栈上实例化对象
Person p1;
p1.setInfo("张三", 20);
p1.showInfo();

// 方式 2:堆上实例化对象(需要用 new 关键字)
Person *p2 = new Person();
p2->setInfo(, );
p2->();


 p2;
p2 = ;
"李四"
25
showInfo
// 堆上对象使用后需手动释放内存
delete
nullptr

二、封装的本质:访问权限控制

封装是面向对象三大特性之一,核心是通过访问权限修饰符隐藏类的内部实现细节,只对外暴露必要的接口,提高代码的安全性和可维护性。 C++ 提供了三种访问权限修饰符,作用域从修饰符出现位置开始,到下一个修饰符或类结束为止。

2.1 三种访问权限
修饰符访问范围核心特点
public类内、类外、子类对外公开的接口,允许外部直接访问
protected类内、子类仅允许类自身和子类访问,类外不可见
private类内仅允许类自身访问,子类和类外均不可见

⚠️ 注意事项:类的默认访问权限是 private,结构体 struct 的默认访问权限是 public。

2.2 访问权限的代码演示
#include <iostream>
#include <string>
using namespace std;

class Person {
    // 默认 private
    string addr = "北京市";
private:
    string name;
    int age;
public:
    void setInfo(string n, int a) {
        // 类内可以访问 private 成员变量
        name = n;
        age = a;
    }
    void showInfo() {
        cout << "姓名:" << name << " 年龄:" << age << " 地址:" << addr << endl;
    }
};

int main() {
    Person p;
    p.setInfo("王五", 30);
    p.showInfo();

    // 错误:name 是 private 成员,类外无法访问
    // p.name = "赵六";
    // 错误:addr 是默认 private 成员,类外无法访问
    // p.addr = "上海市";
    return 0;
}

三、构造函数与析构函数:对象的生命周期管理

构造函数负责对象的初始化,析构函数负责对象的清理工作,二者均由编译器自动调用,无需手动触发。

3.1 构造函数
3.1.1 构造函数的特性
  • 函数名与类名完全相同,没有返回值类型,连 void 都不能写。
  • 对象实例化时自动调用,且只调用一次。
  • 可以重载,支持不同方式的初始化。
  • 如果没有手动定义构造函数,编译器会自动生成一个空参构造函数。
3.1.2 构造函数的分类与实现
#include <iostream>
#include <string>
using namespace std;

class Person {
private:
    string name;
    int age;
public:
    // 1. 空参构造函数(默认构造函数)
    Person() {
        cout << "空参构造函数被调用" << endl;
        name = "未知";
        age = 0;
    }

    // 2. 有参构造函数
    Person(string n, int a) {
        cout << "有参构造函数被调用" << endl;
        name = n;
        age = a;
    }

    // 3. 拷贝构造函数(用已有对象初始化新对象)
    Person(const Person &p) {
        cout << "拷贝构造函数被调用" << endl;
        name = p.name;
        age = p.age;
    }

    void showInfo() {
        cout << "姓名:" << name << " 年龄:" << age << endl;
    }
};

// 构造函数的调用方式
int main() {
    // 方式 1:括号法
    Person p1; // 调用空参构造
    Person p2("张三", 20); // 调用有参构造
    Person p3(p2); // 调用拷贝构造

    // 方式 2:显示法
    Person p4 = Person();
    Person p5 = Person("李四", 25);

    // 方式 3:隐式转换法(不推荐)
    Person p6 = {"王五", 30};

    p1.showInfo();
    p2.showInfo();
    return 0;
}

⚠️ 注意事项:使用括号法调用空参构造时,不能写 Person p1(),这会被编译器识别为函数声明,而非对象实例化。

3.2 析构函数
3.2.1 析构函数的特性
  • 函数名以 ~ 开头,后跟类名,没有返回值类型,也没有参数。
  • 对象销毁时自动调用,且只调用一次。
  • 不能重载,一个类只能有一个析构函数。
  • 如果没有手动定义析构函数,编译器会自动生成一个空析构函数。
3.2.2 析构函数的实战价值

析构函数常用于释放对象占用的动态资源,如堆内存、文件句柄等,避免内存泄漏。

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

class Student {
private:
    string *name; // 堆内存指针
    int age;
public:
    // 有参构造:分配堆内存
    Student(string n, int a) {
        cout << "有参构造函数被调用" << endl;
        name = new string(n); // 堆上分配字符串
        age = a;
    }

    // 析构函数:释放堆内存
    ~Student() {
        cout << "析构函数被调用" << endl;
        if (name != nullptr) {
            delete name; // 释放堆内存
            name = nullptr; // 防止野指针
        }
    }

    void showInfo() {
        cout << "姓名:" << *name << " 年龄:" << age << endl;
    }
};

int main() {
    // 栈对象:函数结束时自动销毁,触发析构函数
    Student s1("小明", 18);
    s1.showInfo();

    // 堆对象:手动 delete 时触发析构函数
    Student *s2 = new Student("小红", 17);
    s2->showInfo();
    delete s2;
    s2 = nullptr;
    return 0;
}

四、封装的实战案例:设计一个圆形类

需求:设计一个圆形类 Circle,包含半径属性,提供设置半径、计算面积、计算周长的功能,要求通过封装隐藏半径的直接访问,确保半径的合法性。

4.1 需求分析
  1. 成员变量:半径 radius,设置为 private,避免外部直接修改。
  2. 成员函数:
    • setRadius(double r):设置半径,需校验半径是否大于 0。
    • getRadius():获取半径,对外提供只读接口。
    • getArea():计算圆的面积,公式:S=πr²。
    • getPerimeter():计算圆的周长,公式:C=2πr。
  3. 构造函数:提供空参和有参构造,初始化半径。
4.2 完整代码实现
#include <iostream>
#include <cmath>
using namespace std;

// 定义圆周率常量
const double PI = acos(-1.0);

class Circle {
private:
    // 私有成员变量:半径
    double radius;
public:
    // 空参构造:默认半径为 0
    Circle() {
        radius = 0.0;
        cout << "空参构造函数被调用,默认半径 0" << endl;
    }

    // 有参构造:初始化半径
    Circle(double r) {
        setRadius(r); // 调用 setRadius 做合法性校验
        cout << "有参构造函数被调用,半径设置为 " << radius << endl;
    }

    // 设置半径:校验合法性
    void setRadius(double r) {
        if (r >= 0) {
            radius = r;
        } else {
            cout << "⚠️ 半径不能为负数,默认设置为 0" << endl;
            radius = 0.0;
        }
    }

    // 获取半径
    double getRadius() {
        return radius;
    }

    // 计算面积
    double getArea() {
        return PI * radius * radius;
    }

    // 计算周长
    double getPerimeter() {
        return 2 * PI * radius;
    }
};

int main() {
    // 测试空参构造
    Circle c1;
    cout << "圆 1 半径:" << c1.getRadius() << endl;
    cout << "圆 1 面积:" << c1.getArea() << endl;
    cout << "圆 1 周长:" << c1.getPerimeter() << endl;
    cout << "-------------------------" << endl;

    // 测试有参构造:合法半径
    Circle c2(5.0);
    cout << "圆 2 半径:" << c2.getRadius() << endl;
    cout << "圆 2 面积:" << c2.getArea() << endl;
    cout << "圆 2 周长:" << c2.getPerimeter() << endl;
    cout << "-------------------------" << endl;

    // 测试非法半径设置
    Circle c3(-3.0);
    cout << "圆 3 半径:" << c3.getRadius() << endl;

    // 动态修改半径
    c3.setRadius(4.0);
    cout << "修改后圆 3 半径:" << c3.getRadius() << endl;
    cout << "修改后圆 3 面积:" << c3.getArea() << endl;
    return 0;
}
4.3 运行结果
空参构造函数被调用,默认半径 0
圆 1 半径:0
圆 1 面积:0
圆 1 周长:0
-------------------------
有参构造函数被调用,半径设置为 5
圆 2 半径:5
圆 2 面积:78.5398
圆 2 周长:31.4159
-------------------------
⚠️ 半径不能为负数,默认设置为 0
有参构造函数被调用,半径设置为 0
圆 3 半径:0
修改后圆 3 半径:4
修改后圆 3 面积:50.2655

五、封装的优势与开发规范

✅ 封装的核心优势

  1. 数据安全:通过 private 限制成员变量的直接访问,避免非法数据的输入。
  2. 代码复用:类的成员函数可以被多个对象复用,减少重复代码。
  3. 易于维护:类的内部实现细节被隐藏,修改内部逻辑时,只要对外接口不变,就不会影响外部代码。
  4. 接口清晰:对外只暴露必要的成员函数,让使用者无需关注内部实现,降低学习和使用成本。
5.1 C++ 类的开发规范
  • 成员变量尽量设置为 private,通过 public 的 get/set 函数访问和修改。
  • 构造函数要保证成员变量的初始化,避免出现未初始化的'脏数据'。
  • 涉及动态内存分配的类,必须手动编写析构函数释放资源,防止内存泄漏。
  • 类的命名采用大驼峰命名法,如 Person、Circle;成员函数和成员变量采用小驼峰命名法,如 setInfo、radius。

六、本章总结

✅ 类是属性和行为的抽象,对象是类的具体实例,二者是面向对象编程的基础。 ✅ 封装的核心是通过 public/protected/private 控制访问权限,隐藏实现细节,暴露统一接口。 ✅ 构造函数负责对象初始化,支持重载;析构函数负责资源清理,不能重载。 ✅ 合理使用封装特性,可以显著提升代码的安全性、复用性和可维护性。

目录

  1. C++ 类与对象:封装特性的实现与实战应用
  2. 一、类与对象的核心概念
  3. 1.1 类的组成
  4. 1.2 类的定义格式
  5. 1.3 对象的实例化与使用
  6. 二、封装的本质:访问权限控制
  7. 2.1 三种访问权限
  8. 2.2 访问权限的代码演示
  9. 三、构造函数与析构函数:对象的生命周期管理
  10. 3.1 构造函数
  11. 3.1.1 构造函数的特性
  12. 3.1.2 构造函数的分类与实现
  13. 3.2 析构函数
  14. 3.2.1 析构函数的特性
  15. 3.2.2 析构函数的实战价值
  16. 四、封装的实战案例:设计一个圆形类
  17. 4.1 需求分析
  18. 4.2 完整代码实现
  19. 4.3 运行结果
  20. 五、封装的优势与开发规范
  21. 5.1 C++ 类的开发规范
  22. 六、本章总结

更多推荐文章

查看全部
  • 设计模式:观察者模式详解与 Java 实现
  • 基于 RAGFlow 本地知识库与定制化大模型的私有化应用
  • LightOnOCR-2-1B:1B 参数轻量级 OCR 模型性能与速度优势
  • 使用 Ollama + AnythingLLM 搭建本地知识库
  • 图寻路算法实战:基于深度优先搜索 (DFS) 的 Java 实现
  • 跨平台 SSH 工具横评:5 款免费替代方案与选型指南
  • 前缀和算法实战:和为 K 的子数组与和可被 K 整除的子数组
  • 医疗 AI 场景下的模型融合与集成策略深度解析
  • Java 工程师转行 AI 大模型实战经验与学习路径分享
  • Python 安装与基础使用图文教程
  • 智能家居联动与节能优化:Java大数据实战拆解
  • AI 数据标注平台的选型与实践:效率提升背后的技术逻辑
  • ASP.NET Core Web API 控制器及方法注解详解
  • 如何训练一个“万亿大模型”?
  • Elasticsearch 全文检索实战:匹配、短语、范围查询及条件删除
  • MySQL 数据库核心操作:创建、修改与备份实战
  • 从传统 RAG 到 GraphRAG:大模型与知识图谱的融合
  • LeetCode 顺序表练习:移除元素、删除重复项与合并有序数组
  • AI Agent 架构概况:关于推理、规划和工具调用
  • Stable Diffusion XL(SDXL)技术解析:改进潜在扩散模型与高分辨率合成
  • 相关免费在线工具

    • Base64 字符串编码/解码

      将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

    • Base64 文件转换器

      将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

    • Markdown转HTML

      将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

    • HTML转Markdown

      将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

    • JSON 压缩

      通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

    • JSON美化和格式化

      将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online