c++类和对象新手保姆级上手教学(中)

前言:

  类和对象中篇,这里讲到的前4个默认成员函数,是类和对象中的重难点,许多资料上的讲法都非常抽象,难以理解,所以我作出这篇总结,分享学习经验,以便日后复习。

目录

6个默认成员函数:

构造函数:

1.概念:

2.用法:

3.特性:

 析构函数:

1.概念:

2.用法:

 3.特性:

4.析构调用顺序练习:

拷贝构造函数:

1.概念:

2.用法:

3.特性:

运算符重载:

用法:

赋值重载:

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

 取地址重载(不重要):

const成员函数:

 


6个默认成员函数:

什么是默认成员函数?

默认成员函数就是你不写编译器自己会自动生成的成员函数

前四个默认成员函数较为重要,后两个很少会自己实现,除非常特殊的情况下,基本上不会自己实现。

构造函数:

1.概念:

  想必大家再用c语言实现栈,链表等数据结构的时候,都会先写一个初始化函数,来初始化我们的数据,但在使用中有时往往会忘记初始化,所以C++就产生了构造函数。

构造函数的作用就是进行初始化

2.用法:

  那构造函数具体是怎样来使用的呢?举一个简单的案例,一个日期类的构造函数如下:

3.特性:

  构造函数的函数名和类名相同。

  无返回值。

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

  构造函数支持重载。

  建议写成全缺省。 

  一个类必须要有默认构造函数,如果你没有写,编译器会自己生成默认构造函数,但编译器默认生成的构造函数内置类型不作处理,自定义类型去调用它的默认构造函数。但在C++11中委员会可能认为对内置类型不作处理显得很呆,所以对这个语法打补丁,支持在声明处给缺省值:

这样编译器默认生成的构造函数就会对内置类型进行处理。 

  但大多数情况下,构造函数都是需要我们自己去实现的。

无参构造函数,全缺省构造函数,编译器默认生成的构造函数,都可以称为默认构造函数,但一个类默认构造函数只能有一个,建议写成全缺省,避免歧义。

 析构函数:

1.概念:

  如果说构造函数的功能时初始化,那么析构函数就像它的死对头:

析构函数负责清理资源的工作,防止内存泄漏。

 还是一样,我们在使用栈,链表等数据结构时最容易忘的就是用完后忘记清理空间,这将导致严重的后果,也就是内存泄漏,而C++中的析构函数可以有效解决这个问题。

2.用法:

由于我这个日期类不涉及动态资源,所以析构函数不必自己实现,但仍会调用:

 3.特性:

 函数名 = ~类名

 无返回值

 一个类只能有一个析构函数,如果不写编译器自己生成

 析构函数不能重载

 对象生命周期结束时,编译器自动调用析构函数

 对于编译器自己生成的析构函数,同样是内置类型不作处理,自定义类型调用它自己的析构函数。

4.析构调用顺序练习:

对于析构函数,其实头疼的是它的多个函数析构时的调用顺序,这里给大家一个公式,大家以后套公式即可:

局部对象(后定义先析构)->局部静态(后定义先析构)->全局对象(后定义先析构)

下面由浅入深来练习一下: 

练习1: 

#include<iostream>
using namespace std;
class Date
{
public:Date(int year=1,int month=1,int day=1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}~Date(){cout << "调用析构" << _year << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1(1);Date d2(2);Date d3(3);return 0;
}

因为他们都是局部变量,遵循后定义先析构,所以:

练习2:

#include<iostream>
using namespace std;
class Date
{
public:Date(int year=1,int month=1,int day=1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}~Date(){cout << "调用析构" << _year << endl;}
private:int _year;int _month;int _day;
};
Date d1(1);
Date d2(2);
Date d3(3);
int main()
{//Date d1(1);//Date d2(2);//Date d3(3);return 0;
}

 现在他们都变为全局变量,仍遵循后定义先析构:

练习3:

#include<iostream>
using namespace std;
class Date
{
public:Date(int year=1,int month=1,int day=1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}~Date(){cout << "调用析构" << _year << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1(1);static Date d2(2);static Date d3(3);Date d4(4);return 0;
}

