C++共享和保护——(3)静态成员

归纳编程学习的感悟,
记录奋斗路上的点滴,
希望能帮到一样刻苦的你!
如有不足欢迎指正!
共同学习交流!
🌎欢迎各位→点赞 👍+ 收藏⭐ + 留言​📝
信念,你拿它没办法,但没有他你什么也做不成!

一起加油!

目录

一、前言:

二、静态数据成员: 

⭐例:具有静态数据成员的 Student 类。 

🔑说明:

三、静态成员函数: 

 ⭐例:类中静态数据成员和静态函数成员示例。

⚡思考:

四、静态成员的访问:

⭐例:类中静态成员函数通过对象访问非静态成员示例。

五、总结: 

六、共勉: 


一、前言:

        我们知道在一个函数内部定义的静态局部变量可以在每次函数调用间实现数据共享。这种共享仅限于这个函数调用之间,因为在函数外部是无法访问到函数内部的局部变量的。我们也可以将函数和函数要访问的数据封装成一个类,这样类中的数据成员可以被类中任何一个函数访问。一方面在类内部的函数之间实现了数据的共享,另一方面这种共享是受限制的,通过设定一定的访问权限后,可以把共享仅限定在类的范围之内。
        数据的共享包括很多、有时候类的对象与对象之间也需要共享数据静态成员是解决同一个类的不同对象之间数据和函数的共享问题。

 例如,学生类的声明如下:

class Student{

protected:
        int ID;
        char*name;
//....其他数据成员与成员函数略

};

        假设设计了一个学生管理系统,系统中随时定义新的学生对象,如果要统计系统中所有学生对象的数目,这个数据应该怎么存放呢?当然也可以在类外设计一个全局变量来存放总数,但这种做法不能实现数据的隐藏。如果在类的内部增加一个数据成员用于存放总数,那么类中的数据成员在类的每个对象中都有一个副本,不仅会造成数据冗余,而且每个对象都分别维护一个“总数”,很容易造成各对象数据的不一致。这个“总数”是为类的所有对象所共同拥有的,应该声明为类的静态数据成员。

二、静态数据成员: 

        在类中声明静态数据成员的格式如下:


class 类名

{
                                                        static <静态数据成员的声明>;

}


        类中声明的静态数据成员仅仅是引用性声明,必须在命名空间作用域的某个地方使用类名限定定义性声明,这时也可以进行初始化与类的一般数据成员不同,静态数据成员需要在类定义之外再进行定义,因为需要以这种方式专门为它们分配空间非静态数据成员的数据空间是与它们所属对象的空间同时分配的一般在类的实现部分完成静态数据成员的初始化。静态成员定义及初始化格式如下:
类名::静态数据成员标识符=初始值;
        静态成员是类的所有对象共享的成员,而不是某个对象本身的成员,它在对象中不占存储空间。在使用时,可以通过对象引用类的静态成员,也可以不定义对象,通过类直接引用静态成员。

⭐例:具有静态数据成员的 Student 类。 

#include<iostream>
#include<cstring>
using namespace std;
class Student{//Student类定义 
	protected:
		int ID;
		char *name;//name为需要动态申请的空间 
		char sex;
		int age;
		static int count;//静态数据成员的声明,用来记录学生的个数 
	public://外部接口 
		Student(int pID,char *pname,char psex,int page);//构造函数 
		~Student();//析构函数 
		void print();
		void Show_count(){//输出静态数据成员 
			cout<<"Object count:"<<count<<endl;
		}
}; 

Student::Student(int pID,char *pname,char psex,int page){
	ID=pID;
	name=new char[strlen(pname)+1];//为name动态申请空间 
	strcpy(name,pname);//将值放入name所指向的内存空间 
	sex=psex;
	age=page;
	count++;//在构造函数中对count++,所有对象成员共同维护一个count 
}

Student::~Student(){
	count--;//在析构函数中对count进行减减操作 
	delete []name;
}

