C++初阶之类与对象(中)——六个默认函数详细解析

个人主页:点我进入主页

专栏分类:C语言初阶  C语言进阶  数据结构初阶    Linux    C++初阶    

欢迎大家点赞,评论,收藏。

一起努力,一起奔赴大厂

目录

一.前言

二.构造函数

2.1构造函数的语法和特性

2.1.1语法

2.1.2特性

2.2代码演示与验证

2.2.1构造函数的多种写法(语法部分验证)

2.2.1.1无参

2.2.1.2传参数

2.2.1.3全缺省 

2.2.1.4默认生成

2.2.1.5三种只能存在一种

2.2.2类嵌套类(特性部分验证)

2.3C++11新写法

三.析构函数

3.1析构函数的语法

3.2代码演示与验证

3.3析构函数应用场景

3.4析构函数的调用顺序

四.拷贝构造

4.1特性

4.2代码解析

4.2.1只有一个拷贝后构造的日期类出现的问题

4.2.2正确的代码

4.3深拷贝

4.4解决方案

4.5传值引发的死递归

五.总结



一.前言

        在本次博客中我将给大家带来6个默认成员函数,主要包括构造函数,析构函数,拷贝构造,赋值重载,符号重载,在这次文章中我们需要记住一个关键点自动调用,其中构造函数是对数据进行初始化,析构函数是完成清理工作,拷贝构造是对同同类对象进行初始化 ,赋值重载是把一个对象给另一个对象。其中重要的是前四个,我们这次对前三个进行讲解。

二.构造函数

2.1构造函数的语法和特性

2.1.1语法

  • 构造函数函数名和类名相同。
  • 构造函数支持函数重载。
  • 构造函数无返回值。
  • 构造函数在对象实例化的时候自动调用。   

2.1.2特性

  • C++分为内置类型和自定义类型,内置类型不会处理,定义类型自动调用它的默认构造。
  • 如果我们没有写默认构造编译器会自动生成一个默认构造。
  • 默认构造会自动调用,其中默认构造包括无参形式,全缺省形式以及编译器自动生成的默认构造,这三个只能存在一个。

2.2代码演示与验证

2.2.1构造函数的多种写法(语法部分验证)

2.2.1.1无参

我们分文件进行编写,我们先创建一个类,头文件的代码为:

#pragma once
#include<iostream>
using namespace std;class Data {
public:Data(){_year = 1;_month = 1;_day = 1;}void Print();
private:int _year;int _month;int _day;
};

我们的打印函数在另一个.cpp文件,主函数在另外一个.cpp文件中

#include"class.h"void Data::Print()
{cout << _year << "/" << _month << "/" << _day << endl;
}

主函数的代码为:

#include"class.h"int main()
{Data d1;d1.Print();return 0;
}

我们运行代码就会看到d1的年月日都被初始化为1

2.2.1.2传参数

我们将构造函数改为

	Data(int year, int month, int day){_year = year;_month = month;_day =day;}

我们按照上面的代码继续运行就会出现问题:

编译器显示我们没有默认构造函数可用,这是为什么呢?我们不是写了吗?我们写了,所以编译器不会生成,只能选择我们写的,我们需要对其进行传参,那我们应该如何修改呢?我们需要知道构造函数时什么时候调用的呢?构造函数是在生成实例化对象的时候自动调用的,所以我们在生成实例化对象的时候进行传参,

//Data d1;
Data d1(1, 1, 1);

看到这里有人就会想到为什么无参的为什么不写成Data da();这主要就是为了和我们的函数声明区分开

2.2.1.3全缺省 
	Data(int year=1, int month=1, int day=1){_year = year;_month = month;_day = day;}

我们将构造函数改成全缺省的形式,的那我们在生成实例化对象的时候既可以传参也可以不传参

	Data d1(1, 1, 1);Data d2;

这两种都可以使用。

2.2.1.4默认生成

我们不写构造函数,我们的结果是什么样子的呢?

我们看大是这些是,这是由于编译器的不同,所以数据可能不同。

2.2.1.5三种只能存在一种

        如果我们写了构造函数,编译器不会生成构造函数,也就是说编译器生成的构造函数和我们写的不能共存,这一点是非常容易理解的,对于无参和全缺省的我们可以看下面的示例:

我们的构造函数为:

	Data(){_year = 1;_month = 1;_day = 1;}	Data(int year=1, int month=1, int day=1){_year = year;_month = month;_day = day;}	

我们的测试代码为:

Data d2;