 现在,d2变成局部静态,根据公式,先局部对象再局部静态,内部仍然按照后定义先析构:

练习4:

#include<iostream>
using namespace std;
class Date
{
public:Date(int year=1,int month=1,int day=1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}~Date(){cout << "调用析构" << _year << endl;}
private:int _year;int _month;int _day;
};
Date d5(5);
static Date d6(6);
Date d7(7);
static Date d8(8);
int main()
{Date d1(1);static Date d2(2);static Date d3(3);Date d4(4);return 0;
}

 先局部对象,再局部静态,最后全局,不管全局对象是否为静态,都遵循后定义先析构:

拷贝构造函数:

1.概念:

 在使用C++中,我们往往会需要将一个类拷贝到另一个相同类型的类中,而拷贝构造函数的作用就是:将该类拷贝到同类型的类中。

2.用法:

为了更严谨,也可以在此处加上const:

 

3.特性:

 函数名和类名相同

 无返回值

 形参部分传引用

 拷贝构造函数也是构造函数

 如果我们不写,编译器会默认生成,默认生成的拷贝构造函数对内置类型成员按内存存储按字节序拷贝,也就是浅拷贝,对自定义成员调用它的拷贝构造。

为什么形参部分必须传引用呢?

因为不传引用可能会引发无穷递归,看下面这个例子:

此时像上图一样使用拷贝构造函数,如果我们的拷贝构造函数是传值:

 

那就需要先调用拷贝构造,调用到拷贝构造时,因为是传值,所以需要将d1先拷贝到形参d,而将d1拷贝到形参d,就又需要调用新的拷贝构造,而新的拷贝构造又是传值,所以就这样一直递归下去,无穷无尽。

编译器默认生成的拷贝构造会拷贝内置类型,那么是不是意味着我们不需要自己实现拷贝构造?

不!!!

编译器默认生成的拷贝构造只能进行浅拷贝。

当我们有一个栈,里面有一个指针,指向了一片空间,当我们还是浅拷贝,用编译器默认生成的拷贝构造函数的话,它就会原原本本的将指针的拷贝到新的指针中,这就导致这篇空间有两个指针指向它,而不是像我们预想的一样,拷贝一块新空间,所以当要进行深拷贝时,我们需要自己来写拷贝构造函数 

所以写拷贝构造时,浅拷贝不需要写,只有有动态资源开辟的,才需要自己写拷贝构造。

运算符重载:

关键字:operator

用法:

将函数名改成operator加需要重载的运算符

在c语言中,对于内置类型我们可以直接用<  >  =  +  -  等符号进行运算,但如果我们要对自定义类型进行运算的话,就需要自己写函数来实现。

如果用运算符重载的话,将大大提高代码的可读性,比如我们实现一个判断两个日期类是否相同,重载==:

重载成成员函数:

重载成全局函数: 

 用法:

显而易见,第三种方法最实用,大大提高了代码的可读性 。

赋值重载:

这里的内容涉及的运算符重载,建议先跳到运算符重载,再来学习这段。

区分拷贝和赋值:

众所周知自定义类型是不能直接用等号连接进行赋值的,那么就需要进行运算符重载;

赋值重载和拷贝构造类似,但赋值重载是支持连续赋值的:

注意赋值重载只能重载成成员函数。 

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

前置++和后置++这两个运算符一模一样,但是作用效果却不同,为了不产生歧义,该如何进行重载呢?

前置++:

用法:

后置++: 

用法 :

可见为了和前置++区分开来,后置++强制增加了一个形参int 来区分。 

