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

【c++初阶】类和对象②默认成员函数以及运算符重载初识

目录

​编辑

默认成员函数:

构造函数

构造函数的特性:

析构函数:

拷贝构造函数:

1. 拷贝构造函数是构造函数的一个重载形式。

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

默认生成的拷贝构造:

1.内置类型完成值拷贝

2. 若未显式定义,编译器会生成默认的拷贝构造函数。

3.拷贝构造函数的典型引用场景

默认赋值运算符

c++运算符重载

赋值:赋值运算符的重载:


默认成员函数:

对于上篇文章中讲解中所使用的类,一般正常使用是没有问题的,但是如果我们在使用某些类的时候,,比如我们的日期类使用时,忘记或者没有进行初始化会发生什么样的问题呢:

现象是编译通过,但是成员变量都是随机值。 严重一点可能会崩溃。

为了解决这个问题,C++中引入了构造函数:

构造函数

是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证 每个数据成员都有 一个合适的初始值,并且在对象整个生命周期内只调用一次。

构造函数的特性:

构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任 务并不是开空间创建对象,而是初始化对象。 其特征如下:

1. 函数名与类名相同。

2. 无返回值。

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

4. 构造函数可以重载。

5. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦 用户显式定义编译器将不再生成。

两个默认构造函数的功能和Init函数的功能是一模一样的,但是构造函数可以默认调用:

 如何调用带参数的构造函数呢:

在创建对象的时候自动调用,

 没有参数调用的时候不可以在对象名字后面加上括号

因为无法和函数声明区分开。

编写某认构造的时候可以使用缺省参数,和无参调用构成重载但是不可以同时存在,无参调用时二者会产生歧义:

Date(int year = 2025, int mouth = 1, int day = 1)
{_year = year;_mouth = mouth;_day = day;
}
//写一个构造函数的重载://Date()
//{
//	_year = 2025;
//	_mouth = 1;
//	_day = 1;
//}

通过上面的例子我们知道,如果我们不写构造函数,使用的时候也可以打印出值,不过是随机值,这就意味着在c++中如果我们不写构造函数应该是有构造函数的,接下来我们观察一个栈的实现类:

现象:队列没写构造函数但是调用了栈的构造函数,如果写一个int size正常应该是不初始化化,初始化的原因是编译器自己做了一些优化。所以这个行为是不确定的。

C语言将数据类型分为了内置类型和自定义类型,

内置类型:int char 指针等,所以Date* p是内置类型,因为是指针,指针的本质就是地址。

自定义类型:struct class enum等等。

某认生成构造函数:内置类型成员不做处理,自定义类型会去调用他的默认构造。

vs2022现象,当一个对象的成员变量中有自定义类型和内置类型的时候,都会去初始化,但是当只有内置类型的时候又不初始化,这是由于编译器的优化导致。

上述对于两种不同类型数据的区别对待使得学习c++这门语言有些冗余,于是在C++11中做了这样的补丁,对于成员变量允许这样操作:

但是,值得注意的是这里的几个成员变量在1这里依旧是声明,并没有因为初始化而变成定义

原因: 这在类中相当于还是图纸,只有当用这个类的类型实例化一个对象的时候才会开辟空间,这里的值理解成缺省值。编译器生成某认构造的时候就可以用了。

重点:无参的构造函数和全缺省的构造函数以及编译器自己生成的构造函数,都称为默认构造函数,并且默认构造函数只能有一个。 注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为 是默认构造函数。也就是不传参的都是默认构造函数。三个函数不能同时存在,否则有歧义。

总结:

1.一般情况下,我们都要自己写构造函数

2.成员都是自定义类型,或者声明时给了缺省值,可以考虑让编译器自己去生成构造函数。

析构函数:

 析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由 编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。

 特性 析构函数是特殊的成员函数,其特征如下:

1. 析构函数名是在类名前加上字符 ~。

2. 无参数无返回值类型。

3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构 函数不能重载

4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。

日期类实际上没有需要时释放的资源,可以看一下调用析构函数的过程:

~Date()
{cout << "data destory" << endl;
}

出了作用领域,,自动调用。 

对于栈的释放资源,析构函数是必要的,内存泄漏不会报错。

~Stack()
{free(_a);_capacity = _top = 0;_a = nullptr;
}

对象的开辟和销毁是由系统来进行的

编译器 生成的默认析构函数,对自定类型成员调用它的析构函数。对于栈类,我们不写析构函数,不会自己销毁,因为编译器不敢。对内置类型不做处理,对自定义类型调用其析构函数。

