【C++】类与对象—— 初始化列表 、static 静态成员、

在这里插入图片描述

类与对象

  • 1 再谈构造函数
    • 1.1 构造函数体赋值
    • 1.2 初始化列表
      • 语法:
      • 建议:
      • 初始化顺序:
      • 注意:
    • 1.3 explicit关键字
  • 2 static 静态成员
    • 2.1 概念
    • 2.2 声明成员变量
    • 2.3 使用类的静态成员
    • 2.4 定义静态成员
    • 总结
  • Thanks♪(・ω・)ノ谢谢阅读!!!
  • 下一篇文章见!!!

1 再谈构造函数

1.1 构造函数体赋值

在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值,以我们之前实现的Date类对象为例。

class Date
{
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

虽然上述构造函数调用的时候,对象中成员变量都有一个初始值了,但是不能将其成为对象中成员变量的初始化,构造函数中语句只能将其成为赋初值,不能叫做初始化。因为初始化只能初始化一次,而构造函数可以多次赋值。进而我们有了初始化列表的概念。

1.2 初始化列表

语法:

初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。

class Date
{
public:
	Date(int year, int month, int day)
	:_year(year)
	,_month(month)
	,_day(day)
	{ }
	
private:
	int _year;
	int _month;
	int _day;
};

建议:

有时我们可以忽略数据成员初始化的和赋值之间的差异,但并非总是这样。
如果成员是const 或 引用变量的话,必须将其初始化。类似的如果存在自定义类型并且该类不存在构造函数时,也必须将其初始化。例如:

class A {
private:
	int a;
};
class Date
{
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
		
	}

private:
	const int _year;
	int& _month;
	int _day;
	A a;
};
int main(){
	const Date a1(2024,2,24);

	return 0;
}

来看看报错:
在这里插入图片描述
显然我们需要初始化来帮助我们解决这些问题。
在很多类中初始化和赋值的区别事关底层效率的问题:前者直接初始化数据成员,后者则先初始化再赋值。除了效率问题外更重要的是,一些数据成员必须初始化。所以一般建议养成使用初始化列表的习惯,这样可以避免某些意想不到的编译错误,特别是遇到类包含构造函数初始值的成员时。

初始化顺序:

显然在构造函数中每个成员只能出现一次。否则给同一个成员赋两个不同初始值有什么意义呢?
需要注意的是初始化列表不限定初始化的执行顺序,因为成员初始化的顺序与他们在类出现顺序一致,第一个成员先初始化,然后第二个,以此类推,因此构造函数初始化列表的前后位置并不影响实际的初始化顺序。
但是下面这个例子不同:

class A
{
public:
	A(int a)
		:_a1(a)
		,_a2(_a1)
	{}
	void Print() {
		cout << _a1 << " " << _a2 << endl;
	}
private:
	int _a2;
	int _a1;
};
int main() {
	A aa(1);
	aa.Print();
}

我们想要两个输出 1 1 ,但是程序实际输出了:
在这里插入图片描述
这就是因为初始化顺序的问题了,因为成员_a2在_a1前,所以先对_a2初始化,就造成了随机值。

注意:

  1. 每个成员变量在初始化列表中只能出现一次(初始化只能一次)
  2. 类中包括以下成员,必须在初始化列表进行初始化 :
    引用成员变量
    const成员变量
    自定义类型成员(并且该类没有默认构造函数时)
  3. 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化
  4. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关。

1.3 explicit关键字

构造函数不仅可以构造与初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值的构造函数,还具有类型转换的作用。

class Date
{
public:
// 1. 单参构造函数,没有使用explicit修饰,具有类型转换作用
// explicit修饰构造函数,禁止类型转换---explicit去掉之后,代码可以通过编译
   explicit Date(int year)
   	:_year(year)
   	{}
private:
   int _year;
   int _month;
   int _day;
};
void Test()
{
   	Date d1(2022);
   // 用一个整形变量给日期类型对象赋值
   // 实际编译器背后会用2023构造一个无名对象,
   //最后用无名对象给d1对象进行赋值

}
 class Date
{
public:
// 2. 虽然有多个参数,但是创建对象时后两个参数可以不传递,
//没有使用explicit修饰,具有类型转换作用
// explicit修饰构造函数,禁止类型转换
		explicit Date(int year, int month = 1, int day = 1)
			: _year(year)
			, _month(month)
			, _day(day)
			{}

		Date& operator=(const Date& d)
		{
				if (this != &d)
					{
						_year = d._year;
						_month = d._month;
						_day = d._day;
					}
				return *this;
		}
private:
		int _year;
		int _month;
		int _day;
};
void Test()
{
		Date d1(2022);
// 用一个整形变量给日期类型对象赋值
// 实际编译器背后会用2023构造一个无名对象,
//最后用无名对象给d1对象进行赋值
		d1 = 2023;
// 将 1 屏蔽掉,2放开时则编译失败,因为explicit修饰构造函数,
//禁止了单参构造函数类型转换的作用
}

由于上述代码可读性不是很好,所以一般单参数的类构造都要使用explicit修饰。

