【029】C++静态成员和 this 指针详解

news2024/12/30 1:32:48

C++静态成员和 this 指针详解

  • 引言
  • 一、静态成员
    • 1.1、静态成员变量
    • 1.2、静态成员变量的使用示例
    • 1.3、静态成员函数
    • 1.4、单例模式设计
  • 二、C++面向对象模型
    • 2.1、成员变量和函数的存储
    • 2.2、this 指针
    • 2.3、this 指针的应用
    • 2.4、const修饰成员函数
  • 总结

引言


💡 作者简介:专注于C/C++高性能程序设计和开发,理论与代码实践结合,让世界没有难学的技术。包括C/C++、Linux、MySQL、Redis、TCP/IP、协程、网络编程等。
👉
🎖️ CSDN实力新星,社区专家博主
👉
🔔 专栏介绍:从零到c++精通的学习之路。内容包括C++基础编程、中级编程、高级编程;掌握各个知识点。
👉
🔔 专栏地址:C++从零开始到精通
👉
🔔 博客主页:https://blog.csdn.net/Long_xu


🔔 上一篇:【028】C++ 类和对象的 构造函数、析构函数、拷贝构造、初始化列表 详解(最全讲解)

一、静态成员

C++静态成员是指属于类而不是属于对象的成员。与普通成员变量和函数不同,静态成员变量和函数在内存中只有一份副本,无论类实例化了多少次,它们都是共享的。

在类的定义中,它的成员(包括成员变量、成员函数)可以使用关键字static声明为静态的,称为静态成员。不管这个类创建了多少个对象,静态成员只有一个拷贝,这个拷贝被所有属于这个类的对象共享。使用静态成员可以实现对类级别的操作。

使用方法:

  1. 声明静态成员变量或函数:在类声明中使用 static 关键字来声明静态成员变量或函数。

  2. 定义静态成员变量或函数:在类外部用作用域解析运算符(::)定义静态成员变量或函数。

1.1、静态成员变量

static修饰的静态成员属于类而不是对象,所有的对象共享一份静态成员数据。例如:

class Data{
private:
	int a;
	int b;
	int c;

	static int d;
};

实例化时它的内存布局:
在这里插入图片描述
静态成员变量中,需要清楚以下几点:

  • static修饰的成员,定义类的时候必须分配空间。
  • static修饰的静态成员数据必须类中定义类外初始化。

示例:

#include <iostream>
using namespace std;
class Data{
private:
	// 普通成员变量
	int a;
	int b;
	int c;
	// 类中定义静态成员变量
	static int d;
};
// 类外初始化静态成员变量,不用加static
int Data::d=100;

int main()
{
	// 静态成员变量可以通过类名称直接访问
	cout<<Data::d<<endl;
	// 静态成员变量可以通过对象访问(对象间共享)
	Data ob1;
	cout<<ob1.d<<endl;

	Data ob2;
	Ob2.d=200;
	Data ob3;
	Ob3.d=300;
	// 共享
	cout<<ob1.d<<endl;
	// 静态成员变量可以通过类名称直接访问
	cout<<Data::d<<endl;
	return 0;
}

输出:

100
100
300
300

1.2、静态成员变量的使用示例

使用静态成员数据统计对象的个数。

#include <iostream>
using namespace std;
class Data{
public:
	int mA;
	static int count;
public:
	Data()
	{
		mA=0;
		count++;
	}
	Data(int num)
	{
		mA=num;
		count++;
	}
	Data(const Data &ob)
	{
		mA=ob.mA;
		count++;
	}
	~Data()
	{
		count--;
	}
};

int Data::count=0;

int main()
{
	Data ob1;
	Data ob2(100);
	Data ob3=ob2;
	cout<<"对象个数:"<<Data::count<<endl;
	{
		Data ob4;
		Data ob5;
		cout<<"对象个数:"<<Data::count<<endl;
	}
	cout<<"对象个数:"<<Data::count<<endl;
	return 0;
}

输出:

对象个数:3
对象个数:5
对象个数:3

这里使用的是public权限的静态成员变量,如果是private或protected权限的,必须使用函数才能访问变量。

1.3、静态成员函数

静态成员函数属于类而不是对象,所有的对象共享。

class Data{
	static void func()
	{
	}
};

静态成员函数中,需要清楚以下几点:

  • 静态成员函数可以直接通过类名称访问。
  • 静态成员函数内只能操作静态成员变量。因为静态成员属于类,在类定义时就创建了,所有开辟了内存空间,可以访问,但是普通成员是类实例化为对象是才开辟空间,所有静态成员函数内只能操作静态成员变量。

示例:

#include <iostream>
using namespace std;

