类和对象【C++】【中篇】

news2024/11/15 8:28:37

目录

一、类的6个默认成员函数

1、构造函数 

2、析构函数

3、拷贝构造函数 

4、赋值重载函数

二、赋值运算符重载 


一、类的6个默认成员函数

注意:默认成员函数不能在类外面定义成全局函数。因为类里没有的话会自动生成,就会产生冲突。 

1、构造函数 

对于下面这个程序,可以看到,每次创建对象时,我们都需要手动调用Init函数,这样是不是有些麻烦呢?

class Date
{
public:
	void Init(int year,int month,int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1;
	d1.Init(2023, 5, 1);
	d1.Print();

    Date d2;
	d2.Init(2023, 5, 2);
	d2.Print();
	return 0;
}

构造函数就可以很好地解决这个问题。

构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象是由编译器自动调用,以保证每个成员都有一个合适的初始值,并且在对象整个生命周期只调用一次。

其主要任务并不是开空间创建对象,而是初始化对象。

特征:

1、函数名与类名相同。

2、无返回值。(也不需要void)

3、对象实例化时编译器会自动调用对应的构造函数。

4、构造函数可以重载。

使用举例: 

class Date
{
public:
	//无参构造函数
	Date()
    {}
	//带参构造函数
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
    Date d1;//调用无参构造函数
	Date d2(2023, 5, 8);//调用有参的构造函数
	return 0;
}

注意:

1、如果通过无参构造函数创建对象时,对象后不用跟括号,否则就成了函数声明。

2、如果类中没有显示定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显示定义,编译器将不再生成。

3、编译器自动生成的默认构造函数,对内置类型不做处理(有些编译器可能会),对自定义类型成员则会调用它的默认构造。

一般情况下,有内置类型时,就需要自己写构造函数,如果全是自定义类型成员,就可以考虑让编译器自己生成。

在C++11中针对内置类型成员不初始化的缺陷,又打了补丁,即,内置类型成员变量在类中声明时可以给默认值。

4、无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。

2、析构函数

(1)概念

析构函数:是特殊的成员函数。与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象的销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中的资源管理

(2)特性 

1、析构函数名是在类名前加 ~

2、无参数无返回类型

3、一个类只能有一个析构函数,若未显示定义,系统自动生成默认的析构函数。

4、析构函数不能重载

5、对象生命周期结束时,C++编译系统自动调用析构函数。

1、一般情况下,有动态申请资源,就需要显示写析构函数释放资源

2、没有动态申请的资源,就不需要写析构

3、如果需要释放的资源的成员类型都是自定义类型,则不需要写析构 

3、拷贝构造函数 

(1)概念

拷贝构造函数:是特殊的成员函数,只有单个形参,该形参是对本类类型对象的引用(一般用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

(2)特征 

1、拷贝构造函数是构造函数的一个重载形式。

2、拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器会直接报错因为会引发无穷递归调用。

3、若未显示定义,编译器会生成默认的拷贝构造函数。默认拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。

class Date
{
public:
	Date(int year=1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d)
	{
		//this->_year = d._year;(d2的_year = d1的_year)
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1;
	Date d2(d1);
	return 0;
}

4、赋值重载函数

d1=d2;//d1.operator =(d2);

已经存在的两个对象之间复制拷贝。

注意:与拷贝构造函数不同的是,拷贝构造函数是用一个对象初始化另一个对象

 下面这个关于日期类的赋值重载函数有没有什么问题?

	void operator =(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
int main()
{
	Date d1(2023, 5, 8);//带参构造函数
	Date d2(d1);//拷贝构造函数,用一个已经存在的对象初始化另一个对象
	Date d3(d2);//拷贝构造函数
	//将d2赋值给d1,已经存在的两个对象的拷贝复制
	d1 = d2 = d3;
	return 0;
}

 在赋值时,如果是连续赋值,上面的函数就会有问题。

d1=d2=d3;

d3赋值给了d2后,应该有一个返回值,而我们上面写的函数的返回值是空。

	Date operator =(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
		return *this;//传值返回,返回的是对象的拷贝,不好
	}

如果像上面这样写,是传值返回,就需要再调用拷贝构造函数

因此,为了提高效率,我们可以将返回值改为引用。

	Date& operator =(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
		return *this;//因为出了作用域*this还在,所以可以用引用返回。
	}

上面的代码对于d1=d1;这样的代码是可以编译通过的,如果不想,可以按照如下写法:

	Date& operator =(const Date& d)
	{
        if(*this != &d)
        {
            _year = d._year;
		    _month = d._month;
		    _day = d._day;
        } 
		return *this;//因为出了作用域*this还在,所以可以用引用返回。
	}

默认生成的赋值重载函数跟拷贝构造一样:

1、内置类型成员:值拷贝/浅拷贝。

2、自定义类型成员会去调用它的赋值重载函数。 

二、赋值运算符重载 

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

函数名字:关键字operator后面接需要重载的运算符符号。

函数原型:返回值类型operator操作符(参数列表)

注意:

(1)不能通过其他连接符号来创建新的操作符。

(2)重载操作符必须有一个类类型参数。

(3)用于内置类型的运算符,其含义不能改变,如+

(4)作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this

(5)(.*)(::)(sizeof)(?:)(.)注意以上5个运算符不能重载,笔试选择题中经常出现。

class Date
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
	//bool operator == (Date* this,const Date& d2)
	bool operator ==(const Date& d2)
	{
		return _year == d2._year && _month == d2._month && _day == d2._day;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1, d2;
	d1.Init(2023, 5, 1);
	d2.Init(2023, 5, 2);
	if (d1 == d2)
	{
		printf("相等");
	}
	else
	{
		printf("不相等");
	}
	return 0;
}

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

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

相关文章

k8s采用ansible安装

一、准备工作 测试服务器 服务器配置进程功能备注192.168.0.189CPU:4核 内存32Gansibleansible一键安装k8s192.168.0.141CPU&#xff1a;12核 内存&#xff1a;10Gdocker&#xff0c;kube-apiserver&#xff0c;etcd&#xff0c;kube-scheduler&#xff0c;kube-controller-m…

产品经理 - 原型图设计软件

原型图设计软件哪个好用&#xff1f;6款好用软件推荐&#xff01; - 知乎 摩客, 墨刀 2014 即时设计是一款支持在线协作的专业级 UI 设计工具&#xff0c;用户数已突破230万&#xff1b; 2021年 5,000万(美元) 国外 axure 老牌 如果有进一步模拟的必要&#xff0c;再换用Ad…

JetPack之lifecycle原理分析

Lifecycle是什么 Lifecycle可以有效的避免内存泄漏和解决android生命周期的常见难题Livecycle 是一个表示android生命周期及状态的对象LivecycleOwner 用于连接有生命周期的对象&#xff0c;如activity,fragmentLivecycleObserver 用于观察查LifecycleOwnerLifecycle框架使用观…

关于SSL证书有效期缩短,看这一篇就够了

在TLS/SSL证书有效期不断被缩短的大趋势下&#xff0c;我们在前文和大家聊了聊企业面临的困境、应对策略及证书自动化管理&#xff0c;今天想和大家继续探讨的是TLS/SSL证书自动化管理切实可行的解决方案。 01 自动化证书管理的重要性 TLS/SSL证书是保障网络连接安全的重要手…

图片位深度以及转换办法

位图文件的格式&#xff1a; ① 位图文件头&#xff0c;所用结构体&#xff1a;BITMAPFILEHEADER&#xff0c;占14个字节 ② 位图信息头&#xff0c;所用结构体&#xff1a;BITMAPINFOHEADER&#xff0c;占40个字节 ③ 颜色表项&#xff0c;所用结构体&#xff1a;RGBQUAD&…

Qt5.14版本通用环境配置安装——最详细教学(看不懂,你怪我)

✨✨✨大家好&#xff0c;我是会飞的鱼-blog&#xff0c;今天我来给大家介绍一下Qt5.14.1安装&#xff0c;有不足之处&#xff0c;请大家多多指教。感谢大家支持&#xff01;&#xff01;&#xff01; 目录 前言 安装文件下载&#xff1a; 安装&#xff1a; 设置 QtCreator…

测试相关记录

1、提测计划、需求拆分、颗粒度 2、线上bug回顾 3、提测流水线 4、测试业绩合同指定

6.2.4图的基本操作 6.3.1图的广度优先遍历 6.3.2图的深度优先遍历

6.2.4图的基本操作 考研里面只考邻接矩阵和邻接表的存储结构 思想较为简单见video 重点理解时间复杂度的遍历原理 6.3.1图的广度优先遍历&#xff08;BFS&#xff09;&#xff08;Breadth first traversal&#xff09; 我们从树的广度优先遍历入手去看图的广度优先遍历的思想 …

【Python入门知识】NumPy 中的随机数及ufuncs函数

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 什么是随机数&#xff1f; 随机数并不意味着每次都有不同的数字。随机意味着无法在逻辑上预测的事物。 伪随机和真随机 计算机在程序上工作&#xff0c;程序是权威的指令集。 因此&#xff0c;这意味着必须有某种算法来…

2路 QSFP,40G 光纤的数据实时采集(5GByte/s 带宽)板卡设计原理图 -PCIE732

板卡概述 PCIE732 是一款基于 PCIE 总线架构的高性能数据传输卡&#xff0c;板卡具有 1 个 PCIex8 主机接口、2 个 QSFP40G 光纤接口&#xff0c;可以实现 2 路 QSFP 40G 光纤的数据实时采集、传输。板卡采用 Xilinx 的高性 能 Kintex UltraScale 系列 FPGA 作为实时处理器…

【鲁棒优化、无功优化】两阶段鲁棒优化的主动配电网动态无功优化【IEEE33节点】(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

网曝快手在离职证明上写:如需背调,只能通过公司指定邮箱,其他渠道均不认可!如何捍卫自己的权益?...

许多公司都喜欢用离职证明拿捏打工人&#xff0c;最近有网友曝光快手在离职证明上做文章&#xff0c;在离职证明上写&#xff1a;如需背调&#xff0c;只能通过公司指定邮箱xxxxkuaishou.com&#xff0c;其他渠道均不认可&#xff01; 楼主问&#xff1a;这种情况如何捍卫自己的…

camunda脚本如何使用

一、camunda脚本有什么用途 在Camunda中&#xff0c;脚本是一种灵活的方式&#xff0c;可以用于在流程定义和表单中编写自定义逻辑。使用脚本&#xff0c;您可以编写JavaScript、Groovy、Python、Ruby等脚本语言中的代码&#xff0c;以实现各种功能。 以下是Camunda脚本的一些…

Shell脚本快速入门

Shell脚本快速入门 1 Hello World2 Shell 变量3 Shell 传递参数4 Shell 基本运算符5 Shell echo命令5 Shell printf 命令6 Shell test 命令7 Shell 流程控制8 Shell 函数9 Shell 输入/输出重定向10 Shell 文件包含参考 1 Hello World 编写脚本文件 test.sh #!/bin/bash echo …

用思科和华为的设备分别完成【单臂路由】的配置

一 什么是单臂路由&#xff1a; 单臂路由&#xff08;router-on-a-stick&#xff09;是指在路由器的一个接口上通过配置子接口&#xff08;或“逻辑接口”&#xff0c;并不存在真正的物理接口&#xff09;的方式&#xff0c;实现原来相互隔离的不同VLAN&#xff08;虚拟…

并发编程06:volatile与JMM

文章目录 6.1 被volatile修饰的变量有两大特点6.2 内存屏障&#xff08;面试重点&#xff09;6.2.1 生活case6.2.2 是什么6.2.3 内存屏障分类6.2.4 困难内容 6.3 volatile特性6.3.1 保证可见性6.3.2 没有原子性6.3.3 指令禁重排 6.4 如何正确使用volatile6.5 本章最后的小总结6…

运算符重载三大补充(前置后置,操作数与参数顺序,指针参数权限),const修饰成员函数,对>> <<的重载与友元函数声明

TIPS 构造函数析构函数拷贝构造函数运算符重载赋值运算符重载当代码当中的运算符连接的全是内置类型的时候&#xff0c;由于内置类型&#xff0c;它是知道该怎么去进行运算的&#xff0c;所以说会直接转化为指令&#xff0c;然后但凡有一个不是内置类型&#xff0c;而是属于自…

JS 实现区块链添加可视化功能

JS 实现区块链添加可视化功能 学习的最后一部分了&#xff0c;完整的资源在这里&#xff1a;https://download.csdn.net/download/weixin_42938619/87765530&#xff0c;有需求的可以自取。 最后一部分是增加一些可视化的功能&#xff0c;完整实现后如下&#xff1a; HTML 部…

基于yolov7开发构建学生课堂行为检测识别系统

yolov7也是一款非常出众的目标检测模型&#xff0c;在我之前的文章中也有非常详细的教程系列的文章&#xff0c;感兴趣的话可以自行移步阅读即可。 《基于YOLOV7的桥梁基建裂缝检测》 《YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程》 《基于YOLOv7融合…

windows 编译 opencv

编译需要的基础工具 #cmake是配置构建工具&#xff0c;mingw是编译工具 cmake CMake是一款跨平台的编译管理工具&#xff0c;可以自动生成各种不同编译环境&#xff08;如Makefile、Visual Studio Solution等&#xff09;&#xff0c;从而实现在不同平台上进行代码编译的目的…