void Student::print(){
	cout<<"ID:"<<ID<<"\nName:"<<name<<"\nSex:"<<sex<<"\nAge:"<<age<<endl; 
}

int Student::count=0;

int main(){ 
	Student std1(20230011,"李华",'F',18);//定义对象std1,其构造函数会使count++ 
	std1.print();
	std1.Show_count();//输出对象的个数 
	Student std2(20230012,"张三",'M',19);//定义对象std2,其构造函数会使count++ 
	std2.print();
	std2.Show_count();//输出对象的个数 
	return 0;	
}

🔑说明:

        类Student 中的静态数据成员 count,用来统计 Student 类的对象个数,每定义一个新对象,count 的值就相应加 1,静态成员 count 的定义和初始化必须在类外进行,初始化时引用的方式要注意两点: (1).必须用类名来引用;(2)虽然静态数据成员在类中声明的是私有的,在这里却可以直接初始化。除了定义初始化的时候,在其他地方,例如,在主函数中就不允许直接访问了。count 的值是在类的构造函数中计算的,std1 对象生成时,调用构造函数;std2 对象生成时,调用构造函数。两次调用构造函数访问的均是同一个静态成员 count。通过对象 std1 和对象 std2 分别调用 Show_count 函数,输出的也是同一个 count在不同时刻的数值。这样,就实现了 std1 和 std2 两个对象之间的数据共享。 

三、静态成员函数: 

        函数 Show_count 是专门用来输出静态成员 count 的。count 是类中的私有成员如果需要查看 count 的值,需要调用类的公有接口函数 showCount。在所有对象声明之前,系中对象的个数为 0,可否通过 Show_Count 将这个值输出呢?由于此时系统中还没有对象,无法通过对象来调用 Show_Count,由于 count 是整个类共有的,不属于某一个对象。因此,我们希望对count 的访问也可以不通过对象,而直接通过类名来访问。在主函数中增加了类直接调Show_count语句,如下所示:

int main(){ 
	Student::Show_count(); 
	Student std1(20230011,"李华",'F',18);//定义对象std1,其构造函数会使count++ 
	std1.print();
	std1.Show_count();//输出对象的个数 
	Student std2(20230012,"张三",'M',19);//定义对象std2,其构造函数会使count++ 
	std2.print();
	std2.Show_count();//输出对象的个数 
	return 0;	
}

        编译后“Student::showCount0:”语句出错,提示对普通函数 Show_count 的调用必须通过对象名。
        可以将函数 Show_count 也声明为静态的,同静态数据成员一样,静态成员函数也属于整个类,由同一类的所有对象共同拥有,为这些对象共享。静态成员函数可以直接由类调用。不需要通过类定义对象后再调用。

 ⭐例:类中静态数据成员和静态函数成员示例。

#include<iostream>
#include<cstring>
using namespace std;
class Student{//Student类定义 
	protected:
		int ID;
		char *name;//name为需要动态申请的空间 
		char sex;
		int age;
		static int count;//静态数据成员的声明,用来记录学生的个数 
	public://外部接口 
		Student(int pID,char *pname,char psex,int page);//构造函数 
		~Student();//析构函数 
		void print();
		static void Show_count(){//静态成员函数输出静态数据成员 
			cout<<"Object count:"<<count<<endl;
		}
}; 

Student::Student(int pID,char *pname,char psex,int page){
	ID=pID;
	name=new char[strlen(pname)+1];//为name动态申请空间 
	strcpy(name,pname);//将值放入name所指向的内存空间 
	sex=psex;
	age=page;
	count++;//在构造函数中对count++,所有对象成员共同维护一个count 
}

Student::~Student(){
	count--;//在析构函数中对count进行减减操作 
	delete []name;
}

void Student::print(){
	cout<<"ID:"<<ID<<"\nName:"<<name<<"\nSex:"<<sex<<"\nAge:"<<age<<endl; 
}

int Student::count=0;

