IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 默认成员函数详解 -> 正文阅读

[C++知识库]默认成员函数详解


#### c++作为面向对象的编程语言,与c语言相比最大的一个特点就是类的使用,使数据与方法打包(变量与函数打包)在类中。而类中很重要的就是默认成员函数,默认成员函数是帮助我们更好处理对象与内存的一种方式,所以我们有必要充分的理解认识它们,这样才能使我们的代码更加流畅便捷易读。
#### 所谓默认成员函数,就是在一个空类中,即使我们什么都不写,编译器会自动生成的函数。但是我们也可以自己去写,实现我们想要做到的功能,这时候,编译器就会优先使用我们自己实现的默认成员函数。下面将重点介绍四个重要的默认成员函数。

一、构造函数

1.作用

####构造函数完成的是某一类的一个对象中成员变量的初始化工作。即在对象创建时,编译器就会自动调用构造函数,完成类中成员变量的初始化。

2.函数样式

####构造函数有两种要求,编译器才会将其作为构造函数
(1)函数名必须与类名相同
(2)函数无返回值(无返回值不代表是void,void表示有返回值,返回值为空)

//示例
class Date
{
public:
	Date(int year, int month, int day)  //初始化成员变量
	{ 
		_year = year;
		_month = month;
		_day = day;
	}
	private:
	int _year;
	int _month;
	int _day;
};

3.使用特点

(1)构造函数在创建对象的时候调用,分为两种调用方式,一种是传值调用,一种是默认值调用。
(2)给定值调用就是在创建对象时,我们将想要成员变量初始化的值当作参数传给构造函数,这个要求构造函数形参列表中必须有形参来接受实参。
(3)默认值调用就是指在创建对象的时候,我们不需要传参,在创建对象时直接给定某一默认值来初始化成员变量。这时候构造函数我们称为默认构造函数。
(4)默认构造函数:默认构造函数就是指不用传参就可以调用初始化成员变量的构造函数,一共有三种默认构造函数。
1.编译器自动生成的构造函数:这类构造函数是双标的,对于成员变量中的内置类型,它会不做任何处理,变量中仍然是随机值,而对于自定义类型(class、struct、union),编译器生成的构造函数就会调用该类型的默认构造函数(注意,一定是默认构造函数。因为你没传值,因此该自定义类型的成员变量就会去调用它的类型得到默认构造函数去初始化)
2.无参的构造函数:函数参数列表中没有参数
3.全缺省的默认构造函数:在参数列表中形参全缺省,因此在不传参的情况下就会使用缺省值来初始化成员变量。缺省的构造函数有一个好处,就是即支持传值调用,又支持默认值调用,可以在构造对象时传值来赋予想要的值

//1.不写编译器自动生成一个默认构造函数
//2.无参的函数
Date()
{
	_year = 2000;
	_month = 1;
	_day = 1;
}
//3.带有缺省值的构造函数
Date(int year = 2000, int month = 1, int day = 1)
{
	_year = year;
	_month = month;
	_day = day;
}
//构造函数的使用
int main()
{
	Date d1;	//这是使用默认构造函数,进行默认值的初始化
	Date d2(2021,7,22);	//这是进行传参的初始化
}

4.注意事项

(1)最推荐的构造函数类型是全缺省的,这样既可以传参按照自己的意愿初始化,又可以使用默认构造函数。
(2)每个类都必须有默认构造函数,自己不写就会由编译器自己生成一个,但是编译器自动生成的默认构造函数双标:内置类型不处理,自定义类型调用该类型的默认构造函数。因此可能编译器生成的这个不符合自己的需求。
(3)构造函数支持函数重载,这使得可以有多种初始化方式。

二、析构函数

1.作用

####析构函数完成的是在对象声明周期接受后自动调用进行资源的清理(开辟空间的释放等)不是完成对象的销毁。对象的销毁是在函数栈帧销毁时自动完成的,根本不需要认为处理。

2.函数样式

####析构函数要满足下面两个要求,编译器才会将它当作析构函数
(1)函数名为类名前加~
(2)函数无参,无返回值。

~Date()
{
	//资源的清理
}

3.使用特点

