【小梦C嘎嘎——启航篇】类和对象(中篇)

【小梦C嘎嘎——启航篇】类和对象(中篇)😎

  • 前言🙌
    • 类的6个默认成员函数
      • 构造函数
      • 析构函数
      • 拷贝构造函数
        • 拷贝构造函数的特性有哪些?
        • 既然编译器可以自动生成一个拷贝构造函数,为什么我们还要自己设计实现呢???
        • 拷贝构造函数典型调用场景有哪些呢???
      • 运算符重载
        • 运算符重载需要注意的地方
      • 赋值运算符重载
        • 赋值运算符重载函数有哪些特性???
        • 为什么赋值重载函数只能重载成类成员函数不能重载成全局函数呢???
        • 既然编译器可以自动生成一个赋值重载函数了,为什么我们还要自己设计实现呢???
      • 前置++和后置++重载
        • 前置++:返回+1之后的结果
        • 后置++:
      • const 修饰的成员
        • const对象可以调用非const成员函数吗?非const对象可以调用const成员函数吗?const成员函数内可以调用其它的非const成员函数吗?非const成员函数内可以调用其它的const成员函数吗?
      • 取地址及const取地址操作符重载
  • 总结撒花💞

追梦之旅,你我同行

   
😎博客昵称:博客小梦
😊最喜欢的座右铭:全神贯注的上吧!!!
😊作者简介:一名热爱C/C++,算法等技术、喜爱运动、热爱K歌、敢于追梦的小博主!

😘博主小留言:哈喽!😄各位CSDN的uu们,我是你的博客好友小梦,希望我的文章可以给您带来一定的帮助,话不多说,文章推上!欢迎大家在评论区唠嗑指正,觉得好的话别忘了一键三连哦!😘
在这里插入图片描述

前言🙌

    哈喽各位友友们😊,我今天又学到了很多有趣的知识,现在迫不及待的想和大家分享一下!😘我仅已此文,分享有关 C++ 类和对象的相关知识 ~ 都是精华内容,可不要错过哟!!!😍😍😍

类的6个默认成员函数

构造函数

  • 构造函数是用来对对象初始化的,并非是为对象开辟空间的。
  • 构造函数的函数名与类名相同。
  • 无返回值类型,不用写void
  • 一个类中可以有多个构造函数,也就是构造函数是可以实现重载的。
  • 在定义对象时,会自动调用构造函数,对对象进行初始化操作。
  • 构造函数是类的默认成员函数,如果自己没有写,编译器会默认生成一个无参的构造函数。
  • 默认构造函数:无参的构造函数、全缺省的构造函数、自己没写编译器自动生成的构造函数。在一个类中,有且只有一个默认构造函数。当有多个时,会出现调用冲突。
  • 当要调用无参的构造函数时,定义对象时不要加(),例如Data d(),这样是错误的。这样编译器区分不清它是函数声明还是调用构造函数,产生二义性了。

析构函数

  • 析构函数是用来进行对对象资源的清理工作,而不是用来销毁对象,销毁对象是程序结束系统自动销毁回收空间的。
  • 析构函数的函数名与类名相同,前面加一个~。
  • 无返回值也无参数。
  • 一个类中只能有一个析构函数,不能实现重载。
  • 在程序结束时,编译器会自动先调用析构函数。
  • 构造函数是类的默认成员函数,如果自己没有写,编译器会默认生成一个无参的构造函数。

拷贝构造函数

什么是拷贝构造函数?顾名思义,就是完成对象的之间的拷贝。

拷贝构造函数的特性有哪些?

这里,我对拷贝构造函数总结为以下几点特性:

  • 拷贝构造函数是一种特殊的函数。

  • 拷贝构造函数其实就是构造函数的一个重载。

  • 如果没有显示的实现拷贝构造函数,编译器会自动生成默认拷贝构造函数供程序使用。

  • 一个已经存在的对象拷贝给一个还不存在的对象时,编译器会自动调用拷贝构造函数。

  • 一般在传值传参和传值返回中,会调用拷贝构造函数。

  • 拷贝构造函数函数列表中,有且只有一个参数,一般加上const修饰,且必须是本类类型对象的引用,如果不是引用的话会导致无限递归的问题。

既然编译器可以自动生成一个拷贝构造函数,为什么我们还要自己设计实现呢???