int main(){ 
	Student::Show_count(); 
	Student std1(20230011,"李华",'F',18);//定义对象std1,其构造函数会使count++ 
	std1.print();
	std1.Show_count();//输出对象的个数 
	Student std2(20230012,"张三",'M',19);//定义对象std2,其构造函数会使count++ 
	std2.print();
	std2.Show_count();//输出对象的个数 
	return 0;	
}

⚡思考:

        可以在静态成员函数 Show_count 中访问非静态成员x、y吗? 

四、静态成员的访问:

         类中非静态的成员只能通过对象名来调用,而静态成员包括静态数据成员和静态成员函数,可以在类外通过类名和对象名来调用。但要习惯使用类名调用静态成员,因为即使是通过对象名调用静态成员,实质上也是通过对象的类型信息确定调用类的静态成员,与具体对象没有任何关系。
        在一般情况下,类中静态成员函数主要用于访问同一个类中的静态数据成员,而不能访问类
中的非静态数据成员。因为静态成员函数实质上并不是由某个具体对象来调用的,所以不能隐含

地通过调用对象访问类中的非静态成员。
        我们不能在静态成员函数 Show_count 中访问本类的非静态成员x和y。如果一定要在静态成员函数中访问非静态成员,可以显式地通过对象来调用。

⭐例:类中静态成员函数通过对象访问非静态成员示例。

#include<iostream>
#include<cstring>
using namespace std;
class Student{//Student类定义 
	protected:
		int ID;
		char *name;//name为需要动态申请的空间 
		char sex;
		int age;
		static int count;//静态数据成员的声明,用来记录学生的个数 
	public://外部接口 
		Student(int pID,char *pname,char psex,int page);//构造函数 
		~Student();//析构函数 
		static void Show_count(Student p){
		//静态成员函数访问静态数据成员和非静态数据成员 
			cout<<"Object count:"<<count<<endl;//静态成员函数直接访问静态信息 
			cout<<"ID:"<<p.ID<<"\nName:"<<p.name<<"\nSex:"<<p.sex<<"\nAge:"<<p.age<<endl; 
			//静态成员函数需要通过对象访问非静态信息 
		}
}; 

Student::Student(int pID,char *pname,char psex,int page){
	ID=pID;
	name=new char[strlen(pname)+1];//为name动态申请空间 
	strcpy(name,pname);//将值放入name所指向的内存空间 
	sex=psex;
	age=page;
	count++;//在构造函数中对count++,所有对象成员共同维护一个count 
}

Student::~Student(){
	delete []name;
}

int Student::count=0;

int main(){ 
	Student std1(20230011,"李华",'F',18);//定义对象std1,其构造函数会使count++ 
	std1.Show_count(std1);//通过静态成员函数访问非静态信息需要通过对象 
	Student std2(20230012,"张三",'M',19);//定义对象std2,其构造函数会使count++ 
	std2.Show_count(std2);//通过静态成员函数访问非静态信息需要通过对象 
	return 0;	
}

五、总结: 

  • 静态成员是解决同一个类的不同对象之间数据和函数的共享问题。
  • 一般在类的实现部分完成静态数据成员的初始化。
  • 静态成员是类的所有对象共享的成员,而不是某个对象本身的成员,它在对象中不占存储空间。
  • 静态成员函数可以直接由类调用。不需要通过类定义对象后再调用。
  • 静态成员包括静态数据成员和静态成员函数。
  • 即使是通过对象名调用静态成员,实质上也是通过对象的类型信息确定调用类的静态成员,与具体对象没有任何关系。

六、共勉: 

         以上就是我对C++共享和保护——(3)静态成员的理解,希望本篇文章对你有所帮助,也希望可以支持支持博主,后续博主也会定期更新学习记录,记录学习过程中的点点滴滴。如果有不懂和发现问题的小伙伴,请在评论区说出来哦,同时我还会继续更新对C++共享和保护的理解,请持续关注我哦!!! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/245584.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

zabbix简单介绍2

学习目标: 能够实现一个web页面的监测能够实现自动发现远程linux主机能够通过动作在发现主机后自动添加主机并链接模板能够创建一个模版并添加相应的元素(监控项,图形,触发器等)能够将主机或模板的配置实现导出和导入能够实现至少一种报警方式(邮件,微信等)能够通过zabbix_pro…