class Data{
private:
	int data;
	static int mA;
public:
	static int getA()
	{
		// data = 200;//error,不可以操作普通变量
		return mA;
	}
};

int Data::mA=100;
int main()
{
	// 静态成员函数可以直接通过类名称访问。
	cout<<Data::getA()<<endl;
}

1.4、单例模式设计

步骤:

  • 防止类在外界实例化对象,将构造函数私有化(包括无参构造、有参构造、拷贝构造)。
  • 定义一个静态的指针变量,保存唯一实例的地址。
  • 获取唯一的实例地址;提供静态成员函数。
  • 定义任务函数。

示例:

#include <iostream>
using namespace std;

class SingleTon {
	// 将构造函数私有化,防止类在外界实例化对象
private:
	SingleTon() {}
	SingleTon(const SingleTon &ob) {}
	~SingleTon() {}
private:
	// 定义一个静态指针变量,保存唯一实例的地址
	static SingleTon* const p;
public:
	// 提供一个静态成员函数,返回唯一实例的地址
	static SingleTon* getSingleTon(void)
	{
		return p;
	}
	// 定义的任务函数
	void printData(const char *str)
	{
		cout << "打印:" << str << endl;
	}
};

// 实例化对象
SingleTon* const SingleTon::p = new SingleTon;

int main()
{
	SingleTon *p1 = SingleTon::getSingleTon();
	p1->printData("hello sinleton");
	p1->printData("Lion");
	p1->printData("Tom");

	SingleTon *p2 = SingleTon::getSingleTon();
	p2->printData("hi sinleton");
	p2->printData("Long");
	p2->printData("Lucien");
	return 0;
}

二、C++面向对象模型

2.1、成员变量和函数的存储

C++实现了“封装”、“数据”和数据处理操作(函数)分开存储。C++中的非静态成员变量直接内含在类对象中,成员函数虽然内含在class声明中,却不出现在对象中,每一份非内联成员函数只会产生一份函数实例。
例如:

class Data{
public:
	char a;
	int b;
	static int c;
public:
	void func(){}
};

在这里插入图片描述
sizeof(Data)的大小只是a和b所占用空间大小(类的对象所占空间大小)。

示例:

#include <iostream>
using namespace std;

class Data01{
public:
	int mA;
};

class Data02{
public:
	int mA;
	static int data;
};

class Data03{
public:
	void func()
	{
		cout<<"Data02 func"<<endl;
	}
public:
	int mA;
	static int data;
};

class Data02{
public:
	void func()
	{
		cout<<"Data02 func"<<endl;
	}
	static void func02()
	{
		cout<<"Data02 static func02"<<endl;
	}
public:
	int mA;
	static int data;
};

int main()
{
	Data ob01;
	Data02 ob02;
	Data03 ob03;
	Data04 ob04;

	cout<<"sizeof(Data): "<<sizeof(ob01)<<endl;
	cout<<"sizeof(Data02): "<<sizeof(ob02)<<endl;
	cout<<"sizeof(Data03): "<<sizeof(ob03)<<endl;
	cout<<"sizeof(Data04): "<<sizeof(ob04)<<endl;

	return 0;
}

输出:

sizeof(Data): 4
sizeof(Data02): 4
sizeof(Data03): 4
sizeof(Data04): 4

可以看到:C++类对象中的变量和函数是分开存储的。

2.2、this 指针

C++的数据和操作也是分开存储的,并且每一个非内联成员函数只会诞生一份函数实例;也就是说多个类型相同的对象会公用一块代码;那么这块代码如何区分哪个对象调用自己呢?
在这里插入图片描述

对象1的数据
对象2的数据
对象3的数据
公用函数代码

C++通过提供特殊的对象指针:this指针,解决上述的问题;this 指针指向被调用的成员函数所属的对象。成员函数通过this指针即可 知道操作的是哪个对象的数据。this指针是一种隐式指针,隐含于每个类的非静态成员函数中。this指针无需定义,直接使用即可。
在这里插入图片描述
注意:静态成员函数内部没有this指针(因为this指针保存的是对象地址,而静态成员函数属于类,在对象出现之前就已经存在),静态成员函数不能操作非静态成员变量。

2.3、this 指针的应用

(1)函数形参和成员同名可以使用this指针解决。

#include <iostream>
using namespace std;

class Data{
public:
	int num;
public:
	Data(int num)
	{
		this->num=num;
		cout<<this<<endl;
	}
};

int main()
{
	Data ob(100);
	cout<<ob.num<<endl;
	cout<<&ob<<endl;
	return 0;
}

输出:

0x61fe8c
100
0x61fe8c

(2)this 指针来完成链式操作。

#include <iostream>
using namespace std;

