【C++课程学习】:类和对象(拷贝构造和运算符重载)

news2024/11/24 11:31:23

🎁个人主页:我们的五年

🔍系列专栏:C++课程学习

🎉欢迎大家点赞👍评论📝收藏⭐文章

 

目录

✍拷贝构造:

🍉特点一:

🍉特点二:

🍉特点三:

🍉特点四:

拷贝构造函数三种调用场景:

✍运算符重载:

🍭赋值运算符重载:

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


 

前言:

前面已经学过默认成员函数,但是只讲了构造函数和析构函数。这篇文章就来讲一讲剩下的两个默认成员函数:拷贝构造函数和赋值运算符重载。

拷贝构造函数也是属于构造函数的,只是拷贝构造是用另外一个对象里的数据给新创建的对象赋值。

✍拷贝构造:

拷贝构造:

拷贝构造只有一个和要创建的对象同类型的参数的引用,而且一般用const修饰,因为这个参数只要读取权限就可以了。因为他属于构造函数,所以我们传参时满足这一特点,编译器就会调用这个构造函数。

🍉特点一:

拷贝构造是构造函数的一种重载形式。


🍉特点二:

拷贝构造的参数只有一个,并且一定要是同类型的对象的引用。

比如:

Data (const Data& d){

        ……

}


🍉特点三:

如果是传值拷贝构造,那么就会发生无穷递归。

看看下面的错误示范:

#include<iostream>
using namespace std;

class Data {
public:
	Data(int year, int month, int day) {
		_year = year;
		_month = month;
		_day = day;
	}
	Data(const Data d) {
		//……
	}
private:
	int _year=1;
	int _month=1;
	int _day=1;
};
int main()
{
	Data a(2024,6,11);
	Data b(a);
	return 0;
}

●b实例化的时候,就会去调用拷贝构造,然后把实参a传给形参d.

●但是传值要进行拷贝,调用d拷贝构造,把a拷贝给d。

●差不多每次传给另外一个参数,就要调用一次拷贝构造,这样就会一直重复下去。


🍉特点四:

如果我们不显式实现,因为也是属于默认成员函数,所以编译器会自己生成。编译器会自己生成,编译器自己生成的拷贝构造函数是按内存存储按字节序列进行拷贝的。这种拷贝叫浅拷贝,或者值拷贝。因为如果类的成员有的是指针,那也是拷贝同样的指针,这样是不行的。

自定义类型就是调用它的拷贝构造函数。

总结:

如果一个类有空间申请,那么一定要显式自己写拷贝构造函数。如果没有资源的清理,那么编译器生成的也是可以的。比如日期类就不要显式实现。

拷贝构造函数三种调用场景:

1.在创建新的对象的时候,参数是同类型对象的引用。

2.在传值传参的时候,也是要调用拷贝构造函数的。

3.当类类型作为返回值的时候,也是要调用拷贝构造函数的。

从上面的三种场景来看,日常我们可以不用传值就不要用传值。也就是尽可能的使用传引用,除非特殊情况一定要用传值。

✍运算符重载:

概念:

在类中,为了增强代码的可读性,C++中引入了运算符重载这一概念。因为是重载,所以我们也可以推断出,我们用一样的运算符,但是是不同的类型的时候,就会调用不同的函数。

运算符重载是特殊函数名的函数,有返回类型和参数,返回类型和参数与普通的函数差不多。

●函数名:operator+要重载的运算符。

●原型:返回类型    函数名(参数列表)。

●必须是已存在的运算符才能重载,比如>,<。@这个符号就不能进行运算符重载。

●重载操作符必须有一个类类型的参数。

●虽然看起来形参比操作对象少一个,其实是隐藏了一个this指针,this指针是指向最前面那个操作对象的。

●   .*       sizeof       ::     .     ?:        这五个运算符是不能进行重载的。

🍭赋值运算符重载:

赋值运算符重载的格式:

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

●返回类型:类型&(这个类类型的引用),返回引用是为了可以支持连续赋值,比如c=b=a,顺序是,先是a给b赋值,然后返回b,然后在b给c赋值。

●赋值运算符只能重载成类的成员函数,不能重载为全局函数。

因为如果重载为全局函数,这时候在类里面没有显示实现,所以编译器会自己生成一个赋值运算符。这样我们调用赋值的时候,编译器就不知道去调用哪个赋值函数。

●编译器自己生成的赋值运算符,对于内置类型,也是去按内存的字节序进行赋值。对应自定义类型,那么就去调用它的赋值运算符函数。

下面是日期类的显式赋值运算符重载:

#pragma once
#include<iostream>
#include<stdbool.h>
#include<assert.h>
#include<math.h>
using namespace std;
public:
	//全缺省的构造函数
	Data(int year = 1, int month = 1, int day = 1) {
		_year = year;
		_month = month;
		_day = day;
	}
	//拷贝构造函数
	Data(const Data& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	//赋值运算符重载
    Data& operator = (const Data& d) {
	_year = d._year;
	_month = d._month;
	_day = d._day;
	return *this;
}


	//析构函数
	~Data() {
		_year = -1;
		_month = -1;
		_day = -1;
	}
private:
	int _year;
	int _month;
	int _day;
};


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

