C++学习笔记----8、掌握类与对象(四)---- 不同类型的数据成员(1)

        c++对于数据成员给了你许多选项。除了在类中声明简单的数据成员,可以生成静态数据成员供所有类的对象共享,const成员,引用成员,reference-to-const成员,等等。本节我们解释一下这些不同类型的数据成员的细节。

1、静态数据成员

        有时候给类的第一个对象变量的拷贝会过度猎杀或者不管用。数据成员可能特定于类,但让每个对象有一个拷贝是不合适的。例如,你可能想给每个spreadsheet一个单独的数字标识符。就需要一个从0开始的计数器,每个对象可以包含它的ID。这个spreadsheet计数器确实属于Spreadsheet类,但是让每个Spreadsheet对象都有一个拷贝是没有什么道理的,因为不管怎么样你都要让所有的计数器同步。c++提供了一个解决方案,使用静态数据成员。静态数据成员是一个与类而不是对象相关联的数据成员。可以认为静态数据成员是类的全局变量。下面是Spreadsheet类的定义,包含了新的静态计数数据成员:

export class Spreadsheet
{
    // Omitted for brevity

private:
    static std::size_t ms_counter;
};

        在类定义中除了列出静态类成员之外,还需要在源文件中为它们分配空间,通常会把类成员函数的定义放到源文件中。可以同时初始化它们,但是要记住与正常的变量与数据成员不同,它们缺省是被初始化为0的。静态指针会被初始化为nullptr。下面是分配空间并且将其初始化为0的ms_counter的代码:

size_t Spreadsheet::ms_counter;

        静态数据成员缺省初始化为0,但是如果你想,也可以显式地像下面这样对其进行初始化:

size_t Spreadsheet::ms_counter { 0 };

        该代码出现在任何函数或者成员函数体之外。差不多像是声明一个全局变量,除了Spreadsheet::范围解释符指出它是Spreadsheet类的一部分。

        与正常的数据成员一样,访问控制指示符也应用于静态数据成员。可以将ms_counter数据成员弄成public的,但是,你早已知晓,是不推荐拥有public数据成员的(我们后面要讨论的const static数据成员是个例外)。应该通过public的getter与setter来获得对数据成员的访问。如果想要给静态数据成员赋予访问的权限,可以提供public的静态get/set成员函数。

1.1、内联变量

        可以将静态数据成员声明为inline。这样做的好处是不需要在源文件中为其分配空间。下面是例子:

export class Spreadsheet
{
    // Omitted for brevity

private:
    static inline std::size_t ms_counter { 0 };
};

        注意inline关键字,有了这样的类定义,下面这行代码就可以从源文件中移除了:

size_t Spreadsheet::ms_counter;

1.2、在类成员函数内访问静态数据成员

        可以使用静态数据成员就像它们是类成员函数中的通常的数据成员一样。例如,你可能会想生成一个Spreadsheet类的m_id的数据成员并在Spreadsheet构造函数中从ms_counter进行初始化。下面是带有m_id成员的Spreadsheet类定义:

export class Spreadsheet
{
public:
	// Omitted for brevity
	std::size_t getId() const;
private:
	// Omitted for brevity
    static inline std::size_t ms_counter{ 0 }; 
    std::size_t m_id { 0 };
};

        下面是对赋值给初始ID的Spreadsheet构造函数的实现:

Spreadsheet::Spreadsheet(size_t width, size_t height)
: m_id { ms_counter++ }, m_width { width }, m_height { height }
{
    // Omitted for brevity
}

        你可以看到,构造函数可以访问ms_counter就像它是一个正常的成员。拷贝构造函数也赋值一个新的ID。这会自动处理,因为Spreadsheet拷贝构造函数代理到non-copy构造函数,它生成了新的ID。

        对于这个例子,假定一旦ID赋值给一个对象,它就不再改变。所以,不应该在拷贝赋值操作符中拷贝ID。这样的话,推荐使m_id成为一个const数据成员:

export class Spreadsheet
{
private:
    // Omitted for brevity
    const std::size_t m_id { 0 };
};

        既然数据成员一旦生成就不再改变,就不可能在构造函数体内初始化。这样的数据成员必须要么直接在类定义或者在构造函数初始化器中初始化。这也就意味着不能在赋值操作符中给这样的数据成员赋新值。对于m_id来说这不是总是,因为一旦Spreadsheet拥有了一个ID,它就不会再改变。然而,要依实际情况而定,如果这就使你的类无法赋值,赋值操作符就要被明正典刑--显式删除了。