2 static 静态成员

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

2.1 概念

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化

2.2 声明成员变量

我们通过在成员的声明之前加入关键字 static 就可以创建,和其他成员一样,静态成员也是可以被 public 或 private的。静态成员变量的类型可以是常量,引用,指针,类类型等。
并且,静态成员函数也不与任何对象绑定在一起,他们不包含this指针。作为结果,静态成员函数不能声明成const 的而且我们也不能在static 函数体内使用this指针。这一限制及适用于this的显式使用,也对调用非静态成员的隐式使用有效。

2.3 使用类的静态成员

使用时我们通过作用域运算符直接访问静态成员。
虽然静态成员不属于类的某个对象,但是我们依然可以使用类的对象、引用、或者指针来访问静态成员。如下:

class Date
{
public:
	Date(int year, int month, int day)
	:_year(year)
	,_month(month)
	,_day(day)
	{ }
static void count();
private:
	int _year;
	int _month;
	int _day;
};
void count(){
}int main(){
	Date d1;
	Date* d2 = &d1; 
	d2->count();
	d1.count();
	return 0;
}

2.4 定义静态成员

和其他成员函数一样,我们既可以在类内部也可以在外部定义。当在类外定义时,不需要重复写 static 关键字,该关键字只出现在类内部的声明语句。
和类的所有成员一样,当我们指向类外部的静态成员时,必须指明成员所属的类名。static 关键字则只出现在类内部的声明语句中
要确保对象只定义一次,最好的办法就是把静态成员的定义与其他非内联函数的定义于同一个文件中。

总结

  1. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区
  2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明
  3. 类静态成员即可用 类名 :: 静态成员 或者 对象.静态成员 来访问
  4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
  5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制

Thanks♪(・ω・)ノ谢谢阅读!!!

下一篇文章见!!!

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

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

相关文章

Linux:gcc的基本知识

gcc 是一个将C语言文件变成可执行文件的工具。 在Linux中&#xff0c;如果需要将一个C语言文件变得可以执行&#xff0c;那么除了这个文件本身的内容是C语言编写的内容外&#xff0c;还需要gcc这个编译工具进行编译才行。 gcc 使用的格式方法:gcc 要编译的文件 //在该代码下…

【数据结构与算法初学者指南】【冲击蓝桥篇】String与StringBuilder的区别和用法

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《数据结构与算法&#xff1a;初学者入门指南》&#x1f4d8;&am…

Llama2模型的优化版本:Llama-2-Onnx

Llama2模型的优化版本&#xff1a;Llama-2-Onnx。 Llama-2-Onnx是Llama2模型的优化版本。Llama2模型由一堆解码器层组成。每个解码器层&#xff08;或变换器块&#xff09;由一个自注意层和一个前馈多层感知器构成。与经典的变换器相比&#xff0c;Llama模型在前馈层中使用了不…

Redis进阶篇

Redis线程模型 redis是基于内存运行的高性能k-v数据库&#xff0c;6.x之前是单线程, 对外提供的键值存储服务的主要流程 是单线程&#xff0c;也就是网络 IO 和数据读写是由单个线程来完成&#xff0c;6.x之后引入多线程而键值对读写命 令仍然是单线程处理的&#xff0c;所以 …

[SpringDataMongodb开发游戏服务器实战]

背景&#xff1a; xdb其实足够完美了&#xff0c;现在回想一下&#xff0c;觉得有点复杂&#xff0c;我们不应该绑定语言&#xff0c;最好有自己的架构思路。 七号堡垒作为成功的商业项目&#xff0c;告诉我&#xff1a;其实数据是多读少写的&#xff0c;有修改的时候直接改库也…

离散数学 第八单元 布尔代数

目录 1. 布尔函数 2. duality 二元性 3. 表示布尔函数的布尔表达式 sum-of-products expansions 4. Functional Completeness 5. Logic Gates 逻辑门​​​​​​​ 4. 最小化 K-map卡诺图 Quine-McCluskey法 1. 布尔函数 嗯也就是我要知道布尔代数是啥形式&#xff…

[面试] 什么是死锁? 如何解决死锁?

什么是死锁 死锁&#xff0c;简单来说就是两个或者多个的线程在执行的过程中&#xff0c;争夺同一个共享资源造成的相互等待的现象。如果没有外部干预线程会一直阻塞下去. 导致死锁的原因 互斥条件&#xff0c;共享资源 X 和 Y 只能被一个线程占用; 请求和保持条件&#xf…

VMware虚拟机从一台电脑复制到另一台电脑

1 概述 在一台电脑上利用虚拟机安装了OS系统&#xff0c;特别是如果虚拟机中的系统进行了各种繁琐的配置&#xff0c;因为换电脑或者需要在其他电脑上配置&#xff0c;这个时候就可以将虚拟机中的系统复制拷贝一份到新电脑上&#xff0c;省时省力。 2 操作步骤 2.1 vmx文件 …

数字化转型导师坚鹏:政府数字化运营三步曲之认知、行动、结果

