C++ 类与对象详解:从结构体到面向对象编程

C++ 的面向对象编程(OOP)核心是 类(Class) 和 对象(Object)。类是用户自定义的数据类型,用于封装数据(属性)和操作数据的方法(行为);对象则是类的实例。本文将从 C 风格结构体 引入,逐步深入讲解 C++ 的类和对象,结合代码和详细说明。


1. 从 C 风格结构体到 C++ 类

1.1 C 风格结构体(Struct)

在 C 语言中,结构体(struct)用于将多个相关变量组合成一个复合类型:

#include <iostream>
#include <cstring> // 用于 strcpy// C 风格结构体:表示一个学生
struct StudentC {char name[50]; // 姓名(字符数组)int age;       // 年龄float score;   // 分数
};int main() {// 创建结构体变量并初始化StudentC s1;strcpy(s1.name, "Alice"); // C 风格字符串赋值s1.age = 20;s1.score = 95.5f;// 访问结构体成员std::cout << "Name: " << s1.name << ", Age: " << s1.age << ", Score: " << s1.score << std::endl;return 0;
}

说明

  • 数据完全公开,无法控制访问权限

  • 操作数据的行为(函数)与数据本身分离(结构体仅包含数据,操作需额外函数实现)

  • 缺乏数据保护机制,容易导致非法修改


1.2 C++ 结构体(增强版)

C++ 保留了 struct,但允许在结构体内定义函数(方法),并支持访问控制(public/private):

#include <iostream>
#include <string> // 使用 std::string 替代字符数组// C++ 结构体(带方法)
struct StudentCpp {std::string name; // 更安全的字符串int age;float score;// 结构体内定义方法:打印学生信息void printInfo() {std::cout << "Name: " << name << ", Age: " << age << ", Score: " << score << std::endl;}
};int main() {StudentCpp s2;s2.name = "Bob"; // 直接赋值s2.age = 21;s2.score = 88.0f;s2.printInfo(); // 调用结构体方法return 0;
}

说明

  • C++ 的 struct 默认成员是 public 的(与 class 默认 private 不同)。
  • 可以在结构体内定义方法,但通常更推荐用 class 表达面向对象概念。

1.3 从结构体到类的关键转变

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

类是结构体的升级版,通过 访问修饰符 控制成员的可见性,并强制将数据和方法绑定在一起:

// 使用 class 关键字
class Point {int x;  // 默认 privateint y;  // 默认 privatepublic:void print() {cout << "(" << x << ", " << y << ")" << endl;}void set(int newX, int newY) {if (newX >= 0 && newY >= 0) {  // 添加验证逻辑x = newX;y = newY;}}int getX() const { return x; }  // const 成员函数int getY() const { return y; }
};int main() {Point p1;p1.set(3, 4);// p1.x = 5;  // 错误:x 是 private 成员cout << p1.getX() << endl;  // 正确:通过公共接口访问return 0;
}

关键概念

  1. 封装:将数据和行为组合在一起,并控制访问权限

  2. 访问修饰符

    • public:公开的,任何代码都可以访问

    • private:私有的,只有类内部可以访问

    • protected:受保护的,类内部和派生类可以访问

  3. const 成员函数:承诺不修改对象状态的成员函数


2. 类的核心特性详解

2.1 构造函数与初始化

基本构造函数
  • 构造函数
    • 特殊方法,在创建对象时自动调用,用于初始化数据。
    • 语法:ClassName(参数列表) : 初始化列表 {}
class Student {string name;int age;double score;public:// 构造函数Student(const string& n, int a, double s) {name = n;age = a;score = s;}void display() const {cout << name << ", " << age << "岁, 成绩: " << score << endl;}
};int main() {Student stu("张三", 18, 90.5);  // 调用构造函数stu.display();return 0;
}

初始化列表(更高效的初始化方式)