【数据结构入门精讲 | 第一篇】打开数据结构之门

数据结构与算法是计算机科学中的核心概念&#xff0c;也与现实生活如算法岗息息相关。鉴于全网数据结构文章良莠不齐且集成度不高&#xff0c;故开设本专栏&#xff0c;为初学者提供指引。 目录 基本概念数据结构为何面世算法基本数据类型抽象数据类型使用抽象数据类型的好处 数…

短视频自媒体创作者都在用的去水印小程序

如今可以发短视频的平台越来越多&#xff0c;我们经常看到喜欢的视频想下载下来&#xff0c;或者当做手机壁纸&#xff0c;由于直接下载下来视频都会带有平台的水印&#xff0c;让我们用着看起来非常不美观&#xff0c;所以我们就要想办法去掉这个水印&#xff0c;下载没有水印…

arthas一次操作实现递归分析下游方法的耗时

背景 使用arthas的trace分析方法的耗时时&#xff0c;我们一般只能分析下一层的方法的耗时&#xff0c;然后一层一层的递归进去找到耗时最长的那个方法&#xff0c;有没有一种方式可以一次trace分析就可以把所有要关注的下层所有的耗时都打印出来&#xff1f; 解决方式 使用…

物奇平台TWS蓝牙耳机频响曲线问题

物奇平台TWS蓝牙耳机频响曲线问题 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)&#xff1f;可加我微信hezkz17, 本群提供音频技术答疑服务&#xff0c;群赠送蓝牙音频&#xff0c;DSP音频项目核心开发资料, 1 高频有抖动 2 物奇原厂频响曲线

第三方电脑小爱同学用快捷键唤醒

第三方电脑安装小爱同学-CSDN博客 请结合之前安装小爱同学的教程安装过程请提前取消windows更新 安装完成之后登录账号即可使用 Ahk2.0 下载地址&#xff1a;https://www.autohotkey.com/download/ahk-v2.zip 打开链接即可自动下载&#xff0c;下载后解压出来点击install.cmd安…

有效的括号,成对字符合法性检测

说在前面 &#x1f388;不知道大家对于算法的学习是一个怎样的心态呢&#xff1f;为了面试还是因为兴趣&#xff1f;不管是出于什么原因&#xff0c;算法学习需要持续保持。 一、题目描述 给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0…

HarmonyOS学习 第2节 DevEco Studio工程介绍

工程配置页 界面布局介绍 代码编辑区、通知栏、工程目录区、预览区 工程目录区 便于理解&#xff0c;可以切换为 Ohos AppScope主要用于存放整个应用公共的信息与资源 entry默认的初始模块ets文件用于存放编写的代码文件configuration存放相应模块的配置文件resources对应模块…

交叉编译---理解+环境配置

文章目录 一、基础理解二、配置环境方式一&#xff1a;临时输入&#xff08;麻烦&#xff09;方式二&#xff1a;编写脚本文件&#xff08;推荐&#xff09;方式三&#xff1a;永久指定&#xff08;不太推荐&#xff09; 三、知识补充&#xff1a;source与 ./1、source2、命令.…

Signal EM的流程与分析

RedhawkTM 提供了一种在设计中分析Power EM和SignalEM的单一平台方法。Power EM通常作为Static IR和Dynamic IR分析的组成部分进行。Signal EM分析是单独进行分析的,检查设计中所有信号线和过孔的平均(单向或双向)、RMS和峰值电流密度【1】。 1 SignalEM 流程介绍 如图7…

Jmeter,提取响应体中的数据:正则表达式、Json提取器

一、正则表达式 1、线程组--创建线程组&#xff1b; 2、线程组--添加--取样器--HTTP请求&#xff1b; 3、Http请求--添加--后置处理器--正则表达式提取器&#xff1b; 4、线程组--添加--监听器--查看结果树&#xff1b; 5、线程组--添加--取样器--调试取样器。 响应体数据…

