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:构造函数与对象
第一章:构造函数揭秘 —— 创造者的第一次触碰 构造函数,顾名思义,是用于创建和初始化对象的特殊方法。它没有返回类型,名字与类名一致。构造函数是对象诞生的第一步,也是最至关重要的一步。让我们通过一个生动的例子…...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...
macOS 终端智能代理检测
🧠 终端智能代理检测:自动判断是否需要设置代理访问 GitHub 在开发中,使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新,例如: fatal: unable to access https://github.com/ohmyzsh/oh…...
篇章二 论坛系统——系统设计
目录 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 1. 数据库设计 1.1 数据库名: forum db 1.2 表的设计 1.3 编写SQL 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 通过需求分析获得概念类并结合业务实现过程中的技术需要&#x…...
Linux-进程间的通信
1、IPC: Inter Process Communication(进程间通信): 由于每个进程在操作系统中有独立的地址空间,它们不能像线程那样直接访问彼此的内存,所以必须通过某种方式进行通信。 常见的 IPC 方式包括&#…...