政府数字化运营三步曲之认知、行动、结果 课程背景&#xff1a; 很多政府都在开展数字化运营工作&#xff0c;目前存在以下问题急需解决&#xff1a; 不清楚政府数字化运营包括哪些关键工作&#xff1f; 不清楚政府数字化运营工作的核心方法论&#xff1f; 不清楚政府数…

单词倒排——c语言解法

以下是题目&#xff1a; 这个题中有三个点&#xff0c; 一个是将非字母的字符转换为空格&#xff0c; 第二是如果有两个连续的空格&#xff0c; 那么就可以将这两个连续的空格变成一个空格。 第三个点就是让单词倒排。 那么我们就可以将这三个点分别封装成三个函数。 还有就是…

电脑闹钟软件哪个好用?

电脑闹钟软件哪个好用&#xff1f;一款带有闹钟定时提醒的备忘录软件是比较实用的&#xff0c;很多上班族每天都要处理堆积如山的工作&#xff0c;总是会忙于一件事的时候忘记另外一件事&#xff0c;导致效率极低。如当一项重要会议需要提前准备资料时&#xff0c;我们却忙于其…

复旦大学MBA聚劲联合会:洞见智慧,拓宽思维格局及国际化视野

12月2日&#xff0c;“焕拥时代 俱创未来”聚劲联合会俱创会年度盛典暨俱乐部募新仪式圆满收官。16家复旦MBA俱乐部、200余名同学、校友、各界同仁齐聚复旦管院&#xff0c;一起在精彩纷呈的圆桌论坛里激荡思想&#xff0c;在活力四射的俱乐部风采展示中凝聚力量。      以…

《Docker 简易速速上手小册》第1章 Docker 基础入门(2024 最新版)

文章目录 1.1 Docker 简介与历史1.1.1 Docker 基础知识1.1.2 重点案例&#xff1a;Python Web 应用的 Docker 化1.1.3 拓展案例 1&#xff1a;使用 Docker 进行 Python 数据分析1.1.4 拓展案例 2&#xff1a;Docker 中的 Python 机器学习环境 1.2 安装与配置 Docker1.2.1 重点基…

《隐私计算简易速速上手小册》第9章:实现隐私计算的步骤(2024 最新版)

文章目录 9.1 规划与设计:描绘你的隐私保护蓝图9.1.1 基础知识9.1.2 主要案例:设计一个隐私保护的数据分享平台9.1.3 拓展案例 1:创建一个隐私保护的健康数据分析系统9.1.4 拓展案例 2:开发一个加密的即时通讯应用9.2 实施与部署:从蓝图到现实9.2.1 基础知识9.2.2 主要案例…

BentoML:如何使用 JuiceFS 加速大模型加载?

BentoML 是一个开源的大语言模型&#xff08;LLM&#xff09; AI 应用的开发框架和部署工具&#xff0c;致力于为开发者提供最简单的构建大语言模型 AI 应用的能力&#xff0c;其开源产品已经支持全球数千家企业和组织的核心 AI 应用。 当 BentoML 在 Serverless 环境中部署模型…

牛客网 HJ10 字符个数统计

思路&#xff1a; 我们创建两个数组&#xff0c;一个数组接受输入的字符&#xff0c;另一个数组用来统计字符种数 同时将该字符作为下标传给另一个数组&#xff0c;如果另一个数组的这个下标对应的值为0&#xff0c;说明该字符没有被统计过&#xff0c;计数器加1&#xff0c;…

在当前源文件的目录或生成系统路径中未找到文件

vsqt中增加&#xff0c;减少文件&#xff0c;都必须要动一下cmakelist.txt,点一下换行或者保存 因为vsqt反应不过来 1。都必须要动一下cmakelist.txt,点一下换行或者保存 2.然后全部重新生成&#xff0c;或者重新扫描解决方案&#xff08;多扫几次&#xff09;

现货黄金中短线投资该怎么做?

要明确什么是现货黄金的中短线投资&#xff0c;中短线投资是指在短期内&#xff08;一般为几天至几周&#xff09;对现货黄金进行买卖操作&#xff0c;以期获得收益的投资方式。相较于长线投资&#xff0c;中短线投资的风险相对较大&#xff0c;但同时收益也更为可观。那么&…

只需三步即可更改centos7系统语言,centos7系统语言更换,centos7系统中文互换

只需三步即可更改centos7系统语言,centos7系统语言更换,centos7系统中文互换 操作系统&#xff1a;centOS7.8 64位 ssh登录工具:FinalShell FinalShell可以点此下载 先查看系统的默认语言 locale #zh_CN 中文如何验证是中文&#xff0c;可以使用umtui来验证 umtui是一款…

【MATLAB源码-第146期】基于matlab的信源编码仿真GUI,对比霍夫曼编码,算术编码和LZ编码。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 霍夫曼编码、算术编码和LZ编码是三种广泛应用于数据压缩领域的编码技术。它们各自拥有独特的设计哲学、实现方式和适用场景&#xff0c;因此在压缩效率、编解码速度和内存使用等方面表现出不同的特点。接下来详细描述这三种编…
最新文章