C++ 11 初识

一.C 11的简介 在2003年C标准委员会曾经提交了一份技术勘误表(简称TC1)&#xff0c;使得C03这个名字已经取代了C98称为C11之前的最新C标准名称。不过由于C03(TC1)主要是对C98标准中的漏洞进行修复&#xff0c;语言的核心部分则没有改动&#xff0c;因此人们习惯性的把两个标准合…

什么是 API 代理?

API 代理就像您的计算机和互联网上的特殊服务之间的有用中间人。这有点像将翻译、保安和信使合而为一。 什么是 API 代理&#xff1f; API 代理就像您和在线服务之间的有用中间人。当您的计算机需要从特殊在线服务&#xff08;API&#xff09;获取某些内容时&#xff0c;API 代…

一步步教你制作婚礼策划展示小程序

随着互联网的发展&#xff0c;越来越多的服务和产品开始通过线上进行展示和销售。婚庆行业也不例外。通过制作婚庆小程序&#xff0c;商家可以更好地展示婚庆服务、婚礼策划、婚宴预定等相关信息&#xff0c;吸引更多的潜在客户。本文将介绍如何从零开始制作婚庆小程序&#xf…

芸鹰蓬飞:抖店的运营技巧是什么?

抖店&#xff0c;作为抖音平台上的电商业务&#xff0c;为商家提供了一个全新的销售渠道。然而&#xff0c;要成功运营抖店&#xff0c;商家需要掌握一定的方法和技巧。下面&#xff0c;我们就来详细介绍一下抖店的运行方式。 商品选择&#xff1a;首先&#xff0c;商家需要选择…

DS二分查找_搜索二维矩阵(纯二分查找写法)

本题我写了两个方法&#xff0c;一个是的时间复杂度,就是本文章一个mn时间复杂度&#xff0c;这个比较简单&#xff0c;如果不会二分法可以看这篇文章 Description 使用二分查找法来判断m*n矩阵matrix中是否存在目标值target。 该矩阵有以下特性&#xff1a; 1. 每行中的整数…

一键提取微信聊天记录,生成HTML、Word文档永久保存,还能生成微信年度聊天报告

不知道生活中你有没有遇到过这种情况&#xff0c;聊天记录不完整&#xff0c;有的在手机上&#xff0c;有的在电脑上&#xff0c;搜索起来很烦。那有没有一种办法可以把微信聊天记录统一呢&#xff1f;当然是有的。下面&#xff0c;就让我们一起来看一下怎么操作。 先看效果 操…

卧槽!jmeter 竟然这么牛逼,压测爽歪歪~

# Http请求模拟 1、新建线程组 操作&#xff1a;鼠标右键测试计划 -> 添加 -> Threads(Users) -> 线程组 -> 修改测试计划名称 新建线程组 2、添加取样器HTTP请求 操作&#xff1a;鼠标右键线程组 -> 添加 -> Sampler -> HTTP请求 -> 填写请求参数 添…

飞轮储能一次调频并网三机九节点系统,虚拟惯性和下垂控制,也可加入虚拟同步机VSG控制,飞轮储能容量可调,系统频率50Hz,离散模型

5MW飞轮储能一次调频并网三机九节点系统&#xff0c;虚拟惯性和下垂控制&#xff0c;也可加入虚拟同步机VSG控制&#xff0c;飞轮储能容量可调&#xff0c;系统频率50Hz&#xff0c;离散模型&#xff0c;仿真运行速度快。 飞轮储能变流器采用双PWM环设计&#xff0c;并网电压电…

基于javaweb实现的实践教学基地管理系统

一、系统架构 前端&#xff1a;html | js | css | bootstrap 后端&#xff1a;spring | springmvc | mybatis-plus 环境&#xff1a;jdk1.8 | mysql8 | tomcat | maven 二、代码及数据库 三、功能介绍 01. web-首页1 02. web-首页2 03. web-首页3 04. web-首页4 05. 管…