我的理解是:编译器生成的默认构造函数只能完成浅拷贝的工作而不能实现深拷贝,而我们在实际开发过程中有些场景是需要深拷贝才能够解决问题的。由于在C++中,默认拷贝构造函数对内置数据类型只完成值拷贝(浅拷贝),对于自定义类型会调用它们的拷贝构造函数。如果,我们实现的类只有内置类型成员变量,也就是说不涉及申请其他资源的,可以只使用编译器提供的默认拷贝构造函数就可以满足我们的需求,无需自己实现,例如Date类的实现就无需手搓拷贝构造函数。但是,如果我们需要申请其他资源,例如需要在堆区上申请空间资源等,则需要我们根据项目工程的实际场景进行手动实现拷贝构造函数,完成深拷贝。例如,我们进行栈类的实现,如果不进行深拷贝的话,会出现多次释放同一块空间资源的问题,从而报错。

拷贝构造函数典型调用场景有哪些呢???

  • 使用已经存在的对象去创建新对象
  • 函数参数类型是类类型对象
  • 函数返回值类型是类类型对象

如果一个类对象所占空间越大,拷贝所带来的消耗就越大。因此,一般在传参时,能够用引用作为参数就使用引用传参;在返回时,能够使用引用返回就不用船只返回。这样可以减少拷贝次数,提高程序的效率。

运算符重载

赋值运算符重载是运算符重载的一种。其实我们也可以不用运算符重载,写一个函数也能实现我们的需求。但是,使用运算符重载可以大大提高代码的可读性。

运算符重载需要注意的地方

  • 不能通过连接其他符号来创建新的操作符:比如operator@
  • 重载操作符必须有一个类类型参数
  • 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
  • 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
  • .* :: sizeof ? : . 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。

赋值运算符重载

赋值运算符重载函数有哪些特性???

  1. 从其函数格式可以看出,其基本格式:返回值类型 operator= (参数列表)。从提高效率来看,一般设计为引用返回即 T&。函数的参数列表中必须有一个本类类型的参数,最好实现为const T & 。赋值重砸函数有返回值的原因其实是为了连续赋值的需求。返回的是*this,以满足连续赋值的需求
  2. 一般没有自己给自己赋值的场景需求,因此在显示实现赋值重载函数时需要避开这个问题。
  3. 赋值重载函数只能重载成类的成员函数,而不能重载成全局函数。
  4. 如果没有显示的实现赋值重载函数,编译器会自动生成一个默认赋值重载函数。其对于内置类型成员变量按照完成值拷贝,对于自定义的类型的成员变量会调用它们的赋值重载函数。

为什么赋值重载函数只能重载成类成员函数不能重载成全局函数呢???

因为,如果在类中没有显示实现赋值重载函数,而是在类外实现赋值重载函数。那么编译器会在类内自动生成一个默认的赋值重载函数。而程序在调用赋值重载函数时,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值运算符重载只能是类的成员函数。 在《c++ Prime 第五版》这本书中也提到,如下图所示:

在这里插入图片描述

既然编译器可以自动生成一个赋值重载函数了,为什么我们还要自己设计实现呢???

这里举一个例子来理解:下面是一个栈类的简单实现。

#include<iostream>
#include<stdlib.h>
using namespace std; typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 10){_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申请空间失败");return;}_size = 0;_capacity = capacity;}void Push(const DataType& data){// CheckCapacity();_array[_size] = data;_size++;}~Stack(){if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}
private:DataType* _array;size_t _size;size_t _capacity;
};
int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2;s2 = s1;return 0;
}

程序运行结果:

在这里插入图片描述

我们可以看到,程序执行最终崩掉了。为什么呢?接下来我画图分析一下:
在这里插入图片描述

  • s1 赋值给s2后,s1和s2的_array指向同一块空间,当s1和s2销毁的时候,都会调用析构函数对 _ array空间进行释放,就出现多次释放同一块空间的问题
  • 赋值后,s2申请的_array 指向的空间就没有人标识它的位置了,从而造成了内存泄露。

前置++和后置++重载

前置++:返回+1之后的结果

注意:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率

后置++:

前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载, C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器自动传递
注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存一份,然后给this + 1。而temp是临时对象,因此只能以值的方式返回,不能返回引用

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date& operator++(){_day += 1;return *this;}Date operator++(int){Date temp(*this);_day += 1;return temp;}
private:int _year;int _month;int _day;
};int main()
{Date d;Date d1(2022, 1, 13);d = d1++;  d = ++d1;  return 0; }

const 修饰的成员

将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数。隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。

const对象可以调用非const成员函数吗?非const对象可以调用const成员函数吗?const成员函数内可以调用其它的非const成员函数吗?非const成员函数内可以调用其它的const成员函数吗?

