C++类成员的访问权限以及类的封装
C++通过 public、protected、private 三个关键字来控制成员变量和成员函数的访问权限,它们分别表示公有的、受保护的、私有的,被称为成员访问限定符。所谓访问权限,就是你能不能使用该类中的成员。
Java、C# 程序员注意,C++ 中的 public、private、protected 只能修饰类的成员,不能修饰类,C++中的类没有共有私有之分。
在类的内部(定义类的代码内部),无论成员被声明为 public、protected 还是 private,都是可以互相访问的,没有访问权限的限制。

在类的外部(定义类的代码之外),只能通过对象访问成员,并且通过对象只能访问 public 属性的成员,不能访问 private、protected 属性的成员。

本节重点讲解 public 和 private,protected 将在继承中讲解。
下面通过一个 Student 类来演示成员的访问权限:
#include <iostream>using namespace std;//类的声明class Student{private: //私有的char *m_name;int m_age;float m_score;public: //共有的void setname(char *name);void setage(int age);void setscore(float score);void show();};//成员函数的定义void Student::setname(char *name){m_name = name;}void Student::setage(int age){m_age = age;}void Student::setscore(float score){m_score = score;}void Student::show(){cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<endl;}int main(){//在栈上创建对象Student stu;stu.setname("小明");stu.setage(15);stu.setscore(92.5f);stu.show();//在堆上创建对象Student *pstu = new Student;pstu -> setname("李华");pstu -> setage(16);pstu -> setscore(96);pstu -> show();return 0;}
运行结果:小明的年龄是15,成绩是92.5李华的年龄是16,成绩是96
类的声明和成员函数的定义都是类定义的一部分,在实际开发中,我们通常将类的声明放在头文件中,而将成员函数的定义放在源文件中。

类中的成员变量 m_name、m_age 和m_ score 被设置成 private 属性,在类的外部不能通过对象访问。也就是说,私有成员变量和成员函数只能在类内部使用,在类外都是无效的。
成员函数 setname()、setage() 和 setscore() 被设置为 public 属性,是公有的,可以通过对象访问。private 后面的成员都是私有的,直到有 public 出现才会变成共有的;public 之后再无其他限定符,所以 public 后面的成员都是共有的。
成员变量大都以m_开头,这是约定成俗的写法,不是语法规定的内容。以m_开头既可以一眼看出这是成员变量,又可以和成员函数中的形参名字区分开。
以 setname() 为例,如果将成员变量m_name的名字修改为name,那么 setname() 的形参就不能再叫name了,得换成诸如name1、_name这样没有明显含义的名字,否则name=name;这样的语句就是给形参name赋值,而不是给成员变量name赋值。

