【C++】类和对象(三)

前言

📚作者简介:爱编程的小马,是一名大厂后端c++程序员。

📚本文收录于C++系列,本专栏主要是分享我所了解的c++知识,带领大家慢慢从了解c++到认识c++,持续更新!

📚相关专栏Linux正在发展,敬请期待!

📚本文主要内容:认识类和对象六个默认成员函数

目录

1.类的6个默认成员函数

2.拷贝构造函数

[2.1 定义](#2.1 定义)

[2.2 特征](#2.2 特征)

3.赋值运算符重载

[3.1 定义](#3.1 定义)

[3.2 特性](#3.2 特性)

4.取地址重载函数

[4.1 定义](#4.1 定义)

[4.2 特性](#4.2 特性)

总结


1.类的6个默认成员函数

如果一个类中什么成员都没有,简称为空类。空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员 函数。默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。

分为构造函数,析构函数,拷贝构造函数,赋值重载函数,取地址重载函数(两个,一个是普通对象,一个是const对象),今天介绍后面四个

2.拷贝构造函数

2.1 定义

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

2.2 特征

拷贝构造函数也是特殊的成员函数,其特征如下:

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

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

我先就这两点给大家举个例子

cpp 复制代码
class Date
{
public:
	//构造函数
	Date(int year =1 , int month =1, int day=1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//拷贝构造函数
	Date(Date& d)
	{
		_year = d._year;
		_month =d._month;
		_day = d._day;
	}

	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
private:
	//内置类型
	int _year;
	int _month;
	int _day;
};

int main()
{
	//构造函数什么时候会调用,类实例化一个新的对象就是之前没有的
	Date d1(2024, 8, 2);
	//什么时候会调用拷贝构造,第一就是函数传参,第二就是用已经存在的对象
	//去实例化一个新的对象
	Date d2 (d1);
	d1.Print();
	d2.Print();
	return 0;
}

3、如果拷贝构造函数没有显式定义,编译器就会生成一个默认的拷贝构造函数,默认的拷贝构造函数是浅拷贝。

大家看,我把拷贝构造函数屏蔽了,还是可以用d1去初始化d2,那拷贝构造没有什么存在的意义呀,那编译器自己就能把拷贝构造写出来并且可以使用,其实不是这样的,编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,还需要自己显式实现吗? 当然像日期类这样的类是没必要的。那么下面的栈类呢?验证一下试试?

代码崩了,我调试给大家找找原因,这块难度比较大,我讲解详细一些。

同一块空间,释放两次,是不是就崩了?这就是C++为了补C语言浅拷贝(值拷贝)的一个坑,C++用了一个拷贝构造函数来解决问题,就是你函数传参之前,先去调用拷贝构造函数完成深拷贝,再调用函数完成功能。这块的深拷贝怎么写?

cpp 复制代码
Stack(Stack& s)
	{
		STDataType* tmp = (STDataType*)malloc(sizeof(STDataType) * s._size);
		_a = tmp;
		memcpy(_a, s._a, sizeof(STDataType) * s._size);
		_size = s._size;
		_capacity = s._capacity;
	}

思路:重新开辟一个新的空间,将原空间的内容拷贝过来,即可。

5. 拷贝构造函数典型调用场景:

使用已存在对象创建新对象

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

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

3.赋值运算符重载

3.1 定义

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

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

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

3.2 特性

1. 赋值运算符重载格式

参数类型:const T&,传递引用可以提高传参效率

返回值类型:T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值 检测是否自己给自己赋值

cpp 复制代码
//拷贝构造函数
	Date(Date& d)
	{
		_year = d._year;
		_month =d._month;
		_day = d._day;
	}
	//赋值重载函数
	Date& operator = (const Date & d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
		return *this;
	}

2. 赋值运算符只能重载成类的成员函数不能重载成全局函数

是因为定义为全局函数,编译器会产生调用歧义。

大家可能觉得,有了拷贝构造,这俩功能不是一样吗?为什么要需要复制重载呢?其实是下面这个原因:

3、用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。注 意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符 重载完成赋值。

4.取地址重载函数

4.1 定义

返回类的地址

4.2 特性

1、一个是普通对象,一个是const对象

2、这两个默认成员函数一般不用重新定义 ,编译器默认会生成。

3、这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需 要重载,比如想让别人获取到指定的内容!

日期类简单代码:

cpp 复制代码
class Date
{
public:
	//构造函数
	Date(int year =1 , int month =1, int day=1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//拷贝构造函数
	Date(Date& d)
	{
		_year = d._year;
		_month =d._month;
		_day = d._day;
	}
	//赋值重载函数
	Date& operator = (const Date & d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
		return *this;
	}
	//取地址重载函数
	Date* operator& ()
	{
		return nullptr;
	}

	const Date* operator& ()const
	{
		return this;
	}
	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
private:
	//内置类型
	int _year;
	int _month;
	int _day;
};

int main()
{
	const Date d1(2024, 8, 2);
	Date d3(2023, 7, 4);
	Date d4(2010, 7, 4);
	cout << d1.operator& () << endl;;
	cout<<&d3<<endl;
	cout << &d4 << endl;
	return 0;
}

总结

今天介绍了拷贝构造函数,赋值重载函数,取地址重载函数(两个,一个是普通对象,一个是const对象),明天给大家更新完整的日期类,学到这个地方就算入门了。

如果这份博客对大家有帮助,希望各位给小马一个大大的点赞鼓励一下,如果喜欢,请收藏一下,谢谢大家!!!

制作不易,如果大家有什么疑问或给小马的意见,欢迎评论区留言

相关推荐
XiaoLeisj2 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
励志成为嵌入式工程师3 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉3 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer3 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq3 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
记录成长java5 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
前端青山5 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
青花瓷5 小时前
C++__XCode工程中Debug版本库向Release版本库的切换
c++·xcode
睡觉谁叫~~~5 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust
音徽编程5 小时前
Rust异步运行时框架tokio保姆级教程
开发语言·网络·rust