 取地址重载(不重要):

主要是对对象进行取地址操作,编译器自己生成的已经完全够用,没有必要再自己写,除非有特殊需求:

const成员函数:

如果我们希望某个成员函数不能对成员变量进行修改时,我们可以进行const修饰:

用法: 

我们可以对不用对成员变量进行修改的成员函数进行const修饰,增加代码的严谨性。如果const修饰的成员函数对成员变量进行了修改,编译器会报错:

C++类和对象中篇到此结束,这篇是最难也是最重要的一篇,下篇我会陆续更新进行收尾。 

 

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

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

相关文章

土壤墒情监测站的工作原理

TH-TS600土壤墒情自动监测站是一种用于自动检测土壤墒情的仪器&#xff0c;它可以实时监测土壤的水分含量和温度&#xff0c;并将数据传输到数据中心或监测中心进行分析和处理。 土壤墒情自动监测站通常由传感器、数据采集器、数据传输设备和数据处理软件等部分组成。传感器是…

Laravel02 路由基本概念和用法 给视图传递请求参数

Laravel02 路由基本概念和用法 1. 路由的基本概念2. 给视图传递请求参数 1. 路由的基本概念 routes文件夹下的web.php是用来定义路由规则的。 自己定义一个路径 2. 给视图传递请求参数 在laravel里使用一个辅助函数request来快速获取请求参数

NX/UG二次开发—CAM—平面铣边界准确设置方法

大家在对平面铣设置边界时&#xff0c;经常遇到边界方向与自己期望的不一致&#xff0c;有些人喜欢用检查刀路是否过切来判断&#xff0c;但是对于倒角、负余量等一些情况&#xff0c;刀路本来就是过切的。对于多边界&#xff0c;可以根据选择的曲线来起点和面的方向来确定&…

Camera2 createCaptureSession源码分析

当应用调用CameraManager#openCamera获取到已打开的camera设备后&#xff0c;会调用createCaptureSession方法来完成camera stream创建和stream的相关配置。在createCaptureSession方法中&#xff0c;首先将应用的surfaces信息封装成可跨binder传递的OutputConfiguration对象&a…

ACE 中的Active Object模式

Active Object 设计模式&#xff1a; 1&#xff09; 根据对象被调用的方式&#xff0c;可以将对象分为两类: Passive Object和Active Object。Passive 和 Object和调用者在同一个线程中&#xff0c;这就是我们通常所用的函数调用。而Active Object和调用在不同的线程中&#xf…

Leo赠书活动-16期 名校毕业生教材

Leo赠书活动-16期 名校毕业生教材 ✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 赠…

大厂的数据质量中心系统设计

日常工作中&#xff0c;数据开发上线完一个任务后并不是就可以高枕无忧&#xff0c;时常因上游链路数据异常或者自身处理逻辑的 BUG 导致产出的数据结果不可信。而问题发现可经历较长周期&#xff08;尤其离线场景&#xff09;&#xff0c;往往是业务方通过上层数据报表发现数据…

华为---RSTP(二)---RSTP基本配置示例

目录 1. 示例要求 2. 网络拓扑图 3. 配置命令 4. 测试终端连通性 5. RSTP基本配置 5.1 启用STP 5.2 修改生成树协议模式为RSTP 5.3 配置根交换机和次根交换机 5.4 设置边缘端口 6. 指定端口切换为备份端口 7. 测试验证网络 1. 示例要求 为防止网络出现环路&#xf…

【论文精读】MAE

摘要 将掩码重建任务从nlp引入到cv&#xff0c;提出非对称掩码自编码器。 框架 概述 如上图&#xff0c;本文提出掩码自编码器&#xff0c;即将给定原始信号的部分观测值的情况下重建原始信号&#xff0c;编码器将观察到的部分信号(没有掩码标记)映射到潜在表示&#xff0c;采…

Golang for 循环

从基础知识到高级技术、并发和通道 Go&#xff08;Golang&#xff09;编程语言中的“for”循环是一个基本而多功能的结构&#xff0c;用于迭代集合、重复执行代码块以及管理循环控制流。Golang的“for”循环语法简洁却强大&#xff0c;为处理多样的循环场景提供了一系列能力。无…

算法——数值算法——牛顿迭代法

目录 牛顿迭代法 一、1021: [编程入门]迭代法求平方根 牛顿迭代法 迭代法&#xff08;Iteration&#xff09;是一种通过反复递推计算来逼近解的方法。而牛顿迭代法&#xff08;Newtons method&#xff09;则是一种特定的迭代法&#xff0c;用于求解方程或函数的根、最小值、最…

MySQL数据库基础(十):DQL数据查询语言

文章目录 DQL数据查询语言 一、数据集准备 二、select查询 三、简单查询 四、条件查询 1、比较查询 2、范围查询 3、逻辑查询 4、模糊查询 5、非空查询 五、排序查询 六、聚合查询 七、分组查询与having子句 1、分组查询介绍 2、group by的使用 3、group by 聚…

【设计模式】23种设计模式笔记

设计模式分类 模板方法模式 核心就是设计一个部分抽象类。 这个类具有少量具体的方法&#xff0c;和大量抽象的方法&#xff0c;具体的方法是为外界提供服务的点&#xff0c;具体方法中定义了抽象方法的执行序列 装饰器模式 现在有一个对象A&#xff0c;希望A的a方法被修饰 …

单片机学习笔记---红外遥控红外遥控电机调速(完结篇)

目录 低电平触发中断和下降沿触发中断的区别 红外遥控 Int0.c Int.h Timer0.c Timer0.h IR.c IR.h main.c 红外遥控电机调速 Timer1.c Timer.h Motor.c Motor.h main.c 上一节讲了红外发送和接收的工作原理&#xff0c;这一节开始代码演示&#xff01; 提前说…

微信小程序-表单提交和校验

一、使用vant组件生成如下页面 二、前端代码如下 <form bindsubmit"submitForm"><view class"cell-group"><van-cell-group><van-field value"{{ title }}" label"商品名称" placeholder"请输入商品名称&qu…

Dubbo框架admin搭建

Dubbo服务监控平台&#xff0c;dubbo-admin是图形化的服务管理界面&#xff0c;从服务注册中心获取所有的提供者和消费者的配置。 dubbo-admin是前后端分离的项目&#xff0c;前端使用Vue&#xff0c;后端使用springboot。因此&#xff0c;前端需要nodejs环境&#xff0c;后端需…

复高斯分布的随机变量的模方的分布

文章目录 复高斯分布的随机变量的模方的分布问题的源头矩阵服从复高斯分布向量服从复高斯分布 复高斯分布的随机变量的模方的分布 已知 X ∼ C N ( μ , Σ ) X \sim \mathcal{C N}(\boldsymbol{\mu}, \boldsymbol{\Sigma}) X∼CN(μ,Σ) 则 ∥ X ∥ 2 \|X\|^2 ∥X∥2的分布为…

如何在本地服务器部署TeslaMate并远程查看特斯拉汽车数据无需公网ip

文章目录 1. Docker部署TeslaMate2. 本地访问TeslaMate3. Linux安装Cpolar4. 配置TeslaMate公网地址5. 远程访问TeslaMate6. 固定TeslaMate公网地址7. 固定地址访问TeslaMate TeslaMate是一个开源软件&#xff0c;可以通过连接特斯拉账号&#xff0c;记录行驶历史&#xff0c;统…

关于Android下gralloc,hwcompoer以及surface模块的重新认识

关于Android下gralloc&#xff0c;hwcompoer以及surface模块的重新认识 引言 欠债还钱天经地义&#xff0c;知识的债也是如此&#xff01;这不必须得将我前面欠下来的债给补上&#xff01;对于任何复杂的知识点&#xff0c;我们都可以采用庖丁解牛的学习方式&#xff0c;一步步…

文献速递:GAN医学影像合成--双向映射生成对抗网络用于脑部 MR 到 PET 合成

文献速递&#xff1a;GAN医学影像合成–双向映射生成对抗网络用于脑部 MR 到 PET 合成 01 文献速递介绍 作为精准医学的基石&#xff0c;多模态医学图像已成为必备要素。稿件收到日期&#xff1a;2021年6月26日&#xff1b;修改日期&#xff1a;2021年8月6日&#xff1b;接受…