类的六个构造函数相关干货

构造函数

特点

1.名字与类名相同
2.无返回值
3.对象实例化的时候编译器自动调用这个函数
4.构造函数可以重载(无参构造函数,拷贝构造等)
5.如果类中没有显式定义构造函数(深拷贝),则编译器会自动生成一个默认构造函数(浅拷贝/值拷贝),若显式定义了编译器就不再生成

class Date
{
public:
	Date()//无参构造函数
	{}
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
public:
	void test1()
	{
		Date d1;//无参
		Date d2(2024, 4, 14);//带参
	}
};

6.c++把类型分为内置类型和自定义类型,对于内置类型来说,编译器自动生成的默认构造函数是不会将内置类型初始化的(为了弥补这个缺陷,c++11中的内置成员变量在声明的时候是可以给默认值的),所以如果下面这个代码我们没有主动去设置构造函数,里面的三个成员变量就都是随机值,若他是自定义类型,编译器就会去调用这个类型的默认构造函数

#include<iostream>
using namespace std;
class Day
{
public:
	Day()
	{
		_day = 0;
		cout << "Day()" << endl;
	}
private:
	int _day;
};
class Date
{
private:
	int _year=2024;
	int _month=4;
	Day _day;
};
int main()
{
	Date d1;
	return 0;
}

7.无参的构造函数,全缺省的构造函数和编译器自动生成的构造函数都可以被称为默认构造函数

初始化列表

来由

调用构造函数赋值时,我们会给变量一个初始值,但是这不能称为变量的初始化,只能称为赋值,因为初始化只能初始化一次,而构造函数中可以对变量多次赋值,于是就产生了初始化列表。

用法

以一个冒号为开始,每个成员变量后面跟着一个用括号隔开的值或者表达式

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

注意:每个成员变量在初始化列表中只能初始化一次,也就是只能出现一次,当类中成员变量包含引用成员变量,const类型成员变量,没有默认构造函数的类类型成员变量时,都要放在初始化列表初始化,我们也尽量使用初始化列表初始化,因为不管你用不用初始化列表,程序都会先走初始化列表再执行构造函数里面的内容的,成员变量的声明顺序就是初始化列表的初始化顺序,与初始化列表里的顺序是无关的,所以最好不要让初始化的成员互相初始化,很容易得到随机值

explicit关键字

我们偶尔会看到如下代码

class vientiane
{
public:
	vientiane(int year,int month=1,int day=1)
	:_year(year)
	,_month(month)
	,_day(day)
	{}
private:
	int _year;
	int _month;
	int _day;
}
int main()
{
	vientiane d1(2024);
	vientiane d2=2024;
	return 0;
}

也许你会疑惑,d2是一个自定义类型,而2024是一个整形,为什么可以这样直接赋值呢?其实,c++里有一种隐式类型转换,比如说你现在有一个整形变量a=1,你想让他赋值给double类型变量b,那么在赋值过程中会产生一个double类型的临时变量,这个double类型的临时变量被赋值成1.0,然后再用这个临时变量去给b赋值,上图那段代码也一样,“2024”会先调用构造函数构造一个vientiane类型的变量,然后再用拷贝构造去初始化d2,如果你不想要有这样的类型转换,你可以在构造函数前加一个explicit关键字

class vientiane
{
public:
	explicit vientiane(int year,int month=1,int day=1)
	:_year(year)
	,_month(month)
	,_day(day)
	{}
private:
	int _year;
	int _month;
	int _day;
}
int main()
{
	vientiane d1(2024);
	vientiane d2=2024;
	return 0;
}

这样,上述代码就会报错了
在这里插入图片描述

析构函数

概念

析构函数不是对对象的销毁,而是完成销毁后对对象里的资源清理工作,对象的销毁是由编译器自己进行的

特点

1.析构函数名是类名前加一个~
2.析构函数没有参数也没有返回值,自然就无法构成重载
3.一个类只能有一个析构函数,若没有显式定义析构函数,则编译器会自动生成默认析构函数
4.对象生命周期结束时,编译器会自动调用析构函数