拷贝构造函数:

传参本质就是一个拷贝。

对于日期类的传参拷贝:

void Test(Date d)
{d.Print();
}int main()
{Date d1;Test(d1);

这是值拷贝也就是浅拷贝

对于栈类的传参如果也使用值拷贝:

可能会出现对一块空间进行多次释放的问题。

c++规定,自定义类型的对象拷贝的时候,调用一个函数,这个函数叫做拷贝构造。

Date d2(d1)  使用d1初始化d2也是拷贝构造。

1. 拷贝构造函数是构造函数的一个重载形式。

日期类的拷贝构造:

Date(Date& d)
{_year =d._year;_mouth = d._mouth;_day = d._day;
}

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

调用拷贝构造如果是传值传参的话又会引起拷贝构造。

所以会用传指针和传引用的方式。

c++规定自定义类型对象传参拷贝,必须经过拷贝构造。可以这么理解

但是引用传参和指针传参不会发生拷贝构造函数的调用。

关于栈类的拷贝,浅拷贝可能会引起析构的时候一块空间释放两次的问题,所以栈类一般定义为深拷贝:

Stack(Stack& stt)
{_a = (int*)malloc(sizeof(int) * stt._capacity);if (_a == nullptr){perror("malloc fail");exit(-1);}memcpy(_a, stt._a, sizeof(int) * stt._top);_top = stt._top;_capacity = stt._capacity;
}

对于队列类,我们没有写拷贝构造函数,自己调用了拷贝构造:

默认生成的拷贝构造:

1.内置类型完成值拷贝

自定义类型会调用这个成员的拷贝构造。(比如栈这种类型需要我们自己写一个深拷贝,浅拷贝可能会出问题)

  写拷贝构造的时候最好带上const修饰,否则会出现反向拷贝的情况。

2. 若未显式定义,编译器会生成默认的拷贝构造函数。

默认的拷贝构造函数对象按内存存储按 字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。

注意:在编译器生成的默认拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定 义类型是调用其拷贝构造函数完成拷贝的。

3.拷贝构造函数的典型引用场景

①使用已经存在的对象创建新对象

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

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

默认赋值运算符

对于“=”,也就是赋值运算符的运算,如果我们不显示实现编译器也会生成一个默认的。跟拷贝构造的行为类似,内置类型完成值拷贝,自定义类型调用它的赋值。stake类涉及空间开辟的情况,需要自己实现完成深层次拷贝,介绍赋值运算符之前,我们先要了解c++中的运算符重载。

c++运算符重载

对于+ - * /这样运算符内置类型可以直接使用,但是自定义类型不可以直接使用

int a = 1;

int b = 2;

c = a+ b;

但是 Date d1 Date d2

d1 == d2这样就不可以直接使用。

对于内置类型来说,编译器知道其类型的含义就可以进行比较,直接就转换成指令了

但是对于自定义类型来说,编译器不知道要按照什么样的规则来进行比较。

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

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

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

注意:

不能通过连接其他符号来创建新的操作符:比如operator@

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

用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义

作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐 藏的this

那么日期类的比较就可以这样来写,关于日期的比较不像自定义类型那些谁大就大,而是有一个比较逻辑,编译器是不能确定我们自己定义的类的比较逻辑的,无法统一所以就无法比较。

bool operator>(const Date& d1, const Date& d2)
{if (d1._year > d2._year){return true;}if (d1._year == d2._year && d1._mouth > d2._mouth){return true;}if (d1._year == d2._year && d1._mouth == d2._mouth && d1._day > d2._day){return true;}return false;}

此时的c++可以支持这样写;

 此时的使用就和我们的内置类型使用运算符感觉没有差异了。

当我们将这个函数的实现放在类里面就会报错:

因为还有一个隐藏的this指针,参数要和操作数匹配,所以这样修改:

bool operator==( const Date& d2)
{return _year == d2._year&& _mouth == d2._mouth&& _day == d2._day;
}
bool operator>( const Date& d2)
{if (_year > d2._year){return true;}if (_year == d2._year && _mouth > d2._mouth){return true;}if (_year == d2._year && _mouth == d2._mouth && _day > d2._day){return true;}return false;}

 调用时这样调用:

d1.operator>(d2);

可以重载那些运算符,主要看这个运算有没有意义,有意义就可以实现,没有意义就不要实现。

赋值:赋值运算符的重载:

两个已经存在的对象进行拷贝。而拷贝构造是一个已经存在的对象去拷贝初始化另外一个对象。

Date& operator=(const Date&d)
{if (this != &d){_year = d._year;_mouth = d._mouth;_day = d._day;}return *this;}

赋值函数是一个默认构造函数,operate= 我们不写编译器会默认生成一个。行为跟拷贝构造类型,对内置类型完成值拷贝,对自定义类型完成他的赋值。date可以不写,myqueque1不写,栈要写,完成深度拷贝。

以上就是c++中的默认成员函数以及支持的默认行为。下一篇文章将介绍c++中的运算符重载

相关文章:

【c++初阶】类和对象②默认成员函数以及运算符重载初识

目录 ​编辑 默认成员函数&#xff1a; 构造函数 构造函数的特性&#xff1a; 析构函数&#xff1a; 拷贝构造函数&#xff1a; 1. 拷贝构造函数是构造函数的一个重载形式。 2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用&#xff0c;使用传值方式编译器直接报…...

【做一个微信小程序】校园地图页面实现

前言 上一个教程我们实现了小程序的一些的功能&#xff0c;有背景渐变色&#xff0c;发布功能有的呢&#xff0c;已支持图片上传功能&#xff0c;表情和投票功能开发中&#xff08;请期待&#xff09;。下面是一个更高级的微信小程序实现&#xff0c;包含以下功能&#xff1a;…...

成熟开发者需具备的能力

精业务 • 指深入理解和熟悉所开发软件的业务逻辑和需求。 • 开发者需要明确软件要解决的问题、面向的用户群体以及核心功能等。 • 精业务有助于开发者更好地设计系统架构、编写符合业务需求的代码&#xff0c;并能根据业务变化灵活调整开发计划。 懂原理 • 指掌握编程的基…...

计算机毕业设计--基于深度学习技术(Yolov11、v8、v7、v5)算法的高效人脸检测模型设计与实现(含Github代码+Web端在线体验界面)

基于深度学习技术&#xff08;Yolov11、v8、v7、v5&#xff09;算法的高效人脸检测模型 Yolo算法应用之《基于Yolo的花卉识别算法模型设计》&#xff0c;请参考这篇CSDN作品&#x1f447; 计算机毕业设计–基于深度学习技术&#xff08;Yolov11、v8、v7、v5&#xff09;算法的…...

力扣做题记录 (二叉树)

二叉树 打算先来了解二叉树基础&#xff0c;都是简单题&#xff0c;目的是熟悉代码格式和解题基础思路。 1、二叉树最大深度 二叉树最大深度 方法一、深度搜索 直接用原函数做递归&#xff0c;比较简单 /*** Definition for a binary tree node.* struct TreeNode {* …...

机试刷题_字符串的排列【python】

题目&#xff1a;字符串的排列 from os import dup # # 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可 # # # param str string字符串 # return string字符串一维数组 # class Solution:def backtrack(self,res,state,choi…...

百度智能云—千帆 ModelBuilder API的简单调用(Java)

百度简介 百度&#xff08;Baidu&#xff09;是拥有强大互联网基础的领先AI公司。百度愿景是&#xff1a;成为最懂用户&#xff0c;并能帮助人们成长的全球顶级高科技公司。 “百度”二字&#xff0c;来自于八百年前南宋词人辛弃疾的一句词&#xff1a;众里寻他千百度。这句话…...

unity学习43:子状态机 sub-state machine

目录 1sub-state machine子状态机 1.1 创建 sub-state machine 1.2 sub-state machine 内容 1.3 子状态机的应用 2 子状态机不同于blend tree的嵌套 3 应用例子&#xff1a;若角色拿不同武器的动画设计&#xff0c;可以使用2种方法 3.1 在1个图层layer里&#xff0c;使用…...

Qt MainWindow

文章目录 0. 概述1. 菜单栏 QMenuBar1.1 例子1&#xff0c;使用图形化界面1.2 例子2&#xff0c;使用代码创建1.3 例子3&#xff0c;添加快捷键1.4 例子4&#xff0c;添加子菜单1.5 例子5&#xff0c;添加分割线和图标1.6 内存泄漏问题 2. 工具栏 QToolBar2.1 例子1&#xff0c…...

GDB QUICK REFERENCE (GDB 快速参考手册)

GDB QUICK REFERENCE {GDB 快速参考手册} References GDB QUICK REFERENCE GDB Version 4 https://users.ece.utexas.edu/~adnan/gdb-refcard.pdf 查看方式&#xff1a;在新标签页中打开图片 References [1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/ [2] gdb-refc…...

【数据结构】 栈和队列

在计算机科学的世界里&#xff0c;数据结构是构建高效算法的基础。栈&#xff08;Stack&#xff09;和队列&#xff08;Queue&#xff09;作为两种基本且重要的数据结构&#xff0c;在软件开发、算法设计等众多领域都有着广泛的应用。今天&#xff0c;我们就来深入探讨一下栈和…...

AI视频创作教程:如何用AI让古画动起来。

事情缘由&#xff1a; 如果是简单的图&#xff0c;找原图直接写提示词即可。 如果碰到多人多活动的图&#xff0c;直接出的效果会很不好&#xff0c;那么该怎么做呢&#xff1f; 图片分模块 首先&#xff0c;复杂部分的图&#xff0c;把长图分多个模块。 比如这张图&#xff0…...

撕碎QT面具(1):Tab Widget转到某个Tab页

笔者未系统学过C语法&#xff0c;仅有Java基础&#xff0c;具体写法仿照于大模型以及其它博客。自我感觉&#xff0c;如果会一门对象语言&#xff0c;没必要先刻意学C&#xff0c;因为自己具有对象语言的基础&#xff0c;等需要用什么再学也不迟。毕竟不是专门学C去搞算法。 1…...

DeepSeek24小时写作机器人,持续创作高质量文案

内容创作已成为企业、自媒体和创作者的核心竞争力。面对海量的内容需求&#xff0c;人工创作效率低、成本高、质量参差不齐等问题日益凸显。如何在有限时间内产出高质量内容&#xff1f;DeepSeek写作机器人&#xff0c;一款24小时持续创作的智能工具&#xff0c;为企业和个人提…...

npm安装依赖(npm install)时遇到认证错误的解决方案

问题描述 在使用 npm install 安装依赖时遇到以下错误&#xff1a; npm error code E401 npm error Incorrect or missing password.解决方案 方案一&#xff1a;使用淘宝&#xff08;或其它国内公共&#xff09;镜像&#xff08;如果已经是淘宝镜像跳过此步&#xff09; 设…...

SpringBoot+微信小程序+数据可视化的宠物到家喂宠服务(程序+论文+讲解+安装+调试+售后等)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统介绍 在经济高速发展、物质生活极大丰富的当下&#xff0c;人们的精神需求愈发凸显&#xff0…...

免费大模型网站

腾讯元宝 腾讯元宝 秘塔搜索 秘塔搜索 超算互联网 超算互联网回答速度很慢 Chatbot Arena Chatbot Arena 大模型竞技场。...

OpenCV的主要模块

OpenCV的模块...

使用 Python 爬虫和 FFmpeg 爬取 B 站高清视频

以下是一个完整的 Python 爬虫代码示例&#xff0c;用于爬取 B 站视频并使用 FFmpeg 合成高清视频。 1. 准备工作 确保安装了以下 Python 库和工具&#xff1a; bash复制 pip install requests moviepy2. 爬取视频和音频文件 B 站的视频和音频文件通常是分开存储的&#x…...

Retrieval-Augmented Generation for LargeLanguage Models: A Survey

标题&#xff1a;Retrieval-Augmented Generation for Large Language Models: A Survey 作者&#xff1a;Yunfan Gaoa , Yun Xiongb , Xinyu Gaob , Kangxiang Jiab , Jinliu Panb , Yuxi Bic , Yi Daia , Jiawei Suna , Meng Wangc , and Haofen Wang 1. By referencing ext…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...

API网关Kong的鉴权与限流:高并发场景下的核心实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中&#xff0c;API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关&#xff0c;Kong凭借其插件化架构…...

软件工程 期末复习

瀑布模型&#xff1a;计划 螺旋模型&#xff1a;风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合&#xff1a;模块内部功能紧密 模块之间依赖程度小 高内聚&#xff1a;指的是一个模块内部的功能应该紧密相关。换句话说&#xff0c;一个模块应当只实现单一的功能…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例

目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码&#xff1a;冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...

倒装芯片凸点成型工艺

UBM&#xff08;Under Bump Metallization&#xff09;与Bump&#xff08;焊球&#xff09;形成工艺流程。我们可以将整张流程图分为三大阶段来理解&#xff1a; &#x1f527; 一、UBM&#xff08;Under Bump Metallization&#xff09;工艺流程&#xff08;黄色区域&#xff…...