(1)析构函数在对象生命周期结束后自动调用
(2)析构函数有且仅有一个,如果为显示定义,那么作为类的默认成员函数,编译器会自动生成一个析构函数,但是这个析构函数也是双标的:对于内置类型,不会进行任何处理,对于自定义类型,则会调用它的析构函数。
(3)析构函数只有一个,无法函数重载。
(4)对于有些类,像成员变量只有int类型的日期类,析构函数就是什么用也没有,因此我们可以不用写,用编译器自己生成的就够了。但是对于动态开辟的内存的成员变量,那么我们必须自己写来释放内存,因为编译器自己生成的不会有释放空间这个功能。

4.注意事项

####因为对象都是在函数栈帧上开辟空间的,所以析构函数的顺序应该符合栈的后入先出,即:后创建的对象先析构。

三、拷贝构造函数

1.作用

####用已存在的对象来创建新对象,并且使新对象的值与已存在对象的值相同,类似于拷贝,因此称为拷贝构造。

2.函数样式

####满足以下条件,编译器才将其处理为拷贝构造函数。
(1)函数名与类名相同(与构造函数形成函数重载)
(2)函数参数只有一个,为同类型对象并且引用传参.传值传参会引发无穷递归。因为:在传值的时候,就需要用实参拷贝构造出形参,目的是实现拷贝构造,结果你在实现的过程中使用了拷贝构造,就会无穷递归

Date(const Date& d)
{
	_year = d.-year;
	_month = d._month;
	_day = d._day;
}

3.使用特点

(1)拷贝构造在创建新对象的时候自动调用
(2)在使用编译器自动生成的时候,对于内置类型会进行浅拷贝,对于自定义类型会调用该类型自己的拷贝构造函数。
(3)使用方式:

int main()
{
	Date d1(2021,7,21);
	Date d2 = d1;	//一种拷贝构造
	Date d2(d1)		//另一种拷贝构造
	return 0;
}

4.注意事项

####对于编译器默认生成的拷贝构造函数来说,完成的是浅拷贝。对于深浅拷贝问题,是一个比较大的问题,在这里我们暂且先知道,浅拷贝,就是无脑的将值毫无改变的赋值过去,然后就会出现一个问题,就是如果成员变量中有指针,那么指针存储的地址也是完全一样的,指向同一块空间,必然会出现一系列的问题,这个时候我们就需要自己写拷贝构造函数,来完成深拷贝。

四、复制运算符重载

1.作用

####这个函数的功能你可以认为就是对象之间的赋值,就和赋值运算符“ = ”对于内置类型的作用一样。

2.函数样式

####符合运算符重载的要求,同时为了支持连续赋值,所以返回值必须是该类型的引用。参数也是该类型的应用,并且因为不会改变内容,最好加const修饰

Date& operator=(const Data& d)
{
	_year = d._year;
	_month = d._month;
	_day = d._day;
}

3.使用特点

(1)当需要将一个对象的值给另一个对象的时候可以使用。
(2)自己不写,在使用编译器会自动生成,对于内置类型会进行浅拷贝,对于自定义类型会调用该类型自己的
赋值运算符重载函数。
(3)使用方式

int main()
{
	Date d1(2021,5,6);
	Date d2(2024,6,9);
	d2 = d1;
}

4.注意事项

(1)赋值重载与拷贝构造的机理完全类似,都会存在浅拷贝存在的问题,因此必要时,还是需要自己写赋值重载。
(2)不能通过连接其他符号来创建新的操作符:比如operator@。
(3)重载操作符必须有一个类类型或者枚举类型的操作数。
(4)用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不能改变其含义。
(5)作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的
操作符有一个默认的形参this,限定为第一个形参。
(6).* 、:: 、sizeof 、?: 、. 注意以上5个运算符不能重载。

总结

####其实还有两个默认成员函数没提到取地址及const取地址操作符重载但是这两个使用编译器默认生成的就足够了,完全没必要自己写,而且也十分简单。
####总结一下:默认成员函数都是自己不写编译器可以自己生成的,但是编译器生成的很难达到我们想要的那种效果。如:内置类型构造函数的初始化、浅拷贝问题因此我们要根据实际情况来实现默认成员函数。来为代码保驾护航。
####
####
####
####如有错误,请指正。谢谢!
####有问题请在评论区留言,我会尽力解答!

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-22 13:57:27  更:2021-07-22 13:57:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/6 12:10:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码