#include<iostream>
using namespace std;
class Date
{
public:
	Date()
	{
		_year = 2024;
		_month = 4;
		_day = 14;
	}
	~Date()
	{
		_year = 0;
		_month = 0;
		_day = 0;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1;
	return 0;
}

5.编译器生成的默认析构函数和默认构造函数一样,对于自定义类型,编译器都会自动调用对应的默认析构函数
6.如果类中没有申请资源时,析构函数可以不写,但如果有申请时,就必须写析构函数,否则就会造成内存泄露

拷贝构造

概念

只有单个形参,编译器在创建新对象的时候会自动调用,这个形参必须是和新生成对象一样的类型

特点

1.拷贝构造是构造函数的一个重载函数
2.在调用拷贝构造创建新变量的时候,必须使用引用,否则会引发无穷递归调用,因为函数在传参的时候会调用拷贝构造创建形参,所以会无穷尽递归
3.若未显式定义,编译器会生成默认拷贝函数,默认构造函数会按内存储存字节进行字节序拷贝,这种拷贝称为浅拷贝/值拷贝,这种方式有一个缺点,比如说当你初始化一个字符串s1,然后初始化一个s2,如果你执行s1=s2这个操作,那当你改变s1里元素的时候,s2里元素也会跟着改变,这还有一个问题,因为类是有析构函数的,当你程序结束的时候,这个位置会被析构两次,程序就崩了
4.编译器自动生成的默认拷贝构造函数中,内置类型是使用字节拷贝构造的,而自定义类型是调用自定义类型的拷贝构造函数进行拷贝

//拷贝构造
string(const string& str)
	:_size(strlen(str._str))
	,_str(new char[1])
{
	delete[] _str;
	_capacity = _size;
	char* tmp = new char[_capacity + 1];
	strcpy(tmp, str._str);
	_str = tmp;
}

若没有这个自定义函数,两个不同对象的_str会指向同一块空间,动其中一个对象就会影响到另外一个对象。
5.关于什么时候需要写拷贝构造:如果涉及到资源的申请就需要写拷贝构造函数进行深拷贝,否则只需要用编译器自动生成的浅拷贝即可。

应用场景

1.使用已创建对象初始化新对象

string str1;//旧对象
string str2(str1);

2.函数参数类型为类类型对象

void Func(string str);//会调用拷贝构造

3.函数返回值类型为类类型对象

string func()
{
	string str;
	return str;
}

注:为了提高传参效率,能传引用就尽量不要用传值调用。

运算符重载

特点

用法

函数名字:operator后接需要重载的运算符符号
函数原型:返回值 operator 需要重载的运算符符号(参数列表)
下图用日期类Date作为例子

ostream& operator<<(ostream& out,Date& d1)
{
	out<<d1.year<<d1.month<<d1.day<<endl;
	return out;
}
注意

1.重载操作数必须有一个类类型参数
2.内置类型的运算符不能改变其含义,比如说内置类型的加减乘除,不能通过运算符重载改变它们的含义
3.作为类类型成员重载时,参数少1,有一个参数是隐藏的this指针
4.“*”“::”“sizeof”“?:”“.”这五个运算符不能重载
5.赋值运算符必须重载为类的函数,不能放在全局变量里

Date& operator=(Date& d1,Date& d2)
{
	if(&d1!=&d2)
	{
		d1.year=d2.year;
		d1.month=d2.month;
		d1.day=d2.day;
	}
	return d1;
}

若你去测试这一行代码,你会发现vs编译器底下会报一个错: error C2801: “operator =”必须是非静态成员,原因是用户如果在类中没有显式实现一个赋值运算符重载,编译器会默认生成一个浅拷贝赋值运算符重载,这时如果用户在类外又实现一个运算符重载,就会与编译器中默认生成的函数冲突,所以赋值运算符只能是类内的函数。
6.如果没有涉及到资源拷贝,那么赋值运算符实现和不实现都可以,但一旦涉及到资源申请,就必须实现赋值运算符重载,否则会导致某一些指针指向同一块空间,这个时候当你操作其中一个对象就会影响到另外一个对象,而且有析构两次的问题(一个类里面的成员有包含别的类,没有进行深拷贝就会析构两次,造成程序崩溃)
7.前置++,–与后置++,–的问题:因为前置++和后置++运算符都一样,只是使用的位置不一样,为了区分这两种,c++规定前置++可以和平常的运算符重载一样使用,而若要实现后置++的运算符重载,就需要在参数列表里加一个int

Date operator++();//前置++
Date operator++(int)//后置++

const成员

概念

const修饰的成员函数统称为const成员函数,const修饰成员函数,实际上是修饰该成员函数的隐藏this指针,表明在该成员函数中不能对类的任何成员进行修改

class Date
{
public:
	void Print() const//等价于 void Print(const Date* this)
	{
		cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
	}
private:
	int _year;
	int _month;
	int _day;
}
特点

const成员函数可以调用const成员函数,但不能调用非const成员函数(读写权限被放大),而非const成员函数可以调用const成员函数和非const成员函数
const对象不能调用非const成员函数(读写权限放大),而非const对象两种都可以调用。

取地址运算符重载

一般不自己实现,编译器会自动实现,下图是日期类的一部分

Date* operator&()
{
	return this;
}
const Date* operator&() const
{
	return this;
}

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

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

相关文章

IP地址查询API接口怎么对接

IP地址查询API接口又叫IP归属地信息查询API接口&#xff0c;指的是根据IP地址查询归属地定位信息&#xff0c;包含国家、省、市、街道和运营商、区号、邮编、坐标等信息。那么IP地址查询API接口该怎么对接呢&#xff1f; 首先我们找到一家有做IP归属地信息查询API接口的服务商…

Python程序设计教案

文章目录&#xff1a; 一&#xff1a;软件环境安装 第一个软件&#xff1a;pycharm 第二个软件&#xff1a;thonny 第三个软件&#xff1a;IDIE&#xff08;自带的集成开发环境&#xff09; 二&#xff1a;相关 1.规范 2.关键字 3.Ascll码表 三&#xff1a;语法基础…

【学习】如何高效地进行集成测试

在软件开发的过程中&#xff0c;测试环节至关重要。而在这其中&#xff0c;集成测试更是保证软件质量的关键步骤之一。本文将探讨如何高效地进行集成测试&#xff0c;以确保软件的稳定性和可靠性。 一、什么是集成测试 集成测试是指在单元测试的基础上&#xff0c;将模块按照设…

JavaScript进阶知识点及案例(续)

编程思想 面向过程介绍 面向过程就是分析出解决问题所需要的步骤&#xff0c;然后用函数把这些步骤一步一步的实现&#xff0c;使用的时候再一个一个的依次调用就可以了 面向对象介绍 面向对象是把事务分解成为一个个对象&#xff0c;然后由对象之间分工与合作面向对象是以…

word导出或另存为pdf图片不清晰问题解决方案

问题描述&#xff1a; 使用word 2019导出pdf时图片不清晰&#xff0c;即使我已经在“选项 → \to →高级 → \to →图片大小和质量 → \to →不压缩文件中的图像 ”选项卡中关闭掉了图片压缩依然无效。 解决方案&#xff1a; 利用word foxit pdf 软件打印的方案转pdf。 &…

Linux加强篇-存储结构与管理硬盘(三)

目录 ⛳️推荐 磁盘容量配额 VDO虚拟数据优化 软硬方式链接 ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站 磁盘容量配额 使用磁盘容量配额服务来限制某位用户或某个用户组针…

Java 笔记 07:包机制,JavaDoc 文档的生成方式,Math 工具类,以及字符串连接符相关内容

一、前言 记录时间 [2024-04-25] 系列文章简摘&#xff1a; Java 笔记 01&#xff1a;Java 概述&#xff0c;MarkDown 常用语法整理 Java 笔记 04&#xff1a;Java 数据类型基础&#xff0c;数据类型转换&#xff0c;及其相关场景拓展 Java 笔记 05&#xff1a;变量和常量相关知…

第55篇:创建Nios II工程之Hello_World<一>

Q&#xff1a;本期我们开始介绍创建Platform Designer系统&#xff0c;并设计基于Nios II Processor的Hello_world工程。 A&#xff1a;设计流程和实验原理&#xff1a;需要用到的IP组件有Clock Source、Nios II Processor、On-Chip Memory、JTAG UART和System ID外设。Nios I…

Golang | Leetcode Golang题解之第48题旋转图像

题目&#xff1a; 题解&#xff1a; func rotate(matrix [][]int) {n : len(matrix)// 水平翻转for i : 0; i < n/2; i {matrix[i], matrix[n-1-i] matrix[n-1-i], matrix[i]}// 主对角线翻转for i : 0; i < n; i {for j : 0; j < i; j {matrix[i][j], matrix[j][i]…

2024采用JSP的酒店客房管理系统源代码+毕业设计论文+开题报告+答辩PPT

点击下载源码 摘 要 计算机技术发展至今已走过了半个多世纪之久&#xff0c;现在各个阶层、各个领域都使用着计算机&#xff0c;在这个快节奏的时代中它已经成为了社会生活的必需品。它的出现是现代社会进步&#xff0c;科技发展的标志。同时现代化的酒店组织庞大&#xff0c;…

C++: IO流

目录 1、C语言输入输出 流的概念&#xff1a; 2、CIO流 3、C文件IO流 1、C语言输入输出 C语言中我们用到的最频繁的输入输出方式就是scanf () 与 printf() 。 scanf(): 从标准输入设备 ( 键 盘 ) 读取数据&#xff0c;并将值存放在变量中 。 printf(): 将指定的文…

新能源汽车小米su7

小米su7汽车 function init() {const container document.querySelector( #container );camera new THREE.PerspectiveCamera( 20, window.innerWidth / window.innerHeight, 1, 50000 );camera.position.set( 0, 700, 7000 );scene new THREE.Scene();scene.background ne…

深入浅出 Spring Boot 3.x:从原理到实战,全面解锁 Java 后端开发新潮流

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;注册地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…

一分钟教会你使用51cto网课视频下载工具下载51cto视频

想要学习技术知识&#xff0c;提升自己的职业能力&#xff0c;51cto是一个绝佳的选择。然而&#xff0c;有时候我们可能无法随时在线观看这些精彩的视频课程。别担心&#xff01;我将在一分钟内教您如何使用51cto视频下载工具&#xff0c;将这些宝贵的学习资源下载到您的设备上…

物联网鸿蒙实训解决方案

一、建设背景 在数字化浪潮汹涌的时代&#xff0c;华为鸿蒙系统以其前瞻的技术视野和创新的开发理念&#xff0c;成为了引领行业发展的风向标。 据华为开发者大会2023&#xff08;HDC. Together&#xff09;公布的数据&#xff0c;鸿蒙生态系统展现出了强劲的发展动力&#x…

钡铼IOy系列模块在无人值守智能仓库中的成功运用,提升仓储物流效率

随着科技的不断发展&#xff0c;无人值守智能仓库正成为现代物流行业的一个重要趋势。在这个快节奏的时代&#xff0c;提升仓储物流效率是企业追求的目标之一。钡铼IOy系列模块为无人值守智能仓库的成功运作提供了关键支持。本文将探讨钡铼IOy系列模块在无人值守智能仓库中的应…

子域名如何启用HTTPS,有免费泛域名SSL证书吗

如今HTTPS已经成为了网站标配&#xff0c;然而&#xff0c;对于一些刚刚起步的网站或是个人博客而言&#xff0c;如何自动跳转到HTTPS&#xff0c;以及免费SSL证书的获取&#xff0c;可能还是一个需要解决的问题。下面就来详细解答这两个问题。 我们需要明确HTTPS与SSL之间的关…

OpenAI 和 Moderna 合作,推进 mRNA 医学

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、关于 Moderna Moderna 是 mRNA 医学领域的佼佼者&#xff0c;其通过不断推动 mRNA 技术的发展&#xff0c;正在重塑药物的制造方式&#xff0c;并深刻地改变我们治疗和预防疾病的方法。凭借在科学、…

包装类简单认识泛型

文章目录 包装类基本数据类型和对应的包装类装箱和拆箱自动装箱和自动拆箱 什么是泛型引出泛型语法 泛型类的使用 包装类 在Java中&#xff0c;由于基本类型不是继承自Object&#xff0c;为了在泛型代码中可以支持基本类型&#xff0c;Java给每个基本类型都对应了一个包装类型…

骑砍2霸主MOD开发(6)-使用C#-Harmony修改本体游戏逻辑

一.C#-Harmony反射及动态注入 利用C#运行时环境的反射原理,实现对已加载DLL,未加载DLL中代码替换和前置后置插桩. C#依赖库下载地址:霸王•吕布 / CSharpHarmonyLib GitCodehttps://gitcode.net/qq_35829452/csharpharmonylib 根据实际运行.Net环境选择对应版本的0Harmony.dll…