这几个问题都设计了权限的问题。我们知道,只能让变量的权限平移或者缩小,不能让权限放大。因此,const对象不可以调用非const成员函数(权限放大);非const对象可以调用const成员函数(权限缩小);const成员函数内不可以调用其它的非const成员函数(权限放大);非const成员函数内可以调用其它的const成员函数(权限缩小)。

取地址及const取地址操作符重载

这两个默认成员函数一般不用重新定义 ,编译器默认会生成。

class Date
{
public:Date* operator&(){return this;}const Date* operator&()const{return this;}
private:int _year; // 年int _month; // 月int _day; // 日
};

这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载。

总结撒花💞

   希望大家通过阅读此文有所收获
   😘如果我写的有什么不好之处,请在文章下方给出你宝贵的意见😊。如果觉得我写的好的话请点个赞赞和关注哦~😘😘😘

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

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

相关文章

【腾讯云 Cloud Studio 实战训练营】使用Cloud Studio构建SpringSecurity权限框架

1.Cloud Studio&#xff08;云端 IDE&#xff09;简介 Cloud Studio 是基于浏览器的集成式开发环境&#xff08;IDE&#xff09;&#xff0c;为开发者提供了一个永不间断的云端工作站。用户在使用 Cloud Studio 时无需安装&#xff0c;随时随地打开浏览器就能在线编程。 Clou…

Spring 知识点

Spring 1.1 Spring 简介 1.1.1 Spring 概念 Spring是一个轻量级Java开发框架&#xff0c;最早有Rod Johnson创建为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题Spring最根本的使命是解决企业级应用开发的复杂性&#xff0c;即简化Java开发。使现有的技术更加容易使…

Linux下进程的特点与环境变量

目录 进程的特点 进程特点的介绍 进程时如何实现并发性的 进程间如何切换 概念铺设 PC指针 上下文 环境变量 PATH 修改PATH HOME SHELL env 命令行参数 什么是命令行参数&#xff1f; 打印命令行参数 通过函数获得环境变量 getenv 命令行参数 env 修改环境变…

SpringBoot 项目使用 Redis 对用户 IP 进行接口限流

一、思路 使用接口限流的主要目的在于提高系统的稳定性&#xff0c;防止接口被恶意打击&#xff08;短时间内大量请求&#xff09;。 比如要求某接口在1分钟内请求次数不超过1000次&#xff0c;那么应该如何设计代码呢&#xff1f; 下面讲两种思路&#xff0c;如果想看代码可…

MySql用户管理、权限管理

用户管理 1. 查看系统用户&#xff08;查询mysql系统数据库中的user表&#xff09; select * from mysql.user; 2. 创建用户 CREATE USER 用户名主机名 identified by 密码 -- 创建用户zhonghua,只能在当前主句localhost访问,密码为123456 create user zhonghualocalhost i…

springCache-缓存

SpringCache 简介&#xff1a;是一个框架&#xff0c;实现了基于注解的缓存功能&#xff0c;底层可以切换不同的cache的实现&#xff0c;具体是通过CacheManager接口实现 使用springcache,根据实现的缓存技术&#xff0c;如使用的redis,需要导入redis的依赖包 基于map缓存 …

MySQL 查询语句大全

目录 基础查询 直接查询 AS起别名 去重&#xff08;复&#xff09;查询 条件查询 算术运算符查询 逻辑运算符查询 正则表达式查询⭐ 模糊查询 范围查询 是否非空判断查询 排序查询 限制查询&#xff08;分页查询&#xff09; 随机查询 分组查询 HAVING 高级查询…

EtherCAT转EtherCAT网关FX5U有EtherCAT功能吗两个ETHERCAT设备互联

1.1 产品功能 捷米JM-ECT-ECT是自主研发的一款ETHERCAT从站功能的通讯网关。该产品主要功能是将2个ETHERCAT网络连接起来。 本网关连接到ETHERCAT总线中做为从站使用。 1.2 技术参数 1.2.1 捷米JM-ECT-ECT技术参数 ● 网关做为ETHERCAT网络的从站&#xff0c;可以连接倍福、…

小型双轮差速底盘机器人实现红外跟随功能

1. 功能说明 本文示例将实现R023样机小型双轮差速底盘跟随人移动的功能。在小型双轮差速底盘前方按下图所示安装3个 近红外传感器&#xff0c;制作一个红外线发射源&#xff0c;实现当红外发射源在机器人的检测范围内任意放置或移动时&#xff0c;机器人能追踪该发射源。 2. 电…