class Student {string name;int age;double score;public:// 使用初始化列表的构造函数Student(const string& n, int a, double s) : name(n), age(a), score(s) {  // 初始化列表// 构造函数体}
};

    初始化列表的优势

    1. 对于类类型成员,直接调用拷贝构造函数而非先默认构造再赋值

    2. 对于 const 成员和引用成员,必须在初始化列表中初始化

    3. 执行效率更高

    默认构造函数
    class Student {// ... 其他成员同上public:Student() : name("无名"), age(0), score(0) {}  // 默认构造函数// 也可以使用默认参数实现Student(const string& n = "无名", int a = 0, double s = 0) : name(n), age(a), score(s) {}
    };int main() {Student stu1;          // 调用默认构造函数Student stu2("李四");  // 使用默认参数return 0;
    }

    2.2 静态成员(类共享数据)

    静态成员属于类本身,而非单个对象,所有对象共享同一份数据:

    #include <iostream>class Student {
    private:static int studentCount; // 静态成员:记录学生总数std::string name;public:Student(const std::string& n) : name(n) {studentCount++; // 创建对象时增加计数}static int getStudentCount() { // 静态方法:访问静态成员return studentCount;}
    };// 初始化静态成员(必须在类外定义)
    int Student::studentCount = 0;int main() {Student s6("Eve");Student s7("Frank");std::cout << "Total Students: " << Student::getStudentCount() << std::endl; // 输出 2return 0;
    }

    说明

    • 静态成员需在类外单独定义和初始化。
    • 静态方法只能访问静态成员,不能访问非静态成员。

    3. 对象:类的实例

    3.1 对象的创建与销毁

    对象是类的实例,通过构造函数初始化,析构函数清理资源:

    #include <iostream>class Resource {
    public:Resource() {std::cout << "Resource acquired!" << std::endl;}~Resource() { // 析构函数std::cout << "Resource released!" << std::endl;}
    };int main() {{Resource res; // 创建对象,调用构造函数// ... 使用 res ...} // 离开作用域,自动调用析构函数return 0;
    }

    输出

    Resource acquired!
    Resource released!

    析构函数特点

    1. 名称是 ~ 加类名,无参数无返回值

    2. 在对象生命周期结束时自动调用

    3. 用于释放资源、清理内存等收尾工作

    4. 如果不显式定义,编译器会生成默认析构函数

    3.2 对象作为函数参数

    对象可以通过值传递、引用传递或指针传递:

    #include <iostream>class Point {
    public:int x, y;Point(int xVal, int yVal) : x(xVal), y(yVal) {}
    };// 1. 值传递(拷贝对象)
    void printPointByValue(Point p) {std::cout << "Value: (" << p.x << ", " << p.y << ")" << std::endl;
    }// 2. 引用传递(避免拷贝)
    void printPointByRef(const Point& p) {std::cout << "Ref: (" << p.x << ", " << p.y << ")" << std::endl;
    }int main() {Point p1(10, 20);printPointByValue(p1); // 拷贝 p1printPointByRef(p1);   // 直接引用 p1return 0;
    }

    建议

    • 大型对象使用 const 引用传递(避免拷贝开销)。
    • 需要修改对象时使用非 const 引用或指针。

    4. 总结

    概念说明
    结构体(Struct)C 风格数据组合,C++ 增强后支持方法,默认成员公开。
    类(Class)封装数据和方法,通过访问修饰符控制可见性,支持构造函数/析构函数。
    对象类的实例,通过构造函数初始化,析构函数清理资源。
    静态成员属于类而非对象,所有对象共享同一份数据。
    封装性通过私有数据和公有方法保护数据安全性。

    本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
    如若转载,请注明出处:http://www.pswp.cn/pingmian/88201.shtml
    繁体地址,请注明出处:http://hk.pswp.cn/pingmian/88201.shtml
    英文地址,请注明出处:http://en.pswp.cn/pingmian/88201.shtml

    如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

    相关文章

    专题:2025数据资产AI价值化:安全、战略与应用报告|附400+份报告PDF、原数据表汇总下载

    原文链接&#xff1a;https://tecdat.cn/?p42885 在数字经济加速渗透的今天&#xff0c;数据作为核心生产要素的价值愈发凸显。上市公司作为经济高质量发展的微观主体&#xff0c;其数据价值化进程不仅关乎企业自身竞争力&#xff0c;更折射出中国产业数字化转型的深度与广度。…

    泛微虚拟视图-数据虚拟化集成

    文章目录一、核心概念对比二、功能特性对比1. 数据操作能力2. 业务逻辑支持3. 性能表现三、技术实现差异1. 虚拟表单实现原理2. 视图实现原理四、典型应用场景对比1. 虚拟表单适用场景2. 视图适用场景五、配置与管理对比六、性能优化差异虚拟表单优化策略视图优化策略七、企业级…

    Ubuntu 下 MySql 使用

    1.开发背景开发项目需要使用到数据库&#xff0c;相对于轻量级的 SQLite&#xff0c;MySql 相对复杂一下&#xff0c;但是可以远程访问&#xff0c;还是比较舒服的。2.开发需求Ubuntu 安装 MySql 服务端&#xff0c;Window 客户端访问 Ubuntu 数据库。3.开发环境Ubuntu20.04 W…

    QT开发技术 【qt应用限制只能启动一个】

    限制 Qt 程序只能启动一个实例 在开发 Qt 应用程序时,可能需要限制程序只能运行一个实例,以避免重复启动。以下是实现这一功能的几种常用方法。 使用 QSharedMemory 限制单实例 通过共享内存判断是否已有程序运行,如果存在则退出当前实例。 #include <QApplication&g…

    Android 禁用beam传输

    1、打开/packages/apps/Nfc/src/com/android/nfc/beam/BeamManager.java找到startBeamReceive、startBeamSend方法public boolean startBeamReceive(Context context,HandoverDataParser.BluetoothHandoverData handoverData) {synchronized (mLock) {if (mBeamInProgress) {re…

    基于 ETL 工具实现人大金仓数据库的数据迁移与整合实操指南

    在企业数字化转型的浪潮下&#xff0c;数据已经成为企业发展的核心资产。人大金仓数据库凭借其稳定可靠的性能&#xff0c;在国内众多企业中得到了广泛应用。但随着业务的不断拓展和系统的更新迭代&#xff0c;数据迁移与整合的需求也日益凸显。无论是将人大金仓数据库的数据迁…

    TCP 事务全面研究:从原理到优化与故障排除

    一、引言 TCP&#xff08;传输控制协议&#xff09;作为互联网的核心协议之一&#xff0c;已经在全球范围内运行了近 50 年。自 1974 年由文顿・瑟夫和罗伯特・卡恩设计以来&#xff0c;TCP 经历了多次修订和优化&#xff0c;以适应不断变化的网络环境和应用需求。TCP 事务是指…

    java实战-Milvus 2.5.x版本向量库-通过集合字段变更示例学习相关api demo

    文章目录前言java实战-Milvus 2.5.x版本向量库-通过集合字段变更示例学习相关api demo1. Milvus版本2. 示例逻辑分析3. 集合字段变更示例demo4. 测试前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _…

    HashMap的get与put流程源码深度解析

    目录 一、HashMap基础结构 二、put操作流程分析 put操作关键步骤总结 三、get操作流程分析 get操作关键步骤总结 四、延伸 1.hash()方法 2. 扩容 resize()方法的主要逻辑&#xff1a; Java 8中对扩容的优化&#xff1a; 3. 转向红黑树的条件 HashMap作为Java集合框架…

    初识Neo4j之图数据库(二)

    目录 一、图数据库如何工作 二、为什么使用图数据库 Neo4j 图数据库以节点、关系和属性的形式存储数据&#xff0c;而不是用表或文档进行数据存储。这意味着用户可以像在白板上画草图那样来组织数据。而且&#xff0c;由于图数据库不受限于预先定义的数据模型&#xff0c;因此…

    Python 中 ffmpeg-python 库的详细使用

    文章目录 一、ffmpeg-python库概述1.1 ffmpeg-python库介绍1.2 安装1.3 优势1.4 常用场景二、基本使用2.1 视频信息获取2.2 视频转码三、视频处理3.1 视频裁剪3.2 视频缩放3.3 视频旋转四、音频处理4.1 提取音频4.2 音频混合五、高级使用5.1 添加水印5.2 视频滤镜5.3 视频合成5…

    JAVA策略模式demo【设计模式系列】

    策略模式用在统一的入口&#xff0c;但需要根据某个类型判断后续执行逻辑&#xff0c;例如我最近遇到的场景&#xff1a;我需要对接一个设备&#xff0c;前端请求我这边&#xff0c;我再去和设备交互&#xff0c;但设备种类很多&#xff0c;各自有自己的接入规则&#xff01;传…

    mysql索引:索引应该选择哪种数据结构 B+树 MySQL中的页 页主体 页目录 索引分类

    索引是什么?为什么要使用索引? 以前学数据结构时学了ArrayList,我们可以往里面存放数据 但是有问题,也就是说当程序重启或是电脑关机之后,数据就没有了,为什么? 因为他的数据是保存在内存中的 数据库把数据保存在磁盘中,就可以完成对数据的持久化内存与外存的区别 内存&…

    SpringBoot静态资源与缓存配置全解析

    springboot中静态资源classpath就是resource文件夹下欢迎页规则项目启动默认去找静态资源下的index.html页面 默认访问该页面favicon原则在静态资源目录下寻找favicon.ico缓存实验在请求中使用Cache-Control 时&#xff0c;它可选的值有&#xff1a;在响应中使用Cache-Control …

    基于 Python Django 和 Spark 的电力能耗数据分析系统设计与实现7000字论文实现

    摘要随着能源问题日益突出&#xff0c;电力能耗数据分析对于提高能源利用效率、降低能源消耗具有重要意义。本文设计并实现了一个基于 Python Django 和 Spark 的电力能耗数据分析系统。系统采用前后端分离架构&#xff0c;前端使用 Django 框架实现用户界面&#xff0c;后端使…

    elementUI vue2 前端表格table数据导出(二)

    为啥前端导出不在赘述了&#xff0c;不然读者也难看到这篇文章。第一步&#xff1a;安装依赖npm install vue-json-excel第二步&#xff1a;引用依赖配置// 导出Excel文件组件 import JsonExcel from vue-json-excel; Vue.component(downloadExcel, JsonExcel)第三步&#xff1…

    RabbitMQ 4.1.1-Local random exchange体验

    Local Random Exchange 一种 RabbitMQ 4.0 引入的新型交换机&#xff0c;主要是为 request-reply&#xff08;RPC&#xff09;场景 设计的。 使用这种交换机时&#xff0c;消息只会被路由到本地节点上的队列&#xff0c;可以确保极低的消息发布延迟。如果有多个本地队列绑定到该…

    中山排气歧管批量自动化智能化3D尺寸测量及cav检测分析

    当前制造业快速发展&#xff0c;传统测量方法正面临严峻挑战。生产规模的持续扩张使得现有测量手段逐渐暴露出效率不足的问题&#xff0c;这种技术滞后性正在直接影响企业的整体生产效率。具体表现为测量速度跟不上生产节拍&#xff0c;精度要求难以达标&#xff0c;最终导致生…

    Debian 11 Bullseye 在线安装docker

    首先移除所有错误的 Docker 软件源&#xff1a;sudo rm -f /etc/apt/sources.list.d/docker*安装必要依赖sudo apt update sudo apt install -y ca-certificates curl gnupg添加 Docker 官方 GPG 密钥&#xff08;使用国内镜像&#xff09;&#xff1a;curl -fsSL https://mirr…

    Spring Boot 项目中多数据源配置使用场景

    在 Spring Boot 中配置多数据源是一个非常常见的需求&#xff0c;主要用于以下场景&#xff1a; 读写分离&#xff1a;一个主数据库&#xff08;Master&#xff09;负责写操作&#xff0c;一个或多个从数据库&#xff08;Slave&#xff09;负责读操作&#xff0c;以提高性能和可…