class Data{
	Data& printData(const char *str)
	{
		cout<<str<<" ";
		return *this;//返回调用该成员函数的对象
	}
}
int main()
{
	Data().printData("hello,").printData("Lion").printData("Long");
}

输出:

hello, Lion Long

2.4、const修饰成员函数

用const修饰成员函数时,const修饰this指针指向的内存区域,成员函数体内不可以修改本类中的任何普通成员变量,除非成员变量类型前面用mutable修饰。

示例:

#include <iostream>
using namespace std;

class Data{
public:
	int a;
	int b;
	mutable int c;
public:
	Data(int a,int b,int c)
	{
		this->a=a;
		this->b=b;
		this->c=c;
	}
	void show(void) const
	{
		//a=100;// error
		c=500;// OK
		cout<<a<<" "<<b<<" "<<c<<endl;
	}
};

int main()
{
	Data obj(100,200,300);
	obj.show();
}

输出:

100 200 500

总结

  1. 静态成员是类的属性,属于整个类而不是类的对象。可以在任何对象中访问它们,但不需要创建实例即可使用它们。

  2. 使用静态成员变量时,必须在其前面加上“类名::”来指定其作用域。例如:ClassName::staticMemberVariable。

  3. 静态成员函数也属于整个类,可以直接通过类名调用,并且不能访问非静态成员变量和函数。

  4. 静态成员变量只有一个副本,在所有对象之间共享。当类的一个对象修改了这个变量时,其他对象也会受到影响。

  5. this 指针是指向当前对象的指针,在成员函数内部使用。它可以用来访问该对象的非静态成员变量和函数。

  6. 在静态成员函数中不能使用 this 指针,因为静态函数没有 this 指针。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

.NET6创建Windows服务

之前的文章已经写过了创建Windows服务。 C#创建Windows服务_c# 创建windows服务_故里2130的博客-CSDN博客 不过之前使用的是.NET Framework创建的Windows服务。现在已经2023年了&#xff0c;其中vs2022有新的方法去创建Windows服务&#xff0c;本次使用.NET6创建Windows服务。…

网络层:虚拟专用网VPN和网络地址转换NAT

1.网络层&#xff1a;虚拟专用网VPN和网络地址转换NAT 笔记来源&#xff1a; 湖科大教书匠&#xff1a;虚拟专用网VPN和网络地址转换NAT 声明&#xff1a;该学习笔记来自湖科大教书匠&#xff0c;笔记仅做学习参考 1.1 虚拟专用网VPN 专用网和公用网的特点 专用网络&#xff…

远程访问VPN配置与验证实验:构建安全的远程连接

远程访问VPN配置与验证实验&#xff1a;构建安全的远程连接 【实验目的】 理解远程访问 VPN的含义。掌握远程访问 VPN的含义。掌握VPN Client软件的使用。验证配置。 【实验拓扑】 实验拓扑如下图所示。 实验拓扑 设备参数表如下表所示。 设备参数表 设备 接口 IP地址 …

【软件设计】模块设计耦合的七种类型

一.什么是高内聚、低耦合&#xff1f; 在结构化分析与模块设计方法中&#xff0c;模块化是一个很重要的概念&#xff0c;它是将一个待开发的软件分解成为若干个小的模块&#xff0c;每个模块可以独立地开发、测试。使得复杂问题的“分而治之”&#xff0c;令程序的结构清晰、易…

ubuntu 20.04 linux6.3.8 qemu arm64 平台 制作ext4根文件系统

前言 可以参考 ubuntu 20.04 qemu linux6.0.1 制作ext4根文件系统 因为需要验证 aarch64 平台下的 glib 库&#xff0c;所以重新搭建了 Linux qemu arm64 的 测试环境 这一篇&#xff0c;开始制作 rootfs 根文件系统&#xff0c;让qemu arm64 平台上的 Linux 系统跑起来 开…

一个springboot项目的jenkins持续集成配置

目录 1.项目基本情况 2.jenkins的下载 1) 安装jdk 2&#xff09;下载、启动和配置jenkins 3. 启动Jenkins 4. 安装Jenkins插件 5. 重启jenkins 6.jenkins工具的配置 1&#xff09; jdk的路径配置 7.创建springboot项目的持续集成任务 1) 新建项目 2&#xff09;代…

倒闭了

前两天在群里听到有人发消息&#xff0c;说是「有陪」倒闭了&#xff0c;然后我去看了相应的消息&#xff0c;看到了下面的图。 一些老的读者可能知道我之前有一段创业经历&#xff0c;这段创业经历就是有陪&#xff0c;我从恒大的时候就开始给有陪做事&#xff0c;那时候我一个…

stm32 滑膜观测器+PLL 锁相环 FOC 无感无刷电机控制

