c++类和对象新手保姆级上手教学(中)

前言:

  类和对象中篇,这里讲到的前4个默认成员函数,是类和对象中的重难点,许多资料上的讲法都非常抽象,难以理解,所以我作出这篇总结,分享学习经验,以便日后复习。

目录

6个默认成员函数:

构造函数:

1.概念:

2.用法:

3.特性:

 析构函数:

1.概念:

2.用法:

 3.特性:

4.析构调用顺序练习:

拷贝构造函数:

1.概念:

2.用法:

3.特性:

运算符重载:

用法:

赋值重载:

前置++和后置++重载:

 取地址重载(不重要):

const成员函数:

 


6个默认成员函数:

什么是默认成员函数?

默认成员函数就是你不写编译器自己会自动生成的成员函数

前四个默认成员函数较为重要,后两个很少会自己实现,除非常特殊的情况下,基本上不会自己实现。

构造函数:

1.概念:

  想必大家再用c语言实现栈,链表等数据结构的时候,都会先写一个初始化函数,来初始化我们的数据,但在使用中有时往往会忘记初始化,所以C++就产生了构造函数。

构造函数的作用就是进行初始化

2.用法:

  那构造函数具体是怎样来使用的呢?举一个简单的案例,一个日期类的构造函数如下:

3.特性:

  构造函数的函数名和类名相同。

  无返回值。

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

  构造函数支持重载。

  建议写成全缺省。 

  一个类必须要有默认构造函数,如果你没有写,编译器会自己生成默认构造函数,但编译器默认生成的构造函数内置类型不作处理,自定义类型去调用它的默认构造函数。但在C++11中委员会可能认为对内置类型不作处理显得很呆,所以对这个语法打补丁,支持在声明处给缺省值:

这样编译器默认生成的构造函数就会对内置类型进行处理。 

  但大多数情况下,构造函数都是需要我们自己去实现的。

无参构造函数,全缺省构造函数,编译器默认生成的构造函数,都可以称为默认构造函数,但一个类默认构造函数只能有一个,建议写成全缺省,避免歧义。

 析构函数:

1.概念:

  如果说构造函数的功能时初始化,那么析构函数就像它的死对头:

析构函数负责清理资源的工作,防止内存泄漏。

 还是一样,我们在使用栈,链表等数据结构时最容易忘的就是用完后忘记清理空间,这将导致严重的后果,也就是内存泄漏,而C++中的析构函数可以有效解决这个问题。

2.用法:

由于我这个日期类不涉及动态资源,所以析构函数不必自己实现,但仍会调用:

 3.特性:

 函数名 = ~类名

 无返回值

 一个类只能有一个析构函数,如果不写编译器自己生成

 析构函数不能重载

 对象生命周期结束时,编译器自动调用析构函数

 对于编译器自己生成的析构函数,同样是内置类型不作处理,自定义类型调用它自己的析构函数。

4.析构调用顺序练习:

对于析构函数,其实头疼的是它的多个函数析构时的调用顺序,这里给大家一个公式,大家以后套公式即可:

局部对象(后定义先析构)->局部静态(后定义先析构)->全局对象(后定义先析构)

下面由浅入深来练习一下: 

练习1: 

