当前位置: 首页 > news >正文

7.C++面向对象3(拷贝构造函数,赋值运算符重载)

⭐本篇为C++学习第7章,主要了解 拷贝构造函数,赋值运算符重载

⭐本人Gitee C++代码仓库:yzc的c++学习: 小川c++的学习记录 - Gitee.com 

上篇讲了6个默认成员函数的构造函数和析构函数。

重要代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;class Date
{
public:Date(int year = 0, int month = 0, int day = 0){_year = year;_month = month;_day = day;}~Date(){}void print(){cout << _year << "/" << _month << "/" << _day << endl;}
private:int _year;int _month;int _day;
};int main()
{return 0;
}

一. 拷贝构造函数

a 拷贝构造函数是构造函数的一个重载,用于对象的拷贝并且初始化

如: 

Data d1(2024,10,1);
Data d2(d1);

b 拷贝构造函数在的参数只有一个且必须使用引用传参,传值会导致无穷递归调用

c 如果用户没有显示定义,编译器会生成默认的拷贝构造函数,但这个函数以内存存储,字节序进行浅拷贝

若使用按值传参会导致无穷递归调用

如:

这是因为传参的时候,需要调用拷贝构造函数对参数进行拷贝,又需要调用拷贝构造函数

正确写法如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;class Date
{
public:Date(int year = 0, int month = 0, int day = 0){_year = year;_month = month;_day = day;}Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}~Date(){}void print(){cout << _year << "/" << _month << "/" << _day << endl;}
private:int _year;int _month;int _day;
};int main()
{Date d1(2024, 10, 11);Date d2(d1);d1.print();d2.print();return 0;
}

 使用引用传参可以防止无穷递归问题,再使用const可以防止修改d中的内容

运行结果如下:

和析构函数一样,拷贝构造函数也存在深浅拷贝问题。

如果我们在堆上申请空间,并且使用了浅拷贝。这就会导致同一块地址空间被析构两次而报错

二. 运算符重载

2.1 其他运算符重载

在了解赋值运算符重载之前要知道什么是运算符重载。

c++为了增强代码可读性引入了运算符重载,运算符重载也是一种函数

函数原型: 返回值类型 operator 运算符符号

运算符符号:如 + - * / == > < 等

为什么要有运算符重载??

        比如我们定义了一个日期类,如何判读两个日期对象是否相等??如何比较两个日期的大小??

如:

很明显需要我们需要自己定义 == 来完成这个功能

==运算符重载

 所以我们很容易写出下面的函数原型,但是这是错误的!

	bool operator==(const Date& d1, const Date& d2){}

因为我们调用的方式是 d1 == d2

        d1 == d2 明显是d1去调用==这个函数来判断和d2是否相等,所以d1已经被this指针传入了,我们无需再传入

正确方法如下:

	bool operator==(const Date& d){//通过this指针来传入第一个参数return this->_year = d._year&& this->_month = d._month&& this->_day = d._day;}

测试

>运算符重载

	bool operator > (const Data& d){if (_year > d._year)return true;else if (_year == d._year && _month > d._month)return true;else if (_year == d._year && _month == d._month && _day > d._day)return true;elsereturn false; }

有了==运算符重载可以轻易写入>运算符重载,体现了代码的复用

<运算符重载

由>运算符重载,我们能轻易写入<运算符重载

	bool operator<(const Date& d){if (_year < d._year)return true;else if (_year == d._year && _month < d._month)	//这里直接调用==重载符return true;else if (_year == d._year && _month == d._month && _day < d._day)return true;elsereturn false;}

2.2 赋值运算符重载

赋值运算符重载的意义是用一个对象赋值给另一个对象。

赋值运算符重载和拷贝构造函数要区分。

由于赋值运算符重载是6个默认成员函数之一,如果用户没有自定义,系统会按字节序进行浅拷贝

int main()
{Date d1(2024, 10, 11);Date d2(1, 1, 1);d2 = d1;	//赋值运算符重载,d2已经初始化Date d3(d1);//拷贝构造,d3还没有初始化return 0;
}
	void operator=(const Date& d){//如果this指向对象的地址和d的地址不一样才能进行赋值//如果地址一样说明二者相等(不仅仅是值相同,连内存地址都一样!),无需赋值//我们需要完成的是深拷贝,两个对象仅仅是值相同,内存地址不一样if (this != &d){this->_year = d._year;this->_month = d._month;this->_day = d._day;}}

简单测试:

但是上面代码还完美。比如我们经常有下列操作

按照上面的写法会报错,因为我们返回值是void

当(d2=d1)后执行 d3=void,这显然是不对的。我们需要返回d2才能完成 d3=d2

	//使用引用返回可以减少拷贝,增加效率Date& operator=(const Date& d){//如果this指向对象的地址和d的地址不一样才能进行赋值//如果地址一样说明二者相等(不仅仅是值相同,连内存地址都一样!),无需赋值if (this != &d){this->_year = d._year;this->_month = d._month;this->_day = d._day;}//this执行被赋值的对象,解引用就能找到它return *this;}

简单测试

可以看到,能够完成多次赋值

注意:

a.不能连接其他操作符构成新的操作符如operator@
b.重载操作符必须用于自定义类类型
c.用于内置类型的操作符,其含义不可改变,如+不能改变含义
d.作为类成员的重载函数时,其参数要少一个。由于有一个默认参数this
e.   .*	::	sizeof	:?	.  这五个操作符不可重载

三.下章重点

3.1 const成员

3.2 取地址重载 


http://www.mrgr.cn/news/47580.html

相关文章:

  • stackqueue
  • poi处理多选框进行勾选操作下载word以及多word文件压缩
  • istoreos安装tailscale命令
  • ISP各模块功能介绍
  • ffmpeg 编译遇到的坑
  • AI在软件工程教育中的应用与前景展望
  • Renesas R7FA8D1BH (Cortex®-M85) 上超声波测距模块(HC-SR04)驱动开发
  • Effective C++笔记之二十四:stack overflow
  • window.location.href和open的区别
  • QD1-P14 HTML常用标签:input输入标签
  • MySQL--事务(详解)
  • PGMP-00基础单词(1-25)
  • 数学基础 -- 三角函数极限之小数场景
  • 【.NET 8 实战--孢子记账--从单体到微服务】--角色(增加/删除/修改/查询)
  • React技术在Meta Connect 2024大会
  • LeetCode15.三数之和
  • 【cpp】 lambda 表达式常用笔记
  • ViT模型技术学习
  • 【部署篇】Redis-02单机部署
  • (27)QPSK信号在非相关平坦莱斯(Rician)衰落信道上的误码率性能MATLAB仿真
  • 点进HTML初步了解
  • JAVA开发中的常用通讯协议
  • Linux !ko/5.17-BBRplus AMD64(X86_64)内核致命的 futex_wait 函数死锁问题。
  • 力扣 前缀和
  • Java中的拦截器、过滤器及监听器
  • tcpdump深入浅出