当前位置: 首页 > news >正文

C++ Primer 类的静态成员

欢迎阅读我的 【C++Primer】专栏

专栏简介:本专栏主要面向C++初学者,解释C++的一些基本概念和基础语言特性,涉及C++标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级程序设计技术。希望对读者有帮助!

在这里插入图片描述
在这里插入图片描述

目录

  • 7.6 类的静态成员
    • 声明静态成员
    • 使用类的静态成员
    • 静态成员的类内初始化
    • 静态成员能用于某些场景,而普通成员不能

7.6 类的静态成员

有的时候类需要它的一些成员与类本身直接相关,而不是与类的各个对象保持关联。例如,一个银行账户类可能需要一个数据成员来表示当前的基准利率。在此例中,我们希望利率与类关联,而非与类的每个对象关联。从实现效率的角度来看,没必要每个对象都存储利率信息。而且更加重要的是,一旦利率浮动,我们希望所有的对象都能使用新值。

声明静态成员

我们通过在成员的声明之前加上关键字static使得其与类关联在一起。和其他成员一样,静态成员可以是public的或private的。静态数据成员的类型可以是常量、引用、指针、类类型等。

举个例子,我们定义一个类,用它表示银行的账户记录:

class Account{
public:
void calculate(){amount+=amount*interestRate;}
static double rate(){return interestRate;}
static void rate(double);
private:
std::string owner;
double amount;
static double interestRate;
static double initRate();

类的静态成员存在于任何对象之外,对象中不包含任何与静态数据成员有关的数据。因此,每个Account对象将包括两个数据成员:owner和amount。只存在一个interestRate对象而且它被所有Account对象共享。

类似的,静态成员函数也不与任何对象绑定在一起,它们不包含this指针。作为结静态成员函数不能声明成const的,而且我们也不能在static函数体内使用this。这一限制既适用于this的显式使用,也对调用非静态成员的隐式使用有效。

使用类的静态成员

我们使用作用域运算符直接访问静态成员:

double r;
r =Account::rate();//使用作用域运算符访问静态成员

虽然静态成员不属于类的某个对象,但是我们仍然可以使用类的对象、引用或者指针来访问静态成员:

Account ac1;
Account *ac2=&ac1;
//调用静态成员函数rate的等价形式
r=ac1.rate();//通过Account的对象或引用
r=ac2->rate();//通过指向Account对象的指针

成员函数不用通过作用域运算符就能直接使用静态成员:

class Account{
public:
void calculate(){amount+=amount*interestRate;}
private:
static double interestRate;
//其他成员与之前的版本一致
};定义静态成员和其他的成员函数一样,我们既可以在类的内部也可以在类的外部定义静态成员函数。当在类的外部定义静态成员时,不能重复static关键字,该关键宇只出现在类内部的声明语句:```cpp
void Account::rate(double newRate)
{interestRate=newRate;
}因为静态数据成员不属于类的任何一个对象,所以它们并不是在创建类的对象时被定义的。这意味着它们不是由类的构造函数初始化的。而且一般来说,我们不能在类的内部初始化静态成员。相反的,必须在类的外部定义和初始化每个静态成员。和其他对象一样,-个静态数据成员只能定义一次。类似于全局变量,静态数据成员定义在任何函数之外。因此一旦它被定义,就将一直存在于程序的整个生命周期中。我们定义静态数据成员的方式和在类的外部定义成员函数差不多。我们需要指定对象的类型名,然后是类名、作用域运算符以及成员自己的名字:```cpp
//定义并初始化一个静态成员
double Account::interestRate=initRate();

这条语句定义了名为interestRate的对象,该对象是类Account的静态成员,其类型是double。从类名开始,这条定义语句的剩余部分就都位于类的作用域之内了。因此,我们可以直接使用initRate函数。注意,虽然initRate是私有的,我们也能用它初始化interestRate。和其他成员的定义一样interestRate的定义也可以访问类的私有成员。

要想确保对象只定义一次,最好的办法是把静态数据成员的定义与其他非内联函数的定义放在同一个文件中。

静态成员的类内初始化

通常情况下,类的静态成员不应该在类的内部初始化。然而,我们可以为静态成员提供const整数类型的类内初始值,不过要求静态成员必须是字面值常量类型的constexpr(参见7.5.6节,第267页)。初始值必须是常量表达式,因为这些成员本身就是常量表达式,所以它们能用在所有适合于常量表达式的地方。例如,我们可以用一个初始化了的静态数据成员指定数组成员的维度:

class Account{
public:
static double rate(){return interestRate;}
static void rate(double);
private:
static constexpr int period=30;//period是常量表达式
double daily_tbl[period];
}

如果某个静态成员的应用场景仅限于编译器可以替换它的值的情况,则一个初始化的const或constexpr static不需要分别定义。相反,如果我们将它用于值不能替换的场景中,则该成员必须有一条定义语句。例如,如果period的唯一用途就是定义daily_tbl的维度,则不需要在hccount外面专门定义period。此时,如果我们忽略了这条定义,那么对程序非常微小的改动也可能造成编译错误,因为程序找不到该成员的定义语句。举个例子,当需要把Account::period传递给一个接受const int &的函数时,必须定义period。如果在类的内部提供了一个初始值,则成员的定义不能再指定一个初始值了:

//一个不带初始值的静态成员的定义
constexpr intRccount::period;//初始值在类的定义肉提供

即使一个常量静态数据成员在类内部被初始化了,通常情况下也应该在类的外部定义一下该成员。

静态成员能用于某些场景,而普通成员不能

如我们所见,静态成员独立于任何对象。因此,在某些非静态数据成员可能非法的场合,静态成员却可以正常地使用。举个例子,静态数据成员可以是不完全类型。特别的,静态数据成员的类型可以就是它所属的类类型。而非静态数据成员则受到限制,只能声明成它所属类的指针或引用:

class Bar{
public:
// ...
private:
static Bar meml;//正确:静态成员可以是不完全类型
Bar* mem2;//正确:指针成员可以是不完全类型
Bar mem3;//错误:数据成员必须是完全类型
}静态成员和普通成员的另外一个区别是我们可以使用静态成员作为默认实参:```cpp
class Screen{
public:
//bkground表示一个在类中稍后定义的静态成员
Screen &clear(char=bkground);
private::
static const char bkground;
}

非静态数据成员不能作为默认实参,因为它的值本身属于对象的一部分,这么做的结果是无法真正提供一个对象以便从中获取成员的值,最终将引发错误。

相关文章:

C++ Primer 类的静态成员

欢迎阅读我的 【CPrimer】专栏 专栏简介:本专栏主要面向C初学者,解释C的一些基本概念和基础语言特性,涉及C标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级…...

【UCB CS 61B SP24】Lecture 4 - Lists 2: SLLists学习笔记

本文内容为重写上一节课中的单链表,将其重构成更易于用户使用的链表,实现多种操作链表的方法。 1. 重构单链表SLList 在上一节课中编写的 IntList 类是裸露递归的形式,在 Java 中一般不会这么定义,因为这样用户可能需要非常了解…...

【科研绘图系列】R语言绘制小提琴图、散点图和韦恩图(violin scatter plot Venn)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载画图1画图2画图3画图4画图5画图6画图7参考介绍 【科研绘图系列】R语言绘制小提琴图、散点图和韦恩图(violin & scatter plot & Venn) 加载R包 library…...

Linux中POSIX应用场景

Linux 提供了丰富的 POSIX(Portable Operating System Interface)标准接口,这些接口可以帮助开发者编写可移植、高效的应用程序。POSIX 标准定义了一系列系统调用和库函数,涵盖了文件操作、进程管理、线程管理、信号处理、同步机制…...

量子算法导论

重学了量子算法,不知道是温故而知新,还是之前的教材没有讲过这个概念。 如果把(图灵机)计算机比作一个查询机器,输入x通过f(x)作用得出结果,而查询的过程就是计算的过程。 中文解释…...

nasm - BasicWindow_64

文章目录 nasm - BasicWindow_64概述笔记my_build.batnasm_main.asmEND nasm - BasicWindow_64 概述 学习网上找到的demo. x64和x86的汇编源码还差挺多的。 x64的汇编代码不好写,细节整不对,程序就不运行。 如果要查为啥不运行,也要看和正向…...

SpringBoot:SSL证书部署+SpringBoot实现HTTPS安全访问

一、前言 SSL协议介于TCP/IP协议栈的第四层(传输层)和第七层(应用层)之间,为基于TCP的应用层协议(如HTTP)提供安全连接。它通过在客户端和服务器之间建立一个加密的通道,确保数据在传…...

selenium爬取苏宁易购平台某产品的评论

目录 selenium的介绍 1、 selenium是什么? 2、selenium的工作原理 3、如何使用selenium? webdriver浏览器驱动设置 关键步骤 代码 运行结果 注意事项 selenium的介绍 1、 selenium是什么? 用于Web应用程序测试的工具。可以驱动浏览…...

Spark提交任务

1、Spark提交任务到Yarn 1.1、DwKuduApp spark-submit --class com.io.etl.dwkudu.DwKuduApp \ --files /etl/etl-dwkudu/conf/doris.property,/etl/etl-dwkudu/conf/redis.property,/etl/etl-dwkudu/conf/log4j.property \ --master yarn --deploy-mode cluster \ --driver-…...

游戏引擎学习第113天

仓库:https://gitee.com/mrxiao_com/2d_game_2 黑板:优化的基本过程 在游戏编程中,优化是一个非常重要的学习内容,尤其是想要成为专业开发者时。优化的核心是理解代码的执行速度,以及如何提升其性能。在这个阶段,已经…...

token是什么

在自然语言处理(NLP)和机器学习的背景下,token 是指模型在处理文本时的最小单位。通常,这个单位可以是单词、字符,或者词的一部分。具体来说,token 的定义取决于你使用的模型和它的分词方式。 举个例子&am…...

23. AI-大语言模型-DeepSeek赋能开发-Spring AI集成

文章目录 前言一、Spring AI 集成 DeepSeek1. 开发AI程序2. DeepSeek 大模型3. 集成 DeepSeek 大模型1. 接入前准备2. 引入依赖3. 工程配置4. 调用示例5. 小结 4. 集成第三方平台(已集成 DeepSeek 大模型)1. 接入前准备2. POM依赖3. 工程配置4. 调用示例…...

IPv6报头40字节具体怎么分配的?

目录 IPv6报头结构 字段详解 示例代码:IPv6报头的Python实现 输出示例 IPv6协议是为了解决IPv4地址耗尽问题而设计的下一代互联网协议。与IPv4相比,IPv6不仅提供了更大的地址空间,还简化了报头结构,提高了网络设备的处理效率。…...

驱动开发、移植

一、任务明确:把创龙MX8的驱动 按照我们的要求 然后移植到 我们的板子 1.Linux系统启动卡制作, sd卡 先按照 《用户手册—3-2-Linux系统启动卡制作及系统固化》 把创龙的Linux系统刷进去。 2. 把TLIMX8-EVM的板子过一遍 把刚刚烧好系统的sd卡插入 创…...

BFS与Flood Fill:算法原理、实现细节与复杂度分析

目录 1. 概述 2. BFS 的基本原理 3. Flood Fill 算法 4. BFS 实现 Flood Fill 的步骤 5. C 实现 6. 代码解析 7. 复杂度分析 8. 应用场景 总结 1. 概述 Flood Fill 算法是一种用于填充封闭区域的算法,常用于图像处理、绘图工具和游戏开发中。BFS&#xff08…...

计算机网络基础杂谈(局域网、ip、子网掩码、网关、DNS)

目录 1. 简单局域网的构成 2. IP 地址 3. 子网掩码 4. IP地址详解自定义IP 5. IP 地址详解 6. 网关 7. DNS 域名解析 8. ping 1. 简单局域网的构成 交换机是组建局域网最重要的设备,换句话说,没有交换机就没法搭建局域网 交换机不能让局域网连…...

雷龙CS SD NAND(贴片式TF卡)测评体验

一、产品概述 近期获赠雷龙科技(Longsto)推出的CS系列贴片式SD NAND存储解决方案,包含两片工业级贴片式NAND芯片(CSNP16GCR01-AOW)及全兼容转接板。该方案支持TF卡形态扩展,实现高可靠性嵌入式存储应用。 …...

【Alertmanager】alertmanager告警系统原理剖析与应用实战,应有尽有非常全面

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…...

Java——权限修饰符

一、权限修饰符的继承访问规则 以下按访问范围从宽到窄排序: 修饰符同包同类同包子类同包非子类跨包子类跨包非子类public✔️✔️✔️✔️✔️protected✔️✔️✔️✔️❌默认(包级)✔️✔️✔️❌❌private✔️❌❌❌❌ 关键点&#xf…...

一周学会Flask3 Python Web开发-redirect重定向

锋哥原创的Flask3 Python Web开发 Flask3视频教程: 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 前面我们学过渲染到模板页面,这个其实是一种内部的转发,浏览器地址栏地址没有变化。如果我们想重定向…...

Linux 0.11源码深度解析:kernel/chr_drv/tty_io.c —— 终端I/O的控制中枢与行规约引擎

一、文件概述:用户与内核的交互桥梁tty_io.c​ 位于 /kernel/chr_drv目录,是Linux 0.11中终端(Terminal/TTY)输入输出的核心实现。在1991年的命令行时代,终端是用户与计算机交互的唯一窗口。这个文件负责管理键盘输入的…...

OpenCV中SVM算法原理与图像分类实战

1. 支持向量机与OpenCV的深度整合支持向量机(SVM)作为机器学习领域的经典算法,在OpenCV计算机视觉库中有着成熟的实现。我在实际图像分类项目中多次采用这种组合方案,特别是在处理小样本、高维度数据时,SVM的决策边界优…...

Spring Boot + 策略模式:增强接口扩展性的最佳实践

一、为什么需要策略模式?在实际业务开发中,经常会遇到一个接口有多种不同实现方式的场景。例如:支付系统:微信支付、支付宝支付、银行卡支付订单折扣:满减、打折、VIP特价文件处理:PDF导出、Excel导出、CSV…...

科学AI智能体的强化学习训练与应用实践

1. 科学智能体训练概述科研工作往往充斥着大量重复性劳动——文献查阅、实验流程管理、多模态数据处理等机械性工作占据了研究者大量时间。科学AI智能体的出现,正在改变这一现状。这类智能体能够承担文献综述、假设生成、实验规划、计算任务提交、实验室操作协调、结…...

5分钟在Windows 10上畅玩安卓应用:WSA反向移植完全指南

5分钟在Windows 10上畅玩安卓应用:WSA反向移植完全指南 【免费下载链接】WSA-Windows-10 This is a backport of Windows Subsystem for Android to Windows 10. 项目地址: https://gitcode.com/gh_mirrors/ws/WSA-Windows-10 还在羡慕Windows 11用户能直接…...

Stream-rec直播流录制:从零开始构建你的自动化录播系统

Stream-rec直播流录制:从零开始构建你的自动化录播系统 【免费下载链接】stream-rec Automatic streaming record tool. Live stream and bullet comments recorder. 虎牙/抖音/斗鱼/Twitch/PandaTV/微博直播,弹幕自动录制 项目地址: https://gitcode.…...

MCP多模态融合效率提升300%:从零搭建可落地的跨模态对齐Pipeline

更多请点击: https://intelliparadigm.com 第一章:MCP多模态融合效率提升300%:从零搭建可落地的跨模态对齐Pipeline MCP(Multimodal Contrastive Projection)通过统一隐空间约束,实现文本、图像与语音特征…...

【深度解析】DeepSeek V4 Pro/Flash:百万 Token 上下文、MoE 架构与 OpenAI 兼容 API 实战

摘要: 本文围绕 DeepSeek V4 Pro/Flash 的模型定位、MoE 架构、百万 Token 上下文能力与 OpenAI 兼容 API 接入方式展开,并给出 Python 实战代码。 一、背景介绍:DeepSeek V4 为什么值得开发者关注 DeepSeek V4 的核心看点不只是“模型变大”…...

如何使用python转移mysql数据库中的全部数据

今天,有人告诉我,“马上就要双十一了,我遇到了一个问题。”我很好奇,“是什么问题呢?关于双十一的商品折扣吗?”他说,“不,是我之前双十一的时候,购买的mysql数据库到期了…...

Spring AOP 进阶实战:从日志到权限/链路追踪/限流(真正企业用法)

一、前言 上一篇 Spring AOP 从原理到实战(结合事务彻底搞懂) 我们已经搞懂了: ✔ AOP 原理 ✔ Before / After / Around 的区别 ✔ 事务为什么用 AOP 但是很多人学完之后,会有一个问题:AOP 到底在项目里怎么用&…...