#include<iostream>
using namespace std;
class Date
{
public:
	Date(int year=1,int month=1,int day=1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
	~Date()
	{
		cout << "调用析构" << _year << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1(1);
	Date d2(2);
	Date d3(3);
	return 0;
}

因为他们都是局部变量,遵循后定义先析构,所以:

练习2:

#include<iostream>
using namespace std;
class Date
{
public:
	Date(int year=1,int month=1,int day=1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
	~Date()
	{
		cout << "调用析构" << _year << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
Date d1(1);
Date d2(2);
Date d3(3);
int main()
{
	//Date d1(1);
	//Date d2(2);
	//Date d3(3);
	return 0;
}

 现在他们都变为全局变量,仍遵循后定义先析构:

练习3:

#include<iostream>
using namespace std;
class Date
{
public:
	Date(int year=1,int month=1,int day=1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
	~Date()
	{
		cout << "调用析构" << _year << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1(1);
	static Date d2(2);
	static Date d3(3);
	Date d4(4);
	return 0;
}

 现在,d2变成局部静态,根据公式,先局部对象再局部静态,内部仍然按照后定义先析构:

练习4:

#include<iostream>
using namespace std;
class Date
{
public:
	Date(int year=1,int month=1,int day=1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
	~Date()
	{
		cout << "调用析构" << _year << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
Date d5(5);
static Date d6(6);
Date d7(7);
static Date d8(8);
int main()
{
	Date d1(1);
	static Date d2(2);
	static Date d3(3);
	Date d4(4);
	return 0;
}

 先局部对象,再局部静态,最后全局,不管全局对象是否为静态,都遵循后定义先析构:

拷贝构造函数:

1.概念:

 在使用C++中,我们往往会需要将一个类拷贝到另一个相同类型的类中,而拷贝构造函数的作用就是:将该类拷贝到同类型的类中。

2.用法:

为了更严谨,也可以在此处加上const:

 

3.特性:

 函数名和类名相同

 无返回值

 形参部分传引用

 拷贝构造函数也是构造函数

 如果我们不写,编译器会默认生成,默认生成的拷贝构造函数对内置类型成员按内存存储按字节序拷贝,也就是浅拷贝,对自定义成员调用它的拷贝构造。

为什么形参部分必须传引用呢?

因为不传引用可能会引发无穷递归,看下面这个例子:

此时像上图一样使用拷贝构造函数,如果我们的拷贝构造函数是传值:

 

那就需要先调用拷贝构造,调用到拷贝构造时,因为是传值,所以需要将d1先拷贝到形参d,而将d1拷贝到形参d,就又需要调用新的拷贝构造,而新的拷贝构造又是传值,所以就这样一直递归下去,无穷无尽。

编译器默认生成的拷贝构造会拷贝内置类型,那么是不是意味着我们不需要自己实现拷贝构造?

不!!!

编译器默认生成的拷贝构造只能进行浅拷贝。

当我们有一个栈,里面有一个指针,指向了一片空间,当我们还是浅拷贝,用编译器默认生成的拷贝构造函数的话,它就会原原本本的将指针的拷贝到新的指针中,这就导致这篇空间有两个指针指向它,而不是像我们预想的一样,拷贝一块新空间,所以当要进行深拷贝时,我们需要自己来写拷贝构造函数 

所以写拷贝构造时,浅拷贝不需要写,只有有动态资源开辟的,才需要自己写拷贝构造。

运算符重载:

关键字:operator

用法:

将函数名改成operator加需要重载的运算符

在c语言中,对于内置类型我们可以直接用<  >  =  +  -  等符号进行运算,但如果我们要对自定义类型进行运算的话,就需要自己写函数来实现。

如果用运算符重载的话,将大大提高代码的可读性,比如我们实现一个判断两个日期类是否相同,重载==:

重载成成员函数:

重载成全局函数: 

 用法:

显而易见,第三种方法最实用,大大提高了代码的可读性 。

赋值重载:

这里的内容涉及的运算符重载,建议先跳到运算符重载,再来学习这段。

区分拷贝和赋值:

众所周知自定义类型是不能直接用等号连接进行赋值的,那么就需要进行运算符重载;

赋值重载和拷贝构造类似,但赋值重载是支持连续赋值的:

注意赋值重载只能重载成成员函数。 

前置++和后置++重载:

前置++和后置++这两个运算符一模一样,但是作用效果却不同,为了不产生歧义,该如何进行重载呢?

前置++:

用法:

后置++: 

用法 :

可见为了和前置++区分开来,后置++强制增加了一个形参int 来区分。 

 取地址重载(不重要):

主要是对对象进行取地址操作,编译器自己生成的已经完全够用,没有必要再自己写,除非有特殊需求:

const成员函数:

如果我们希望某个成员函数不能对成员变量进行修改时,我们可以进行const修饰:

用法: 

我们可以对不用对成员变量进行修改的成员函数进行const修饰,增加代码的严谨性。如果const修饰的成员函数对成员变量进行了修改,编译器会报错:

C++类和对象中篇到此结束,这篇是最难也是最重要的一篇,下篇我会陆续更新进行收尾。 

 

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

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

相关文章

新算法UoT助力AI提问——主动寻求信息,任务完成率提高57.8%

引言&#xff1a;信息寻求在不确定性环境中的重要性 在不确定性环境中&#xff0c;信息寻求的能力至关重要。在许多实际应用中&#xff0c;如医学诊断和故障排除&#xff0c;解决任务所需的信息并非一开始就给出&#xff0c;而需要通过提问后续问题来主动寻求&#xff08;例如…

MobaXterm的SFTP文件上传/下载

一、MobaXterm的简介 MobaXterm是一款功能强大的远程计算工具&#xff0c;集成了诸多网络工具和便利功能&#xff0c;包括SSH、X11服务器、SFTP等&#xff0c;支持Windows系统。用户可以使用MobaXterm来轻松管理远程服务器&#xff0c;进行文件传输&#xff0c;远程桌面显示等操…

Rocky 8.9 Kubespray v2.24.0 在线部署 kubernetes v1.28.6 集群

文章目录 1. 简介2. 预备条件3. 基础配置3.1 配置hostname3.2 配置互信 4. 配置部署环境4.1 在线安装docker4.2 启动容器 kubespray4.3 编写 inventory.ini4.4 关闭防火墙、swap、selinux4.5 配置内核模块 5. 部署 1. 简介 kubespray​ 是一个用于部署和管理 Kubernetes 集群的…

掌握array_walk()函数:解锁PHP数组操作的神奇力量!

掌握array_walk()函数&#xff1a;解锁PHP数组操作的神奇力量&#xff01; 在 PHP 开发过程中&#xff0c;我们经常需要对数组进行遍历和处理。array_walk() 函数是 PHP 函数库中的一个重要工具&#xff0c;它提供了一种便捷的方式来对数组中的每个元素执行自定义操作。本文将深…

【EI会议征稿通知】2024年第四届计算机视觉与模式分析国际学术大会(ICCPA 2024)

2024年第四届计算机视觉与模式分析国际学术大会&#xff08;ICCPA 2024&#xff09; 2024 4th International Conference on Computer Vision and Pattern Analysis (ICCPA 2024) 第四届计算机视觉与模式分析国际会议&#xff08;ICCPA 2024&#xff09;将于2024年5月17日至1…

Unity编辑器扩展之是否勾选Text组件BestFit选项工具(此篇教程也可以操作其他组件的属性)

想要批量化是否勾选项目预制体资源中Text组件BestFit属性&#xff08;此篇教程也可以操作其他组件的属性&#xff0c;只不过需要修改其中对应的代码&#xff09;&#xff0c;可以采用以下步骤。 1、在项目的Editor文件中&#xff0c;新建一个名为TextBestFitBatchProcessor的…

忘记管理员密码

1、在/home/jenkins/config.xml中删除&#xff1a; <useSecurity>true</useSecurity><authorizationStrategy class"hudson.security.FullControlOnceLoggedInAuthorizationStrategy"><denyAnonymousReadAccess>false</denyAnonymousRea…

html+css+jquery实现轮播图自动切换、左右切换、点击切换

pc端也好、移动端也好&#xff0c;轮播图很常见&#xff0c;今天用htmlcssjquery实现小米商城轮播图&#xff0c;套UI框架更容易实现 步骤1&#xff1a;把静态轮播图用divcss布局出来&#xff0c;采用盒子模型、相对绝对定位实现 代码如下&#xff1a; <!doctype html>…

leetcode:无重复字符的最长字串(详解)

文章目录 一、题目描述&#xff1f;二、题解方案一&#xff1a;容易理解&#xff08;时间复杂度O(n)&#xff09;方案二&#xff1a;滑动窗口&#xff08;时间复杂度O(n)&#xff09; 一、题目描述&#xff1f; 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最…

十二:枚举与注解

文章目录 01、枚举类的使用1.1、枚举类的理解1.2、自定义枚举类1.3、使用enum关键字定义枚举类1.4、Enum类中的常用方法1.5、使用enum关键字定义的枚举类实现接口 02、注解的使用2.1、注解的理解2.3、如何自定义注解2.4、jdk中4个基本的元注解的使用12.5、jdk中4个基本的元注解…

补-代码随想录第23天|● 669. 修剪二叉搜索树 ● 108.将有序数组转换为二叉搜索树 ● 538.把二叉搜索树转换为累加树

二叉树最后一天 ● 669. 修剪二叉搜索树思路一&#xff1a;递归递归三部曲代码&#xff1a; 思路二&#xff1a;迭代代码&#xff1a; ● 108.将有序数组转换为二叉搜索树思路&#xff1a;递归代码;[左闭右闭] ● 538.把二叉搜索树转换为累加树思路&#xff1a;递归 代码&#…

java基础训练题(2)

一、题目 1. 以下程序输出&#xff08;D&#xff09; public static void main(String[] args) {int num 2;switch (num) {case 1:num;case 2:num;case 3:num;default:num;break;}System.out.println(num);} } A&#xff1a;2 B&#xff1a;3 C&#xff1a;4 D&#xff…

解决本地googleapis 谷歌统计 nodejs 遇到 ECONNRESET和 ETIMEDOUT

在本地通过谷歌分析接口, 获取网站的访问量统计, 用于在管理端面板世界地图显示 获取分析数据的部分代码,这部分很简单示例有 // 获得前10个页面浏览量与页面标题在过去30天 const {BetaAnalyticsDataClient} require(google-analytics/data); const analyticsDataClient ne…

62-JS-canvas画布高斯模糊之图像操作

将一张图片放到canvas画布上 1.绘制图像drawImage <img src="./3.webp" alt=""><canvas></canvas><script>var canvas = document.getElementsByTagName("canvas")[0];canvas.width = 500;canvas.height = 500;var a …

“薪”的一年程序员裁员潮技术变革情况下 程序员就业机会在哪里?

引言&#xff1a;一对来自中国的工程师夫妻在美国的不幸身亡&#xff0c;疑似与谷歌的裁员有关&#xff0c;这一事件再次引发了人们对技术变革下裁员对程序员影响的关注。 一、针对裁员潮的一些看法 在我看来&#xff0c;技术变革对程序员的影响是双面的。一方面&#xff0c;…

anomalib1.0学习纪实-续3:结合python lightning理思路

一、python lightning python lightning是个好东西&#xff0c;但不见得那么友好。 GPT4给我讲解了他的用法&#xff1a; 二、anomalib的思路 1、 创建一个Lightning Module。 首先&#xff0c;在src\anomalib\models\components\base\anomaly_module.py中&#xff0c; cl…

你真的了解—————NumPy吗

&#x1f308;个人主页&#xff1a;小田爱学编程 &#x1f525; 系列专栏&#xff1a;opencv &#x1f3c6;&#x1f3c6;关注博主&#xff0c;随时获取更多关于IT的优质内容&#xff01;&#x1f3c6;&#x1f3c6; &#x1f600;欢迎来到小田代码世界~ &#x1f601; 喜欢的…

2024-02-19(Flume,DataX)

1.flume中拦截器的作用&#xff1a;个人认为就是修改或者删除事件中的信息&#xff08;处理一下事件&#xff09;。 2.一些拦截器 Host Interceptor&#xff0c;Timestamp Interceptor&#xff0c;Static Interceptor&#xff0c;UUID Interceptor&#xff0c;Search and Rep…

Docker从入门到上天系列第一篇:Docker开篇介绍

&#x1f609;&#x1f609; 欢迎加入我们的学习交流群呀&#xff01; ✅✅1&#xff1a;这是孙哥suns给大家的福利&#xff01; ✨✨2&#xff1a;我们免费分享Netty、Dubbo、k8s、Mybatis、Spring、Security、Docker、Grpc、消息中间件、Rpc、SpringCloud等等很多应用和源码级…

如何在iStoreOS软路由系统中安装cpolar实现公网远程本地电脑桌面

文章目录 简介一、配置远程桌面公网地址二、家中使用永久固定地址 访问公司电脑**具体操作方法是&#xff1a;** 简介 软路由是PC的硬件加上路由系统来实现路由器的功能&#xff0c;也可以说是使用软件达成路由功能的路由器。 使用软路由控制局域网内计算机的好处&#xff1a…
最新文章