2、constexpr静态数据成员

        类中的数据成员可以被声明为const或者constexpr,意思是它们在生成与初始化后不能被改变。应该使用static constexpr(或者constexpr static)数据成员在全局常量的位置上,当常量只应用于类时,也叫做类常量。整型的和枚举型的static constexpr数据成员可以被定义并且初始化在类定义内,即使没有将它们定义成内联变量。例如,你可能想要给spreadsheet指定一个最大的高度与宽度。如果用户想要构建一个比最大值更大的高度与宽度的spreadsheet,就会使用最大值。可以将Spreadsheet类的最大值高度与宽度弄成static constexpr成员。

export class Spreadsheet
{
public:
    // Omitted for brevity
    static constexpr std::size_t MaxHeight { 100 };
    static constexpr std::size_t MaxWidth { 100 };
};

        可以如下面这样在构造函数中使用新的常量:

Spreadsheet::Spreadsheet(size_t width, size_t height)
: m_id { ms_counter++ }
, m_width { std::min(width, MaxWidth) } // std::min() defined in <algorithm>
, m_height { std::min(height, MaxHeight) }
{
    // Omitted for brevity
}

        注意:不自动用最大值替换超过的宽度与高度,也可以决定在宽度与高度超过最大值时抛出例外。然而,在构造函数中抛出例外是不会调用析构函数的。所以要认真对待这一点。这个我们会在以后讨论错误处理时再详细讨论。

        这样的常量也可以用于参数的缺省值。记住只能对于从最右边开始的连续的参数给出缺省值。下面是例子:

export class Spreadsheet
{
public:
    explicit Spreadsheet(
    std::size_t width = MaxWidth, std::size_t height = MaxHeight);
    // Omitted for brevity
};

2.1、从类成员函数外部访问静态数据成员

如前所述,访问控制标识符应用于静态数据成员:MaxWidth与MaxHeight为public,所以它们可以从类成员函数外部访问,通过指定变量为Spreadsheet类的一部分,使用::范围解析操作符。例如:

println("Maximum height is: {}", Spreadsheet::MaxHeight);

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

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

相关文章

【Redis】如何在 Ubuntu 上安装 Redis 5

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 本期内容主要介绍如何在 Ubuntu 上安装 Redis5 一些碎碎念&#xff1a; 本来这期内容介绍如何在 Centos 安装 Redis …

区块链可投会议CCF C--CT-RSA 2025 截止10.15 附2024录用率

Conference&#xff1a;The Cryptographers Track at RSA Conference (CT-RSA) CCF level&#xff1a;CCF C Categories&#xff1a;network and information security Year&#xff1a;2025 Conference time&#xff1a;San Francisco, California, USA • April 28–May …

.NET开源跨平台桌面和移动应用的统一框架 - Eto.Forms

前言 今天大姚给大家分享一个.NET开源、跨平台桌面和移动应用的统一框架&#xff1a;Eto.Forms。 项目介绍 Eto.Forms是一个.NET开源、跨平台的桌面和移动应用的统一框架&#xff0c;该框架允许开发者使用单一的UI代码库构建在多个平台上运行的应用程序&#xff0c;并利用各…

嵌入式C语言自我修养:编译链接

源文件生成可执行文件的过程&#xff1f; 源文件经过预处理、编译、汇编、链接生成一个可执行的目标文件。 编译器驱动程序&#xff0c;包括预处理器、编译器、汇编器和链接器。Linux用户可以调用GCC驱动程序来完成整个编译流程。 使用GCC驱动程序将示例程序从ASCII码源文件转换…

数字图像处理:边缘检测

数字图像处理&#xff1a;边缘检测 笔记来源&#xff1a; 1.Gradient and Laplacian Filter, Difference of Gaussians (DOG) 1.1 图像一阶梯度 水平方向的一阶导数 一阶导数滤波器在实际应用中难实现的原因 图像梯度中&#xff0c;一阶梯度中找局部极大值就是边缘所在处&a…

SOCKS5代理和HTTP代理哪个快?深度解析两者的速度差异

在现代互联网环境中&#xff0c;使用代理IP已经成为了许多人日常生活和工作的必备工具。无论是为了保护隐私&#xff0c;还是为了访问某些特定资源&#xff0c;代理IP都扮演着重要的角色。今天&#xff0c;我们就来聊聊SOCKS5代理和HTTP代理&#xff0c;看看这两者到底哪个更快…

netty编程之实现websocket客户端并发送二进制消息

写在前面 源码。 本文看下netty如何实现websocket客户端并发送二进制消息。 ws的server端参考这篇文章。 1&#xff1a;正文 抽象类AbstractWebsocketClient定义了发送二进制数据的方法&#xff1a; public abstract class AbstractWebsocketClient implements Closeable {…

向量数据库|第1期|从零开始学习