因为三个成员变量都是私有的,不能通过对象直接访问,所以必须借助三个 public 属性的成员函数来修改它们的值。下面的代码是错误的:
Student stu;//m_name、m_age、m_score 是私有成员变量,不能在类外部通过对象访问stu.m_name = "小明";stu.m_age = 15;stu.m_score = 92.5f;stu.show();
简单地谈类的封装
private 关键字的作用在于更好地隐藏类的内部实现,该向外暴露的接口(能通过对象访问的成员)都声明为 public,不希望外部知道、或者只在类内部使用的、或者对外部没有影响的成员,都建议声明为 private。
根据C++软件设计规范,实际项目开发中的成员变量以及只在类内部使用的成员函数(只被成员函数调用的成员函数)都建议声明为 private,而只将允许通过对象调用的成员函数声明为 public。
另外还有一个关键字 protected,声明为 protected 的成员在类外也不能通过对象访问,但是在它的派生类内部可以访问,这点我们将在后续章节中介绍,现在你只需要知道 protected 属性的成员在类外无法访问即可。
有读者可能会提出疑问,将成员变量都声明为 private,如何给它们赋值呢,又如何读取它们的值呢?
我们可以额外添加两个 public 属性的成员函数,一个用来设置成员变量的值,一个用来获取成员变量的值。上面的代码中,setname()、setage()、setscore() 函数就用来设置成员变量的值;如果希望获取成员变量的值,可以再添加三个函数 getname()、getage()、getscore()。
给成员变量赋值的函数通常称为 set 函数,它们的名字通常以set开头,后跟成员变量的名字;读取成员变量的值的函数通常称为 get 函数,它们的名字通常以get开头,后跟成员变量的名字。
除了 set 函数和 get 函数,在创建对象时还可以调用构造函数来初始化各个成员变量,我们将在《C++构造函数》一节中展开讨论。
不过构造函数只能给成员变量赋值一次,以后再修改还得借助 set 函数。这种将成员变量声明为 private、将部分成员函数声明为 public 的做法体现了类的封装性。
所谓封装,是指尽量隐藏类的内部实现,只向用户提供有用的成员函数。
有读者可能会说,额外添加 set 函数和 get 函数多麻烦,直接将成员变量设置为 public 多省事!确实,这样做 99.9% 的情况下都不是一种错误,我也不认为这样做有什么不妥;但是,将成员变量设置为 private 是一种软件设计规范,尤其是在大中型项目中,还是请大家尽量遵守这一原则。
为了减少代码量,方便说明问题,本教程中的类可能会将成员变量设置为 public,请读者不要认为这是一种错误。
对private和public的更多说明
声明为 private 的成员和声明为 public 的成员的次序任意,既可以先出现 private 部分,也可以先出现 public 部分。如果既不写 private 也不写 public,就默认为 private。
在一个类体中,private 和 public 可以分别出现多次。每个部分的有效范围到出现另一个访问限定符或类体结束时(最后一个右花括号)为止。但是为了使程序清晰,应该养成这样的习惯,使每一种成员访问限定符在类定义体中只出现一次。
下面的类声明也是完全正确的:
class Student{private:char *m_name;private:int m_age;float m_score;public:void setname(char *name);void setage(int age);public:void setscore(float score);void show();};
相关文章:
C++类成员的访问权限以及类的封装
C通过 public、protected、private 三个关键字来控制成员变量和成员函数的访问权限,它们分别表示公有的、受保护的、私有的,被称为成员访问限定符。所谓访问权限,就是你能不能使用该类中的成员。 Java、C# 程序员注意,C 中的 publ…...
Linux 多线程解决客户端与服务器端通信
一、一个服务器端只能和一个客户端进行通信(单线程模式) 客户端代码ser.c如下: #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<sys/socket.h> #include<netinet…...
FMX的TListBox单选列表框
TListBox功能比较全,对于选择项,有“两种”模式,一种就是ListItem选中(界面上就是焦点和颜色变化),可以无,单选和多选。另一种是通过CheckBox来选择ListItem的选中。默认下,ShowChec…...
prompt工程(持续更新ing...)
诸神缄默不语-个人CSDN博文目录 我准备想办法把这些东西整合到我的ScholarEase项目里。到时候按照分类、按照prompt生成方法列一堆选项,用户自己生成prompt后可以选择在ScholarEase里面聊天,也可以复制到别的地方(比如ChatGPT网页版之类的&a…...
win11 docker-desktop安装记录
win11安装Docker踩坑实录 马上开始正式工作了,需要用到docker,以前在win10上安装过,新电脑是win11,心想肯定会遇到坑,就浅浅记录一下 首先看一下安装要求 需要wsl2 那么就先进行 wsl的更新 wsl --update注意这里网络…...
opencv特征提取、梯度计算
...
AI绘画工具MJ新功能有点东西,小白也能轻松一键换装
先看最终做出来的效果 直接来干货吧。Midjourney,下面简称MJ 1.局部重绘功能来袭 就在前两天,MJ悄咪咪上线了这个被众人期待的新功能:局部重绘。 对于那些追求创新和个性化的设计师来说,局部绘制不仅是一个实用的功能ÿ…...
java springboot sql防注入的6种方式
在Spring Boot中,可以通过使用参数绑定、预处理语句和使用ORM框架等方式来防止SQL注入。以下是几种常见的方式: 1. 参数绑定:通过使用参数绑定,将用户输入的数据作为参数传递给SQL语句,而不是将其直接拼接到SQL语句中…...
深度学习实战49-基于卷积神经网络和注意力机制的汽车品牌与型号分类识别的应用
大家好,我是微学AI,今天给大家介绍一下深度学习实战49-基于卷积神经网络和注意力机制的汽车品牌与型号分类识别的应用,该项目就像是一只智慧而敏锐的眼睛,专注地凝视着汽车世界。这个项目使用PyTorch作为强有力的工具,提供了一个深度学习的舞台,让我们能够设计和训练一个…...
Open3D(C++) 可视化(3)——批量动态可视化点云
目录 一、概述二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、概述 拿到一个新的点云数据集,想要快速查看数据集内点云的形状特征。然而,对于动辄几千个点云的数据集而言,逐个将点云拖入…...
opencv 文档识别+UI界面识别系统
目录 一、实现和完整UI视频效果展示 主界面: 识别结果界面: 查看处理图片过程: 查看历史记录界面: 二、原理介绍: 将图像变换大小->灰度化->高斯滤波->边缘检测 轮廓提取 筛选第三步中的轮廓…...
下|税收大数据应用研究
上文呢,对于税收大数据我们已经对它有了一定程度的认知。下篇呢,就研究一下应用方面有哪些优势和存在的不足之处。 一、税收大数据应用的优势 1.提升征管效率和预测准确率 税收部门通过收集、分析海量数据。并建立数据分析模型来提升效率和准确率。税…...
数据库连接池druid 的jar包官网下载-最新版下载
进入官网Central Repository: com/alibaba/druid 往下滑 找到最新版点击进入 找到该jar包 点击即可下载...
2023河南萌新联赛第(六)场:河南理工大学 C - 旅游
2023河南萌新联赛第(六)场:河南理工大学 C - 旅游 时间限制:C/C 1秒,其他语言2秒 空间限制:C/C 262144K,其他语言524288K Special Judge, 64bit IO Format: %lld 题目描述 小C喜欢旅游…...
Java | IDEA中Netty运行多个client的方法
想要运行多个client但出现这种提示: 解决方法 1、打开IDEA,右上角找到下图,并点击 2、勾选...
【蓝桥杯】 [蓝桥杯 2015 省 A] 饮料换购
原题链接:https://www.luogu.com.cn/problem/P8627 1. 题目描述 2. 思路分析 小伙伴们如果没有思路可以看看这篇文章~(这里很详细讲解了三种方法!) https://blog.csdn.net/m0_62531913/article/details/132385341?spm1001.2014…...
操作系统-笔记-第三章-内存管理
🌸章节汇总 一、第一章——操作系统的概念 二、第二章——【进程】 二、第二章——【线程】编辑 二、第二章——【进程调度】 二、第二章——【进程同步与互斥】 二、第二章——【锁】 三、第三章——内存管理 四、第四章——文件管理 五、第五章——输入输出管理…...
详解单体架构和微服务(概念,优缺点和区别)
单体架构和微服务 单体架构和微服务架构区别?为什么要用微服务架构? 单体架构的整个系统是一个War包,即war包走天下。微服务架构的项目是很多个war包(一个子系统一个)。 单体架构的优点: 架构简单开发测试部署简单…...
储能运行约束的Matlab建模方法
最近一段时间有很多人问我最优潮流计算中储能系统的建模方法。部分朋友的问题我回复了,有些没有回消息的,我就不再一一回复了,在这里我写一篇博客统一介绍一下。 1.储能系统介绍 首先,让【GPT】简单介绍一下储能系统:…...
微信小程序 车牌号输入组件
概述 一个小组件,用于方便用户输入车牌号码 详细 概述 有时候我们开发过程中会遇到需要用户输入车牌号的情况,让客户通过自带键盘输入,体验不好且容易出错,例如车牌号是不能输入O和I的,因此需要有一个自定义的键盘…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
【Veristand】Veristand环境安装教程-Linux RT / Windows
首先声明,此教程是针对Simulink编译模型并导入Veristand中编写的,同时需要注意的是老用户编译可能用的是Veristand Model Framework,那个是历史版本,且NI不会再维护,新版本编译支持为VeriStand Model Generation Suppo…...