我们可以看到错误为:

这是因为我们的测试代码对于这两种都符合,编译器不知道运行哪一个,所以我们的无参和构造函数不能同时存在,传参数的和无参的虽热可以同时存在,但是他们两个的功能一个全缺省就可以解决,所以全缺省是最完美的。

2.2.2类嵌套类(特性部分验证)

我们将类进行修改,并且增加一个新的类:

class A {
public:A(int data1=1, int data2=1){_data1 = data1;_data2 = data2;}
private:int _data1;int _data2;
};
class Data {
public:int num;Data(int year=1, int month=1, int day=1){_year = year;_month = month;_day = day;}	void Print();
private:int _year;int _month;int _day;A _a;
};

我们进行调试就可以看到我们的内置类型不做任何处理,也就是我们的d2.num,内置类型会调用它的默认构造。

2.3C++11新写法

        在C++11中委员会对构造函数进行了新的更新,可以在声明时进行缺省,我们看下面的代码样例:

class Data {
public:	void Print();
private:int _year=2;int _month = 2;int _day=2;};

三.析构函数

3.1析构函数的语法

  • 析构函数函数名是~类名
  • 析构函数不支持函数重载
  • 析构函数无参数无返回值
  • 对象的声明周期结束时自动调用,若没用显示定义编译器会自动生成。

3.2代码演示与验证

        我们在类里面加上我们析构函数(析构函数是对没用用的资源进行处理,由于我们写的是日期类,不用进行资源的清理,并且为了我们为了更详细的演示所以我们进行打印函数名)。

class Data {
public:Data(int year = 1, int month = 1, int day = 1){cout << "Data" << endl;}~Data(){cout << "~Data" << endl;}
private:int _year;int _month;int _day;};

我们运行后可以看到:

3.3析构函数应用场景

        说到我们的析构函数,我们应该知道祖师爷为什么设计出我们的析构函数,你是否有这样的经历,一个软件本来是挺快的但是当我们用了一段时间后就会变得很卡,当我们将后台杀了再打开就会变快,但是用一段时间后又会卡,这主要就是一些文件打开后就没有关闭,再我们下写程序的时候我们总会出现这样的情况开辟了一段空间后总会忘记释放,祖师爷也深受这些的困扰,所以出现了我们的析构函数,我们一个应用场景就是栈,我们写一个类,代码如下:

class Stack {
public:Stack(){_a = new int[4];_size = 0;_capacity = 4;}~Stack(){delete _a;}
private:int* _a;int _size;int _capacity;
};

在这里就是我们对析构函数的一个应用。

3.4析构函数的调用顺序

我们看下面代码:

Data d4(4, 4, 4);
Data d5(5, 5, 5);
int main()
{Data d1(1, 1, 1);static Data d2(2, 2, 2);Data d3(3, 3, 3);return 0;
}

我们需要知道我们的析构函数符合栈的规则,符合后进先出,也就是说我们先调用后面的析构函数,我们运行后可以看到:

符合我们的规则,先析构3再析构1,由于2是静态变量所以后出,出2,然后出我们的全局变量,出5再出4;我们将5和4定义的位置互换

Data d5(5, 5, 5);
Data d4(4, 4, 4);int main()
{Data d1(1, 1, 1);static Data d2(2, 2, 2);Data d3(3, 3, 3);return 0;
}

我们运行后可以看到:

四.拷贝构造

4.1特性

  • 拷贝构造是构造函数的重载
  • 拷贝构造在传址或传参时自动调用
  • 拷贝构造只有一个参数,必须是类的对象,传值时会发生错误出现死递归,所以我们采用引用。
  • 如果没有显式定义,编译器会自动生成浅拷贝的拷贝构造,如果需要深拷贝就不能完成。

4.2代码解析

4.2.1只有一个拷贝后构造的日期类出现的问题

class Data {
public:Data(const Data& d){_year = d._year;_month = d._month;_day = d._day;}
private:int _year;int _month;int _day;};

当我们运行

	Data d1;

我们看到的错误信息为

这时候我们想构造函数不是默认生成的吗?怎末会不存在默认构造?仔细看我们类的定义,你会发现我们拷贝构造的构造函数重载了,我们需要知道拷贝构造也是构造,所以我们在写拷贝构造时我们需要加上我们的构造函数。

4.2.2正确的代码

class Data {
public:Data(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Data(const Data& d){_year = d._year;_month = d._month;_day = d._day;}
private:int _year;int _month;int _day;};

我们需要将拷贝构造和构造函数一块写,我们只写拷贝构造的话编译器也不会生成构造函数,这是因为拷贝构造也是构造

4.3深拷贝