向量数据库|第1期|从零开始学习 1、向量数据库中的基本概念 1.1 什么是余弦 余弦函数是一种三角函数&#xff0c;在直角三角形中&#xff0c;某个锐角的余弦为&#xff1a;临边与斜边的比值&#xff0c;如下图cosAb/c。引申到任意三角形中&#xff0c;即余弦定理&#xff1a;…

大数据-151 Apache Druid 集群模式 配置启动【上篇】 超详细!

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

数据结构--二叉树的顺序实现(堆实现)

引言 在计算机科学中&#xff0c;二叉树是一种重要的数据结构&#xff0c;广泛应用于各种算法和程序设计中。本文将探讨二叉树的顺序实现&#xff0c;特别是堆的实现方式。 一、树 1.1树的概念与结构 树是⼀种⾮线性的数据结构&#xff0c;它是由 n(n>0) 个有限结点组成…

【C++打怪之路Lv6】-- 内存管理

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;C打怪之路&#xff0c;python从入门到精通&#xff0c;数据结构&#xff0c;C语言&#xff0c;C语言题集&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文(平均质量分82)&#…

15分钟学 Python 第36天 :Python 爬虫入门(二)

Python 爬虫入门&#xff1a;环境准备 在进行Python爬虫的学习和实践之前&#xff0c;首先需要准备好合适的开发环境。本节将详细介绍Python环境的安装、必要库的配置、以及常用工具的使用&#xff0c;为后续的爬虫编写奠定坚实的基础。 1. 环境准备概述 1.1 为什么环境准备…

基于Springboot投稿和稿件处理系统设计与实现

博主介绍&#xff1a;专注于Java vue .net php phython 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟 我的博客空间发布了1000毕设题目 方便大家学习使用 感兴趣的…

数据集-目标检测系列- 货船 检测数据集 freighter>> DataBall

数据集-目标检测系列- 货船 检测数据集 freighter>> DataBall 数据集-目标检测系列- 货船 检测数据集 freighter>> DataBall 数据量&#xff1a;3k 想要进一步了解&#xff0c;请联系。 DataBall 助力快速掌握数据集的信息和使用方式&#xff0c;会员享有 百种…

订阅ROS2中相机的相关话题并保存RGB、深度和点云图

系统&#xff1a;Ubuntu22.04 ROS2版本&#xff1a;ROS2 humble 1.订阅ROS2中相机的相关话题并保存RGB图、深度图和点云图 ros2 topic list/stellar_1/rgb/image_raw /camera/depth/image_raw /stellar_1/points2CMakeLists.txt cmake_minimum_required(VERSION 3.15) projec…

建筑资质的未来发展趋势

&#x1f3d7;️建筑资质是建筑企业进入市场的通行证&#xff0c;它不仅关系到企业的竞争力&#xff0c;也影响着整个建筑行业的健康发展。随着政策的调整和技术的进步&#xff0c;建筑资质管理正面临着新的变革。 1. 资质管理的数字化转型&#xff1a;&#x1f310; 随着信息技…

Gaussian-splatting 项目环境配置笔记(Win11)

如果你是配置别的项目的过程中用到了3D GS相关的内容&#xff0c;然后这部分内容环境一直配不好&#xff0c;也可以跟随这个博客配一下环境&#xff0c;配完后起码3D GS部分就搞定了。 文章目录 概述项目链接&#xff1a;VS2019直接下载链接CUDA不同版本下载链接安装Condasetup…

63.5 注意力提示_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录注意力提示生物学中的注意力提示查询、键和值注意力的可视化使用 show_heatmaps 显示注意力权重代码示例 代码解析结果 小结练习 注意力提示 &#x1f3f7;sec_attention-cues 感谢读者对本书的关注&#xff0c;因为读者的注意力是一种稀缺…

【MATLAB2024b】安装离线帮助文档(windows)

文章目录 一、在 MATLAB 设置中安装二、从math works 网站下载ISO&#xff1a;给无法联网的电脑安装三、重要说明 版本&#xff1a;matlab 2024b&#xff08;或者大于等于2023a&#xff09; 所需空间&#xff1a;10~15 GB 平台&#xff1a;Windows 需要注册math works账号。 一…

深度学习-19-深入理解并训练自己的Tokenizer分词器

文章目录 1 tokenization是什么2 Tokenization方法简介2.1 单词级的Tokenization2.2 子词Tokenization技术2.3 举例说明2.3.1 字符级别2.3.2 词语级别2.3.3 子词级别3 训练自己的Tokenizer3.1 下载数据集3.2 huggingface的Tokenizer实现3.3 my-tokenizer.json字段说明3.4 验证一…