上一期为大家介绍了滑膜观测器正反切的应用案例&#xff0c;收到不少小伙伴的反馈是否有PLL的案例&#xff0c;大概看了一下网上的资料&#xff0c;讲理论的很多&#xff0c;能转化成源码的几乎没有。前半年工作和家里的事情都比较多&#xff0c;一拖再拖&#xff0c;终于在6月…

Attention U-Net:Learning Where to Look for the Pancreas论文总结和代码实现

论文&#xff1a; https://arxiv.org/abs/1804.03999 中文版&#xff1a;https://blog.csdn.net/hhw999/article/details/110134398 源码&#xff1a; https://github.com/ozan-oktay/Attention-Gated-Networks 目录 一、论文背景和出发点 二、创新点 三、Attention U-Net的…

【5G MAC】5G中传输块(TBS)大小的计算方式

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

【学习日记2023.6.18】之 分布式缓存redis持久化_redis主从_reids哨兵_redis分片集群

文章目录 分布式缓存1. Redis持久化1.1 RDB持久化1.1.1 执行时机1.1.2 RDB原理1.1.3 小结 1.2 AOF持久化1.2.1 AOF原理1.2.2 AOF配置1.2.3 AOF文件重写 1.3 RDB与AOF对比 2 Redis主从2.1 搭建主从架构2.1.1 准备实例和配置2.1.2 启动2.1.3 开启主从关系2.1.4 测试 2.2 主从数据…

计算服务资源调度管理

文章目录 前言总体架构“ULT”和“KLT”抽象“内核”“容器”“虚容器” 内存抽象虚拟存储&#xff08;容器调用&#xff09; 多机器调度 前言 今天复习了一下操作系统&#xff0c;系统过了一下&#xff0c;感觉还有点时间&#xff0c;那么顺便来讨论一下&#xff0c;关于我的…

.maloxx勒索病毒数据怎么处理|数据解密恢复,malox/mallox

导语&#xff1a; 随着科技的快速发展&#xff0c;数据成为了企业和个人不可或缺的财富。然而&#xff0c;网络安全威胁也日益增多&#xff0c;其中Mallox勒索病毒家族的最新变种.maloxx勒索病毒的出现给我们带来了巨大的困扰。但不要担心&#xff01;91数据恢复研究院将为您揭…

一、Docker介绍

学习参考&#xff1a;尚硅谷Docker实战教程、Docker官网、其他优秀博客(参考过的在文章最后列出) 目录 前言一、Docker是什么&#xff1f;二、Docker能干撒&#xff1f;三、容器虚拟化技术 和 虚拟机有啥区别&#xff1f;1.虚拟机2.容器虚拟化技术3.对比 四、Docker组成4.1 镜像…

python自动化办公——定制化将电子签名批量签写到PDF文件

python自动化办公——定制化将电子签名批量签写到PDF文件 文章目录 python自动化办公——定制化将电子签名批量签写到PDF文件1、安装依赖2、需求分析3、代码 1、安装依赖 首先需要下载所需要的库 pip install pdf2image pip install img2pdf pip install opencv-python此外还…

【工作记录】基于可视化爬虫spiderflow实战天气数据爬取@20230618

前言 之前写过一篇关于可视化爬虫spiderflow的文章&#xff0c;介绍了基本语法并实战了某校园新闻数据的爬取。 还有一篇文章介绍了基于docker-compose快速部署spiderflow的过程&#xff0c;需要部署的话可参考该文章。 文章链接如下: 可视化爬虫框架spiderflow入门及实战【…

基于SpringBoot+Vue+微信小程序的电影平台

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 研究背景&#xff1a;…

【通过Data Studio连接openGauss---快速入门】

【通过Data Studio连接openGauss---快速入门】 &#x1f53b; 一、访问openGauss&#x1f530; 1.1 确认连接信息&#xff08;单节点&#xff09;&#x1f530; 1.2 使用gsql访问openGauss&#xff08;本地连接数据库&#xff09;&#x1f530; 1.3 使用gsql访问openGauss&…

多道程序设计(操作系统)

目录 1 单道程序设计的缺点 2 多道程序设计的提出 3 多道程序设计的问题 多道程序设计目标&#xff1a; 多道程序设计是操作系统所采用最基本、最重要的技术&#xff0c;其根本目标是提高整个计算机系统的效率。衡量系统效率有一个尺度&#xff0c;那就是吞吐量。 提高系统…

clDice-一种新的分割标准-能够促进管状结构分割的连接性

clDice-a Novel Topology-Preserving Loss Function for Tubular StructureSegmentation论文总结 论文&#xff1a;clDice-A Novel Topology-Preserving Loss Function for Tubular Structure 源码&#xff1a;GitHub - jocpae/clDice 目录 一、论文背景和出发点 二、创新点 …