        在上面的拷贝都是一些浅拷贝,我们看下面的代码:

class Stack {
public:Stack(int capacity=4){_a = new int[4];_size = 0;_capacity = capacity;}~Stack(){delete[] _a;}Stack(const Stack& s){_a = s._a;_size = s._size;_capacity = s._capacity;}
private:int* _a;int _size;int _capacity;
};

我们运行的代码为:

	Stack s1(4);Stack s2(s1);

我们运行后可以看到:

这个主要就是程序出现了对空间的二次free。

4.4解决方案

我们只需要对拷贝构造进行修改即可:

	Stack(const Stack& s){int * _tmp = new int[4];_size = s._size;_capacity = s._capacity;memcpy(_tmp, s._a, 16);_a = _tmp;}

4.5传值引发的死递归

	Data( const Data d){_year = d._year;_month = d._month;_day = d._day;}

这是我们的拷贝构造,我们需要知道当我们调用拷贝构造时会自动调用一次拷贝构造,也就是说传自定义类型时会调用拷贝构造,由于我们使用的是传值,这次调用,调用的会再次调用拷贝构造, 这样就会发生死递归,当我们改成传引用就会完美的解决我们的问题。

五.总结

        类是我们C++中的一个重点,大家可以多看看,最后希望大家可以一键三连。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

C++ dfs 的状态表示(五十一)【第十一篇】

今天我们接着学习dfs&#xff08;状态表示&#xff09;。 1.抽象形式的dfs 前面用到的 DFS 算法都是比较容易想象出搜索过程的&#xff0c;接下来我们看一些不那么容易想象搜索过程的 DFS 过程&#xff0c;这些问题我们称为抽象形式的 DFS。 来回顾一下上节课遇到的一个问题&a…

java 执行方式和类加载过程

java默认属于混合执行&#xff1a; 编译和解释并存 java先进行解释执行&#xff0c;遇到多次重复的代码会把它编程成可执行文件&#xff0c;方便下次直接执行。 可以通过VM参数来修改执行方式。 类加载过程

为什么IDM下载速度很慢,IDM下载速度很慢怎么办

为什么IDM下载速度很慢&#xff0c;IDM下载速度很慢怎么办 IDM采用的是多线程下载模式。 如果说单线程下载“一个人完成一项工作”&#xff0c;那多线程下载就是“多个人完成一项工作”。它能让用户从服务器获得更高的带宽&#xff0c;从而提高资源下载速度。一般IDM会默认使用…

MySQL篇----第十九篇

系列文章目录 文章目录 系列文章目录前言一、什么是存储过程?用什么来调用?二、如何通俗地理解三个范式?三、什么是基本表?什么是视图?四、试述视图的优点?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这…

【漏洞复现】狮子鱼CMS文件上传漏洞(image_upload.php)

Nx01 产品简介 狮子鱼CMS&#xff08;Content Management System&#xff09;是一种网站管理系统&#xff0c;它旨在帮助用户更轻松地创建和管理网站。该系统拥有用户友好的界面和丰富的功能&#xff0c;包括页面管理、博客、新闻、产品展示等。通过简单直观的管理界面&#xf…

postgresql 手动清理wal日志的101个坑

新年的第一天&#xff0c;总结下去年遇到的关于WAL日志清理的101个坑&#xff0c;以及如何相对安全地进行清理。前面是关于WAL日志堆积的原因分析&#xff0c;清理相关可以直接看第三部分。 首先说明&#xff0c;手动清理wal日志是一个高风险的操作&#xff0c;尤其对于带主从的…

70.SpringMVC怎么和AJAX相互调用的?

70.SpringMVC怎么和AJAX相互调用的&#xff1f; &#xff08;1&#xff09;加入Jackson.jar&#xff08;2&#xff09;在配置文件中配置json的消息转换器.(jackson不需要该配置HttpMessageConverter&#xff09; <!‐‐它就帮我们配置了默认json映射‐‐> <mvc:anno…

前端工程化面试题 | 04.精选前端工程化高频面试题

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

禁止文件外发,文件禁止外发的方法

在当今的企业环境中&#xff0c;数据安全至关重要。 什么是企业文件外发&#xff1f; 企业文件外发指的是将企业内部的电子文件发送给组织外部的人员使用。 这种行为可能带来数据安全风险&#xff0c;因为电子文件自身具有易拷贝、易扩散、易传播的特性。 如果带有核心资产或…

AS自治系统的路由协议--BGP

BGPV4 --- IPV4 --- BGPV4 --- MPBGP --- 支持多种不同的地址组 重发布替代BGP的缺陷&#xff1a; 1&#xff0c;选路不佳 2&#xff0c;ASBR的归属问题 BGP --- 无类别路径矢量协议 1&#xff0c;无类别 --- 在传递路由信息的时候携带子网掩码 2&#xff0c;路径矢量 ---…

小游戏和GUI编程(4) | 基于 SFML 的黑客帝国字符雨

小游戏和GUI编程(4) | 基于 SFML 的黑客帝国字符雨 文章目录 小游戏和GUI编程(4) | 基于 SFML 的黑客帝国字符雨1. 简介2. 规划3. 一个字符的下落3. 一个雨滴的下落4. 每个雨滴都是独一无二的5. 重构后&#xff0c; 降落多个雨滴6. 总结7. 参考 1. 简介 使用 SFML 实现黑客帝国…

股价分布统计 100元能买股票吗?

A股的股价一般是多少&#xff1f;100元能买股票吗&#xff1f;能买多少&#xff1f; 一、买入交易规则&#xff1a; 沪深主板(包括中小板)&#xff0c;股票代码以600,000,002开头&#xff0c;每次最低买100股&#xff0c;随后以100股为单位增加&#xff0c;也就是可以买100股&…

k8s-资源限制与监控 15

资源限制 上传实验所需镜像 Kubernetes采用request和limit两种限制类型来对资源进行分配。 request(资源需求)&#xff1a;即运行Pod的节点必须满足运行Pod的最基本需求才能 运行Pod。 limit(资源限额)&#xff1a;即运行Pod期间&#xff0c;可能内存使用量会增加&#xff0…

委托和事件详解

委托和事件详解 前言一、委托1.什么是委托2.委托的声明3.Action<T>委托和Func<T>委托4.委托的缺点5.委托与lambda表达式6.委托的使用&#xff08;1&#xff09;模板方法&#xff08;2&#xff09;回调方法 二、事件1.什么是事件2.事件模型的5个步骤和组成部分&…

《Git 简易速速上手小册》第5章:高级 Git 技巧(2024 最新版)

文章目录 5.1 交互式暂存5.1.1 基础知识讲解5.1.2 重点案例&#xff1a;为 Python 项目分阶段提交5.1.3 拓展案例 1&#xff1a;细粒度控制更改5.1.4 拓展案例 2&#xff1a;处理遗漏的更改 5.2 使用 Rebase 优化提交历史5.2.1 基础知识讲解5.2.2 重点案例&#xff1a;整理 Pyt…

springcloud分布式架构网上商城源码和论文

首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了系统的需求基础上需要进一步地设计系统,主要包罗软件架构模式、整体功能模块、数据库设计。本项…

H12-821_35

35.如图所示,SWA、SWB、SWC都运行RSTP,SWB上的GEO/O/2端口和SWC上的GEO/0/1端其端口角色为? A.backup端口.Alternative端口 B.Alternative端口、Backup端口 C.Root端口、Designate端口 D.Backup端口、Root端口 答案&#xff1a;A 注释&#xff1a; 一个链路&#xff08;冲突域…

hexo部署到gitee(码云)

引言 Hexo 是一个基于Node.js的静态博客框架&#xff0c;而 Gitee&#xff08;也被称为码云&#xff09;是一个国内的代码托管平台&#xff0c;支持 Git 版本控制系统&#xff0c;与 GitHub 类似。将 Hexo 部署到 Gitee Pages 可以让你的博客受益于 Gitee 的国内服务器&#xf…

python web 框架Django学习笔记

2018年5月 python web 框架Django学习笔记 Django 架站的16堂课 MVC架构设计师大部分框架或大型程序项目中一种软件工程的架构模式&#xff0c;把程序或者项目分为三个主要组成部分&#xff0c;Model数据模型、View视图、Controller控制器。 命令及设置相关 创建数据库及中间…

Open CASCADE学习|保存为STL文件

STL (Stereolithography) 文件是一种广泛用于3D打印和计算机辅助设计 (CAD) 领域的文件格式。它描述了一个三维模型的表面而不包含颜色、材质或其他非几何信息。STL文件通常用于3D打印过程中&#xff0c;因为它们仅包含构建物体所需的位置信息。 由于STL文件只包含表面信息&am…