先来说这两个的区别:

1.前置++:调用++函数以后,返回++之的值。

2.前置++:调佣++函数以后,返回++之的值。

因为这两个++的函数名都是operator++,为了构成区分,我们的C++祖师爷在后置++里面放了一个int参数,这样与前置++就可以构成函数重载;

因为前置++可以返回的++以后的值,所以我们++以后,就直接可以用引用返回。

但是后置++,返回的++之前的值,这样我们传值返回。

日期类的前置++和后置++:

#pragma once
#include<iostream>
#include<stdbool.h>
#include<assert.h>
#include<math.h>
using namespace std;

class Data {
	friend ostream& operator<<(ostream& out, Data& d);
	friend istream& operator>>(istream& in, Data& d);
public:
	//全缺省的构造函数
	Data(int year = 1, int month = 1, int day = 1) {
		_year = year;
		_month = month;
		_day = day;
	}
	//拷贝构造函数
	Data(const Data& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
    //+=运算符重载
    Data& operator+=(int day) {
    	if (day < 0)
	    {
		    return *this -= -day;
	    }
	    _day += day;
	    while (_day > GetDay(_year,_month))
	    {
		    _day -= GetDay(_year, _month);
		    _month++;
		    if (_month == 13)
		    {
			    _month = 1;
			    _year++;
		    }
	    }
	return *this;
    }

	//日期的前置++
	Data& operator++() {
	    return *this += 1;
    }

    //日期的后置++
    Data operator++(int) {
	    Data a = *this;
	    *this += 1;
	    return a;
    }
	Data operator++(int);

	//析构函数
	~Data() {
		_year = -1;
		_month = -1;
		_day = -1;
	}
private:
	int _year;
	int _month;
	int _day;
};


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

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

相关文章

实体类status属性使用枚举类型的步骤

1. 问题引出 当实体类的状态属性为Integer类型时&#xff0c;容易写错 2. 初步修改 把状态属性强制为某个类型&#xff0c;并且自定义一些可供选择的常量。 public class LessonStatus {public static final LessonStatus NOT_LEARNED new LessonStatus(0,"未学习"…

高边坡监测规范:确保边坡安全的科学准则

随着土木工程建设的不断发展&#xff0c;高边坡作为常见的土方边坡形式&#xff0c;其安全问题日益受到人们的关注。高边坡监测规范作为保障边坡安全的重要手段&#xff0c;对于预防边坡滑坡、坍塌等地质灾害具有重要意义。本文将对高边坡监测规范进行深入探讨&#xff0c;以期…

微信小程序组件传值

虽然微信小程序是比较轻量的&#xff0c;但是还是拥有组件的 这是文件的基本目录 我们的代码基本都在pages和components文件夹中 在component中创建组件 在component中 &#xff0c;创建一个目录 我创建了一个 head目录 用于配置头部信息 我在这里创建了 一个头部组件&…

程序员,真有不变的技术和稳定的工作吗?

在程序员这个充满变化和创新的领域&#xff0c;很多人追求“稳定”的工作&#xff0c;认为找到一个合适的公司和岗位就能安心一辈子。然而&#xff0c;技术的快速更新迭代和市场需求的不断变化&#xff0c;使得真正的稳定变得越来越难以捉摸。作为程序员&#xff0c;我们需要反…

Java虚拟机 - JVM(类加载器、类加载的过程、双亲委派模型、GC垃圾回收)

一、JVM中数据内存区域划分 本地方法栈&#xff1a;里面保存的是native 关键字的方法&#xff0c;不是用Java写的&#xff0c;而是jvm内部用c实现的。 **程序计数器 和 虚拟机栈 每个线程都存在一份。 如果一个 JVM 进程 中有 10个 线程&#xff0c;那么就会存在 10份 程序计数…

通过文本指令生成3D模型纹理贴图

在3D建模的广阔领域中,我们总是追求更高效、更直观的方法来创建和编辑模型。今天,我要向大家介绍一种革新性的技术,它能够通过文本指令来精确地控制3D模型的细节,包括纹理贴图的生成。 1. 技术定位 这项技术主要定位于交互式3D建模领域,它为用户提供了一种全新的方式来创…

哈喽GPT-4o——对GPT-4o Prompt的思考与看法

目录 一、提示词二、提示词的优势1、提升理解能力2、增强专注力3、提高效率 三、什么样的算无效提示词&#xff1f;1、过于宽泛2、含糊不清3、太过复杂4、没有具体上下文5、缺乏明确目标6、过于开放7、使用专业术语但未定义8、缺乏相关性&#xff1a; 四、提示词正确的编写步骤…

Android 应用加固与重签名—使用AndroidStudio自带工具 apksigner

由 AndroidStudio 生成的release版本的app有自己的签名&#xff0c;但当应用加固后会删除原签名&#xff0c;需要重新签名。 一、加固方式&#xff1a; 使用基础版的腾讯云&#xff08;乐固&#xff09;进行免费加固&#xff0c;上传软件后等待在线加固完成后下载 apk 即可。…

设置SSHkeys多服务器免登录配置(ssh config)

一、背景&#xff1a; 多邮箱或者多git账号进行同一台电脑开发的情况。 有时候&#xff0c;开发时可能会面临一个情况&#xff0c;就是通过自己的电脑&#xff0c;可能同时需要开发多个不同地方的项目&#xff0c;或者说&#xff0c;自己建立的项目已经配置好SSH验证免密登录&a…

Qt C++ TCP服务端响应多客户端通讯

本示例使用的设备&#xff1a;WIFI无线4G网络RFID云读卡器远程网络开关物流网阅读器TTS语音-淘宝网 (taobao.com) #include "mainwindow.h" #include "ui_mainwindow.h" #include "QMessageBox" #include <QDebug> #include <exceptio…

【春秋云镜】Faculty Evaluation System未授权任意文件上传漏洞(CVE-2023-33440)

因为该靶场没有Write up,索性自己搞一下&#xff0c;方便别人&#xff0c;快乐自己&#xff01; 漏洞概述&#xff1a; Sourcecodester Faculty Evaluation System v1.0 is vulnerable to arbitrary code execution via /eval/ajax.php?actionsave_user. 漏洞复现&#xff…

Halcon 多相机统一坐标系

小杨说事-基于Halcon的多相机坐标系统一原理个人理解_多相机标定统一坐标系-CSDN博客 一、概述 最近在搞多相机标定等的相关问题&#xff0c;对于很大的场景&#xff0c;单个相机的视野是不够的&#xff0c;就必须要统一到一个坐标系下&#xff0c;因此我也用了4个相机&#…

SpringBoot Vue Bootstrap 旅游管理系统

SpringBoot Vue 旅游管理系统源码&#xff0c;附带环境安装&#xff0c;运行说明 源码地址 开发环境 jdk1.8,mysql8,nodejs16,navicat,idea 使用技术springboot mybatis vue bootstrap 部分功能截图预览

数据合规怎么做?哪些机构可以做数据合规

企业将数据资源入表的工作是一项复杂而全面的任务 财务部门负责统计数据资源的成本、销售数据等信息,并确保数据资源的会计处理符合会计要求&#xff1b; 数据部门则负责统计数据成本来源、价值实现路径等信息&#xff1b; 法务部门需要确认数据的收集和使用遵循相关的合规要求…

算法分析与设计期末考试复习

重点内容&#xff1a; 绪论&#xff1a; 简单的递推方程求解 1.19(1)(2) 、 教材例题 多个函数按照阶的大小排序 1.18 分治法&#xff1a; 分治法解决芯片测试问题 计算a^n的复杂度为logn的算法&#xff08;快速幂&#xff09; 分治法解决平面最近点对问…

基于遗传优化算法的风力机位置布局matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于遗传优化算法的风力机位置布局matlab仿真&#xff0c;风力机位置布局优化是风能转换系统设计中的一个重要环节&#xff0c;旨在最大化风场的整体发电效率。仿…

数字芯片——时钟与复位

关于此次章节我想要探讨的问题是门控时钟的处理&#xff08;Clock Gating Methodology&#xff09;和时钟复位策略。在低功耗设计中&#xff0c;门控时钟是结构最简洁&#xff0c;最容易实现的电路结构。如上期所讲的&#xff0c;一个控制信号和时钟逻辑与在一起输出的信号作用…

redis设计与实现(四)服务器中的数据库

服务器中的数据库 Redis服务器将所有数据库都保存在服务器状态server.h结构的db数组中&#xff0c;db数组的每个项都是一个redis.h/redisDb结构&#xff0c;每个redisDb结构代表一个数据库。 在初始化服务器时&#xff0c;程序会根据服务器状态的dbnum属性来决定应该创建多少…

产品人生(12):从“产品生命周期管理”看如何做“职业规划”

产品生命周期管理是产品人常接触的一个概念&#xff0c;它是一种全面管理产品从概念构想、设计开发、生产制造、市场推广、销售使用&#xff0c;直至最终退役的全生命周期过程的方法论和一系列业务流程。下面我们来简单介绍下产品生命周期管理&#xff1a; 概念阶段&#xff1a…

C++ | Leetcode C++题解之第145题二叉树的后序遍历

题目&#xff1a; 题解&#xff1a; class Solution { public:void addPath(vector<int> &vec, TreeNode *node) {int count 0;while (node ! nullptr) {count;vec.emplace_back(node->val);node node->right;}reverse(vec.end() - count, vec.end());}vect…