抖音seo矩阵系统源码搭建开发详解

抖音SEO矩阵系统是一个用于提高抖音视频在搜索引擎排名的工具。如果你想开发自己的抖音SEO矩阵系统&#xff0c;以下是详细的步骤&#xff1a; 开发步骤详解&#xff1a; 确定你需要的功能和算法 抖音SEO矩阵系统包含很多功能&#xff0c;比如关键词研究、内容优化、链接建设、…

PHP8的跳转语句-PHP8知识详解

如果循环条件满足的时候&#xff0c;则程序会一直执行下去。如果需要强制跳出循环&#xff0c;则需要使用跳转语句来完成。PHP8的跳转语句包括break语句、continue语句和goto语句。 1、break语句 break语句的作用是完全终止循环&#xff0c;包括while、do…while、for、switch…

6. CSS(三)

目录 一、盒子模型 &#xff08;一&#xff09;网页布局的本质 &#xff08;二&#xff09;盒子模型组成 &#xff08;三&#xff09;边框&#xff08;border&#xff09; &#xff08;四&#xff09;表格的细线边框 &#xff08;五&#xff09;内边距&#xff08;padding…

[JavaScript游戏开发] 绘制Q版地图、键盘上下左右地图场景切换

系列文章目录 第一章 2D二维地图绘制、人物移动、障碍检测 第二章 跟随人物二维动态地图绘制、自动寻径、小地图显示(人物红点显示) 第三章 绘制冰宫宝藏地图、人物鼠标点击移动、障碍检测 第四章 绘制Q版地图、键盘上下左右地图场景切换 文章目录 系列文章目录前言一、本章节…

【TypeScript】类型断言-类型的声明和转换(五)

【TypeScript】类型断言-类型的声明和转换&#xff08;五&#xff09; 【TypeScript】类型断言-类型的声明和转换&#xff08;五&#xff09;一、简介二、断言形式2.1 尖括号语法2.2 as形式 三、断言类型3.1 非空断言3.2 肯定断言-肯定化保证赋值3.3 将任何类型断言为any3.4 调…

Django实现音乐网站 ⑹

使用Python Django框架制作一个音乐网站&#xff0c; 本篇主要是在添加编辑过程中对后台歌手功能优化及表模型名称修改、模型继承内容。 目录 表模型名称修改 模型继承 创建抽象基类 其他模型继承 更新表结构 歌手新增、编辑优化 表字段名称修改 隐藏单曲数和专辑数 姓…

Leetcode周赛 | 2023-8-6

2023-8-6 题1体会我的代码 题2我的超时代码题目体会我的代码 题3体会我的代码 题1 体会 这道题完全就是唬人&#xff0c;只要想明白了&#xff0c;只要有两个连续的数的和&#xff0c;大于target&#xff0c;那么一定可以&#xff0c;两边一次切一个就好了。 我的代码 题2 我…

eNSP 路由器启动时一直显示 # 号的解决办法

文章目录 1 问题截图2 解决办法2.1 办法一&#xff1a;排除防火墙原因导致 3 验证是否成功 1 问题截图 路由器命令行一直显示 # 号&#xff0c;如下图 2 解决办法 2.1 办法一&#xff1a;排除防火墙原因导致 排查是否因为系统防火墙原因导致。放行与 eNSP 和 virtualbox 相…

专业的ADAS测试记录仪ETHOS

随着ADAS驾驶辅助系统技术的快速发展及日臻成熟&#xff0c;近年来ADAS在全球汽车市场已开始快速普及和商业化&#xff0c;而如何确保ADAS系统的可靠和安全俨然成为汽车领域的重要问题。因此&#xff0c;ADAS驾驶辅助系统的测试也成为了各大整车厂及零部件厂商所关注的焦点。 一…

区块链实验室(14) - 编译FISCO-BCOS

FISCO-BCOS是一种区块链平台&#xff0c;与Hyperledger和Ethereum有些不同&#xff0c;详见FISCO BCOS 区块链 编译FISCO BCOS源码的目的是修改或者新增其中功能模块&#xff0c;进行对比实验&#xff0c;验证新想法、新创意的效果。编译的步骤很简单&#xff0c;按技术文档一…

0805hw

1. #include <myhead.h> void Bub_sort(int *arr,int n)//冒泡排序 {for(int i1;i<n;i){int count0;for(int j0;j<n-i;j){if(arr[j]>arr[j1]){int temparr[j];arr[j]arr[j1];arr[j1]temp;count;}}if(count0){break;}}printf("冒泡排序后输出结果:\n"…