C++ --> 类和对象(二)
前言
在前面简单的介绍了OOP,什么是类,在类中的this指针。接下来就深入理解类和对象。
默认成员函数
- 默认构造函数:用于在创建对象时初始化对象的成员变量。
- 默认拷贝构造函数:用于使用已存在的对象来初始化新创建的对象。
- 默认析构函数:在对象生命周期结束时执行清理操作,通常是删除动态分配的资源。
- 默认重载赋值运算符:用于将一个对象的值赋给另一个已存在的对象。
- 默认移动构造函数(C++11及以后版本):用于将资源从一个对象转移到另一个对象,而不是复制这些资源。
- 默认重载移动赋值操作符(C++11及以后版本):用于将一个对象的资源移动到另一个已存在的对象
接下来就依次介绍默认成员函数
一、构造函数
构造函数的特性
构造函数类似于初始化函数,在写Stack时候,首先需要初始化Stack。
构造函数并不是开辟空间创建对象,而是初始化
- 函数名与类名相同
- 无返回值
- 对象实例化时编译器自动调用构造函数
- 构造函数可以重载
class Date
{
public://构造函数Date() //无参构造函数{}Date(int year , int month , int day ) //带参构造函数{_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};int main()
{Date d0;//调用无参数构造 初始化的值是随机值Date d1(2024, 7.1, 8);//调用带参构造d1.Print();return 0;
}
注意:在调用无参构造函数,初始化时候是随机值。
- 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦 用户显式定义编译器将不再生成。
class Date
{
public://Date(int year, int month, int day)//{// _year = year;// _month = month;// _day = day;//}
private:int _year;int _month;int _day;
};int main()
{Date d0;Date d1;d1.Print();return 0;
}
- 在这段代码中,没有显示定义构造函数,那么编译器就会生成一个默认构造函数.
- 如果显示定义(即将代码取消注释),那么 d0 d1将没有可调用的默认构造函数 .
注意:在 (C++11) 中,针对内置类型不初始化打了补丁,成员变量在声明的时候可以给默认值
class Date
{
private:int _year = 1;int _month = 1;int _day = 1;
};
-
无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为 是默认构造函数。
//无参构造函数
Date(int year, int month, int day)
{_year = year;_month = month;_day = day;
}
//全缺省构造函数
Date(int year = 1, int month = 1, int day = 1)
{_year = year;_month = month;_day = day;
}
小结
- 一般情况下,构造函数自己写
- 内置类型都有缺省值,并且符合我们的要求可以不写构造函数
- 类成员变量均为自定义类型(这些均有自己的构造函数),会调用他们自己的构造函数.
二、析构函数
析构函数的特性
- 析构函数名是类名前面加“~”
- 无返回值
- 在一个类中,如析构函数未显示定义,将自动生成.
- 不可以重载
- 对象生命周期结束时候C++编译系统自动调用析构函数
//在这里面以以 Stack 为例
class Stack
{~Stack(){free(_a);_a = nullptr;}
private:int* _a;int _capacity;int _size;
};
- 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如 Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类。
小结
- 内置类型不做任何处理,调用其自己的析构函数.
- 动态申请资源,就要显示定义析构函数.
- 没有动态申请资源可以不写析构函数.
三、拷贝构造函数
拷贝构造函数的特性
- 只有单个形参数,一般用const修饰.
- const修饰是为了防止赋值错误:例如:本应该_year = year 却写成了year = _year;
- 拷贝构造是析构函数的重载形式.
- 参数只有一个,且是类类型对象的引用
- 自定义传值调用C++编译器调用其拷贝构造函数.
- 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错, 因为会引发无穷递归调用
class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}// DateP(const Date d); 错误示范Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}
private:int _year;int _month;int _day;
};int main()
{Date d1(2024,7,9);Date d2(d1);return 0;
}
注意 : 如果拷贝构造函数不加引用,会发生无穷递归. 函数在传值调用会调用拷贝构造函数,如其函数不加入引用(即传值调用),就会发生无限递归.
- 若未显示定义拷贝构造函数,编译器自动生成.
- 内置类型完成值拷贝(浅拷贝)
- 自定义类型会调用它自己的拷贝构造。
深浅拷贝
浅拷贝:浅拷贝是指复制对象时只复制其基本数据类型成员和指针成员,而不复制指针所指向的内存内容
深拷贝:深拷贝则是在复制对象时,不仅复制基本数据类型成员和指针成员,还会为指针所指向的内存内容分配新的内存空间,并将原有内容复制过去。
四、赋值运算符重载(关键字:operator)
运算符重载
运算符重载的概念
- 运算符重载是一项允许开发者为用户自定义的数据类型(如类)定义运算符的特性。
- 通过运算符重载,可以使自定义类型的对象能够使用类似于内置类型的运算符进行操作,从而提高代码的可读性和自然性。
- 运算符重载实质上是函数重载的一种特殊形式,重载的函数通过关键字
operator后跟要重载的运算符符号来命名。
运算符重载的规则
- 运算符重载的限制:C++不允许创建新的运算符,只能对已存在的运算符进行重载。重载运算符不能改变运算符的优先级和结合性,也不能改变运算符操作数的个数及语法结构。
- 运算符重载的实现方式:运算符重载可以通过类的成员函数或非成员函数(通常作为友元函数)来实现。成员函数形式的运算符重载通常用于双目运算符,因为它们可以省略一个参数(即隐含的
this指针)。非成员函数形式的运算符重载则适用于不涉及类对象或需要对称操作的场合。 - 运算符重载的设计原则:重载运算符应该保持其操作的直觉性,避免产生歧义。例如,重载加号运算符(
+)应该执行加法操作,而不是其他操作。
注意:
- 作为类成员函数重载,其形参操作数少一个,形参的第一个参数隐含的this指针。
- (.*)(: :)(sizeof)(? : :)(.)这五种不可以重载。
赋值运算符重载
重载格式:
- 参数类型:const T&,传递引用可以提高传参效率
- 返回值类型:T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值 检测是否自己给自己赋值
- 返回*this :要复合连续赋值的含义
重载注意:
- 赋值运算符重载不能是全局函数,它必须是类的成员函数。
- 重载赋值运算符时,应当考虑异常安全性,确保即使在赋值过程中发生异常,也不会留下半更新的状态。
- 重载赋值运算符时,可以选择返回
const引用,以避免在赋值后对当前对象进行不必要的修改。
class Date
{
public :Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date (const Date& d){_year = d._year;_month = d._month;_day = d._day;}//赋值运算符重载 Date& operator=(const Date& d)//返回this,用来连续赋值。{if(this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}
private:int _year ;int _month ;int _day ;
};
- 赋值运算符只能重载成类的成员函数不能重载成全局函数(因为其属于默认成员函数)
赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现 一个全局的赋值运算符重载,就 和编译器在类中生成的默认赋值运算符重载冲突了,故赋值 运算符重载只能是类的成员函数。
- 用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。(浅拷贝)
单目运算符号(自增、自减)
自增
在下面的例子中:
前置:
- 前置++:返回+1之后的结果
- 注意:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率
后置:
- 前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载
- C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器 自动传递
- 注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存 一份,然后给this+1
- temp是临时对象,因此只能以值的方式返回,不能返回引用
// 前置++
Date& Date::operator++()
{return *this += 1;
}
// 后置++
Date Date::operator++(int)
{Date tmp; tmp += 1;return *this;
}
自减
在这里和前置++ 后置++ 思想一致。
// 后置--
Date Date::operator--(int)
{Date tmp;tmp -= 1;return *this;
}
// 前置--
Date& Date:: operator--()
{return *this -= 1;
}
相关文章:
C++ --> 类和对象(二)
前言 在前面简单的介绍了OOP,什么是类,在类中的this指针。接下来就深入理解类和对象。 默认成员函数 默认构造函数:用于在创建对象时初始化对象的成员变量。默认拷贝构造函数:用于使用已存在的对象来初始化新创建的对象。默认析构…...
利用宝塔安装一套linux开发环境
更新yum,并且更换阿里镜像源 删除yum文件 cd /etc/yum.repos.d/ 进入yum核心目录 ls sun.repo rm -rf * 删除之前配置的本地源 ls 配置阿里镜像源 wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo 配置扩展包 wge…...
VB 实例:掌握 Visual Basic 编程的精髓
VB 实例:掌握 Visual Basic 编程的精髓 引言 Visual Basic(简称VB)是一种由微软开发的高级编程语言,它结合了易于使用的界面和强大的编程功能,使得初学者和专业人士都能快速开发Windows桌面应用程序。本文将通过一系列实例,深入探讨VB编程的基础知识和高级技巧,帮助读…...
层次分析法:matlab代码实现
计算权重: 一、算术平均法 关于矩阵: 1、矩阵的输入写法 [ ; ; ]同行用空格或逗号隔开,不同行用分号间隔 2、矩阵求和 默认按列求和 asum(E) 等同于 asum(E,1) 得到行向量 按行求和 asum(E,2) 得到列向量 对整个矩阵求和 asum(E,"all&…...
07-7.5.3 处理冲突的方法
👋 Hi, I’m Beast Cheng 👀 I’m interested in photography, hiking, landscape… 🌱 I’m currently learning python, javascript, kotlin… 📫 How to reach me --> 458290771qq.com 喜欢《数据结构》部分笔记的小伙伴可以…...
几何距离与函数距离:解锁数据空间中的奥秘
几何距离:直观的空间度量 几何距离,顾名思义,是我们在几何学中熟悉的距离概念,如欧几里得距离、曼哈顿距离和切比雪夫距离等。这些距离度量直接反映了数据点在多维空间中的位置关系。 欧几里得距离:最为人熟知的几何距…...
LabVIEW的Actor Framework (AF) 结构介绍
LabVIEW的Actor Framework (AF) 是一种高级架构,用于开发并发、可扩展和模块化的应用程序。通过面向对象编程(OOP)和消息传递机制,AF结构实现了高效的任务管理和数据处理。其主要特点包括并发执行、动态可扩展性和强大的错误处理能…...
gitlab 搭建使用
1. 硬件要求 ##CPU 4 核心500用户 8 核心1000用户 ##内存 4 G内存500用户 8 G内存1000用户 2. 下载 链接 3. 安装依赖 yum -y install curl openssh-server postfix wget 4. 安装gitlab组件 yum -y localinstall gitlab-ce-15.9.3-ce.0.el7.x86_64.rpm 5. 修改配置文…...
探索JT808协议在车辆远程视频监控系统中的应用
一、部标JT808协议概述 随着物联网技术的迅猛发展,智能交通系统(ITS)已成为现代交通领域的重要组成部分。其中,车辆远程监控与管理技术作为ITS的核心技术之一,对于提升交通管理效率、保障道路安全具有重要意义。 JT8…...
视频使用操作说明书-T80005系列视频编码器如何对接海康NVR硬盘录像机,包括T80005系列高清HDMI编码器、4K超高清HDMI编码器
视频使用操作说明书-T80005系列视频编码器如何对接海康NVR硬盘录像机,包括T80005系列高清HDMI编码器、4K超高清HDMI编码器。 视频使用操作说明书-T80005系列视频编码器如何对接海康NVR硬盘录像机,包括T80005系列高清HDMI编码器、4K超高清HDMI编码器 同三…...
keep-alive缓存组件
keep-alive缓存组件是Vue.js中的一个特殊组件,主要用于缓存内部组件的数据状态,以提高应用的性能和用户体验。以下是关于keep-alive缓存组件的详细解析: 一、作用 缓存组件状态:当组件在<keep-alive>内部切换时࿰…...
Linux上如何安装ffmpeg视频处理软件
在Linux上安装ffmpeg需要以下步骤: 更新系统 在开始安装之前,首先需要更新系统以获取最新的软件包列表和版本。在终端中执行以下命令: sudo apt update sudo apt upgrade安装依赖库 ffmpeg依赖于一些库和工具,需要先安装它们。在…...
element如何实现自定义表头?
有时候我们需要实现自定义表头,例如表头里加按钮啥的,这时候就需要用到自定义表头,但是官方对自定义表头的使用写的还是比较简单,今天就来详细说说 在需要使用自定义表头的表头上使用:render-header来启用自定义表头: <el-table-column :render-header="button&…...
OTP防重放攻击
OTP本意是一次性口令,比如邮箱验证码,短信验证码,或者根据totp或者hotp生成的默认30秒一变的6位数字。 不过开发者要注意,必须要在验证成功后失效那个验证码,不然就会导致重放攻击。 对于邮箱验证码,服务器…...
Oracle数据库加密与安全
Wallet简介: Oracle Wallet(即内部加密技术TDE( Transparent DataEncryption) TDE是 Oracle10gR2中推出的一个新功能,使用时要保证Oracle版本是在10gR2或者以上 Wallet配置: 1.创建一个新目录,并指定为Wallet目录 /home/oracle…...
【YOLO格式的数据标签,目标检测】
标签为 YOLO 格式,每幅图像一个 *.txt 文件(如果图像中没有对象,则不需要 *.txt 文件)。*.txt 文件规格如下: 每个对象一行 每一行都是 class x_center y_center width height 格式。 边框坐标必须是 归一化的 xywh 格式&#x…...
Memcached内存碎片清理术:优化缓存性能的策略
标题:Memcached内存碎片清理术:优化缓存性能的策略 内存碎片是Memcached在长期运行过程中常见的问题,它会降低缓存效率并影响性能。作为高效的分布式内存缓存系统,Memcached提供了多种内存碎片整理策略。本文将详细介绍这些策略&…...
禁止使用存储过程
优质博文:IT-BLOG-CN 灵感来源 什么是存储过程 存储过程Stored Procedure是指为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户可通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行。 …...
Flink异常:org/apache/hadoop/hive/ql/parse/SemanticException
在flink项目中跑 上面这段代码出现如下这个异常, java.lang.NoClassDefFoundError: org/apache/thrift/TException 加上下面这个依赖后不报错 <dependency> <groupId>org.apache.thrift</groupId> <artifactId>libthrift</artifactId…...
Java:构造函数与对象
第一章:构造函数揭秘 —— 创造者的第一次触碰 构造函数,顾名思义,是用于创建和初始化对象的特殊方法。它没有返回类型,名字与类名一致。构造函数是对象诞生的第一步,也是最至关重要的一步。让我们通过一个生动的例子…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
