前言:在上一篇类和对象(上)的文章中我们已经带领大家认识了类的概念,定义以及对类和对象的一些基本操作,接下来我们要逐步进入到类和对象(中)的学习。我们将逐步的介绍类和对象的核心——类和对象的六个默认成员函数。(注意:这六个默认成员函数是类和对象的核心,学好了它我们才能更好的去理解类和对象!)

在这里插入图片描述

MSTcheng: 个人主页
个人专栏:
《C语言》
《数据结构》
《C++由浅入深》

在这里插入图片描述

文章目录

  • 一,什么是成员函数?
  • 二,默认成员函数的种类
  • 三,六个成员函数
    • 3.1构造函数
    • 3.2构造函数的种类和使用
  • 四,析构函数
    • 4.1析构函数的作用
    • 4.2析构函数的用法
  • 五,拷贝构造
    • 5.1拷贝构造的作用
    • 5.2拷贝构造的使用
  • 六,总结

一,什么是成员函数?

要学习类和对象中的六个成员函数,那我们就要先了解什么是成员函数?

  • 成员函数就是在类里面定义的函数,一般定义在类里面的都称为成员如果是变量就称为成员变量,如果是函数就称为成员函数。
#include<iostream>
using namespace std;
class A
{
public://成员函数void func(){cout<<"void func()"<<endl;}
private://成员变量int _a;
}

二,默认成员函数的种类

C++的默认成员函数就是说我们没有显式的写该函数编译器会自动生成该函数就称为默认成员函数。C++有六个默认的成员函数也就是说这六个成员函数如果我们自己不写编译器就会自动生成。至于为什么要搞这些默认成员函数待学完这些默认成员函数你自然就会明白!

六个默认成员函数如下:
在这里插入图片描述

六个默认成员函数有三种,分别是执行初始化,拷贝,以及重载功能的函数。

  1. 执行初始化:构造函数,析构函数
  2. 执行拷贝:拷贝构造,赋值重载
  3. 取地址重载:两个重载函数
    注意:这六个成员函数中比较重要的是前4个,后两个可以作为了解!

下面我们依次介绍这几个函数。

三,六个成员函数

3.1构造函数

构造函数的概念:构造函数是一种特殊的成员函数,用于在创建对象时初始化对象的状态。通常与类名相同,无返回类型,支持重载。

3.2构造函数的种类和使用

在上面的构造函数中我们看到了几种构造函数的类型分别是:

  1. 默认构造函数:无参数,如果我们没有显式的写出来,编译器就会自动生成并进行默认初始化。
  2. 带参的构造函数:带参的构造函数又分为有缺省值和没有缺省值。注意全缺省的构造函数不能与无参的构造函数同时存在!因为这两个函数在调用时会引发冲突!
  3. 拷贝构造函数,参数是类名这个我们后面介绍。
class Date
{
public:
//默认构造函数与类名相同,无返回值,支持重载//不带参数Date(){_year = 1;_month = 1;_day = 1;}//Date(int year=1, int month=1, int day=1) 全缺省的构造函数//一般的构造函数Date(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << this->_year << "/" << this->_month << "/" << _day << endl;}
private:int _year;int _month;int _day;
};

在这里插入图片描述
什么都不写自动调用编译生成的默认构造,对成员变量进行默认初始化(值是随机值).

通过上面的代码我们能了解到构造函数的主要特点:

自动调用不显式写构造函数的情况下,对象创建时由编译器隐式调用,无需手动触发。
无返回值即使语法上不写 void,也不实际返回任何值。
支持重载一个类可以定义多个参数列表不同的构造函数。

注意:对于自定义类型成员变量,要求调用这个成员变量的默认构造函数初始化。如果这个成员变量,没有默认构造函数,那么就会报错!这就要使用初始化列表了,初始化列表后面介绍。

class A
{
};
class Date
{
private:int _year;int _month;int _day;A a; //自定义类a 对于a的初始化就要去调用A这个类的默认构造!	
}

四,析构函数

4.1析构函数的作用

析构函数与构造函数相反,构造函数是执行初始化功能的那么析构函数就是释放资源的。析构函数发挥作用的场景是在有资源需要释放的时候使用,如果像日期类没有资源就没有必要使用析构。当然编译器也会自动调用但不影响使用。

4.2析构函数的用法

析构函数相较于构造函数不同的是构造函数名与类名相同,而析构函数是~类名()
注意:若未显式定义析构函数,编译器会生成默认析构函数。
默认析构函数:
1. 对基本类型(如 int、float)无操作。
2. 对类成员调用其析构函数(按成员声明顺序逆序调用)。

class Date
{
public:
//构造函数Date(int year = 1, int month = 1, int day = 1){//在初始化之前先打印一下这个函数 这样便于我们直观的看到它在被调用cout << "Date(int year = 1, int month = 1, int day = 1)" << endl;_year = year;_month = month;_day = day;}
//析构函数~Date(){//在释放资源之前打印一下 方便直观看到被调用cout << "~Date()" << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;return 0;
}

在这里插入图片描述通过上面的代码我们可以认识到析构函数:

  1. 析构函数跟构造函数类似,无参数,无返回值。
  2. 自动调用析构函数,一个类只有一个析构若为显式定义则调用编译器生成的析构。
  3. 在同一个局部域中含有多个对象那么后定义的对象会先析构!

在上面的代码中我们看到析构函数并没有做什么事只是单纯的在函数内部打印方便我们直观看到调用,那这不就跟默认生成的析构一样吗?

像日期类这样没有资源的类编译器默认生成的就够用它不hi对内置类型如(int,float)做处理,但是如果是像栈这样的类那么编译器生成的析构就不能满足我们的需求了。下面我们来看栈这个类:

class Stack
{
public:Stack(int n = 4){cout << "Stack(int n = 4)" << endl;_a = (int*)malloc(sizeof(int) * n);if (nullptr == _a){perror("malloc申请空间失败");return;}_capacity = n;_top = 0;}//编译器默认生成的析构函数不能满足我们的要求它不会去自动的释放资源 所以需要我们显式写析构函数~Stack(){cout << "~Stack()" << endl;free(_a);_a = nullptr;_capacity = _top = 0;}
private:int* _a;size_t _capacity;size_t _top;
};

在这里插入图片描述

总结一下就是:在对象生命周期结束时系统就会自动调用析构。析构函数与构造函数类似对内置类型不做处理,对于自定义类型的成员就调用它的析构,且无论我们是否显式写析构只要类里面包含自定义类型的成员那么就会去调用它自己那个类的析构!

五,拷贝构造

5.1拷贝构造的作用

拷贝构造的作用就是使用同类型的对象去初始化创建另外一个对象,其中这两个对象都具有相同的成员变量值。可以将拷贝构造理解为给对象创建副本。

5.2拷贝构造的使用

  1. 拷贝构造与构造函数类似,就是参数上略有不同,所以拷贝构造是构造函数的一个重载。
  2. 如果没有显示定义拷贝构造,编译器就会自动生成一个拷贝构造。编译器生成的拷贝构造对内置类型会进行浅拷贝,对于自定义类型就去调用它的拷贝构造。
  3. C++规定了只要是自定义类型的对象进行拷贝行为就要去调用拷贝构造,无论是自定义类型的传值传参还是传值返回都要去调用拷贝构造。对于引用返回可能引发的野引用问题可以去看我之前的文章:传送门:引用返回的坑
class Date
{
public:Date(int year = 1, int month = 1, int day = 1){cout << "Date(int year = 1, int month = 1, int day = 1)" << endl;_year = year;_month = month;_day = day;}//d2(d1) 拷贝构造函数生成对象的拷贝 参数类型与被拷贝对象的类型相同为DateDate(const Date& d){_year = d._year;_month = d._month;_day = d._day;}//这里拷贝构造其实也可以传指针 引用的本质其实就是指针 但是指针还需要开空间 而引用不需要开空间//所以还是优先使用引用做为函数参数/*Date(Date* d){_year = d->_year;_month = d->_month;_day = d->_day;}*/~Date(){cout << "~Date()" << endl;}
private:int _year;int _month;int _day;
};int main()
{Date d1(2025, 4, 24);  // 构造Date d2(d1);           // 拷贝构造 构成 副本(原对象)//直接赋值也是拷贝的意思Date d4 = d1;          // 拷贝构造//使用指针 不推荐//Date d3(&d1);		   // 构造//Date d5 = &d1;	   // 构造return 0;
}

在上面的拷贝构造中参数一定要是传引用传参而不是传值传参,传值传参就会引发无穷递归!下面我们画图来解释:
在这里插入图片描述

这里要注意:像日期类内部没有资源我们可以使用编译器默认生成的拷贝构造就可以满足我们的要求;但是像栈这样的类就不一样了,栈这样的类内部有资源如果直接浅拷贝就会有问题,所以要自己写拷贝构造下面我们就来了解一下深浅拷贝问题:

class Stack
{
public://构造函数Stack(int n = 4){_a = (int*)malloc(sizeof(int) * n);if (nullptr == _a){perror("malloc申请空间失败");return;}_capacity = n;_top = 0;}// st2(st1) 拷贝构造函数生成对象的拷贝 参数类型与被拷贝对象的类型相同为stckStack(const Stack& s){cout << "Stack(Stack& s)" << endl;_a = (int*)malloc(sizeof(int) * s._capacity);if (nullptr == _a){perror("malloc申请空间失败");return;}memcpy(_a, s._a, sizeof(int) * s._top);_top = s._top;_capacity = s._capacity;}
private:int* _a;size_t _capacity;size_t _top;
};

在这里插入图片描述

这时可能有人问那以后是不是看到成员变量带有指针的就要去写拷贝构造呢?其实不是写不写拷贝构造其实跟写析构函数一样看类里面有没有资源,一般来说有资源就要写析构和拷贝构造,所以我们也可以看一个类如果显式写了析构函数那么就要写拷贝构造。

六,总结

学完了上面的内容回答下面两个问题:
第⼀:我们不写时,编译器默认生成的函数行为是什么,是否满足我们的需求?

  • 当我们不写时编译器会自动生成调用对应的构造,析构,拷贝构造等函数。如果像日期类这样没有资源的类可以使用编译器自己生成的构造,析构,拷贝构造函数;相反如果有资源则需要我们自己显式写对应的函数!

第⼆:编译器默认生成的函数不满足我们的需求,我们需要自己实现,那么如何自己实现?

  • 像有资源的类编译器生成的函数不能满足时比如像构造函数就要自己去创造空间,析构函数就要手动去释放空间,拷贝构造就要完成深拷贝等。
以上就是本篇文章的所有内容了,感谢各位大佬观看,制作不易还望各位大佬点赞支持一下!

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

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

相关文章

使用python-fastApi框架开发一个学校宿舍管理系统-前后端分离项目

今天给大家分享一个我最近做的一个学校宿舍管理系统&#xff0c;python版&#xff0c;这个系统实现的功能有&#xff1a;首页 | 学校管理 | 宿舍楼管理 | 宿舍管理 | 学生管理 | 学生调宿 | 学生退宿 | 报修等级 | 宿舍卫生评分 | 违纪记录 | 管理员管理 。一共有11个菜单。 使…

阻塞 vs 非阻塞:程序等待的两种哲学

当程序需要等待外部操作时&#xff0c;是应该"干等"还是"边等边干"&#xff1f;为什么有些程序会卡住不动&#xff0c;而另一些却能流畅运行&#xff1f;这一切都取决于阻塞与非阻塞的编程选择&#xff01;本文将为你揭示这两种模式的本质区别&#xff01;…

MySQL 核心操作全解析(用户 + SHOW+DML+DCL)

MySQL 核心操作全解析&#xff08;用户 SHOWDMLDCL&#xff09; 基于你提供的实操笔记&#xff0c;我们将 MySQL 核心操作拆解为用户管理、SHOW 查询命令、DML 数据操作、TRUNCATE 与 DELETE 对比、DCL 权限控制五大模块&#xff0c;梳理语法逻辑、补充避坑提示&#xff0c;帮…

多语言编码Agent解决方案(6)-部署和使用指南

部署和使用指南 本指南提供完整的部署和使用说明&#xff0c;帮助您设置后端服务并在VSCode、Eclipse和IntelliJ中使用相应的插件。这个解决方案基于vLLM提供AI编码辅助&#xff0c;支持英语、中文和日文。 前提条件 操作系统&#xff1a;Linux、macOS或Windows&#xff08;推荐…

滤波器的三重境界:从信号处理到自动驾驶测试的基石

在自动驾驶的宏大叙事中&#xff0c;我们常常聚焦于人工智能、深度学习、高精地图等"明星技术"。然而&#xff0c;在这些耀眼的光环背后&#xff0c;有一个低调却至关重要的"幕后英雄"——滤波器。它不仅是信号处理的工具&#xff0c;更是连接物理世界与数…

Part4.第8章:神经网络

第8章 激活函数 如果没有激活函数&#xff0c;不论几层的神经网络都是一个线性回归。激活函数的作用是引入非线性。

nextjs+shadcn+tailwindcss实现博客中的overview

最近在用nextjsshadcntailwindcss练手&#xff0c;实现一个博客。做到了overView这里&#xff0c;可实现如下效果1.首先要安装tailwindcss&#xff0c;这个在创建项目的时候就安装了。2.然后安装shadcn,官网教程&#xff1a;3.代码如下&#xff1a;import {Card,CardContent } …

Kotlin 高阶语法解析

Kotlin 高级语法深度解析1. 协程&#xff08;Coroutines&#xff09;1.1 基础概念1.挂起和恢复2.协程构建器 (Coroutine Builders)3.协程作用域4.调度器1.2 核心用法1.3 实战示例2. 密封类&#xff08;Sealed Classes&#xff09;2.1 定义与特性2.2 模式匹配2.3 应用场景3. 内联…

9 基于机器学习进行遥感影像参数反演-以随机森林为例

目录 1 读取数据 2 数据预处理 3模型训练 4模型预测 5精度分析 由于回归任务的标签数据获取比较困难,我们这次用水体指数NDWI来模拟作为回归任务的标签,通过随机森林来拟合回归NDWI,其计算公式如下: NDWI = (band3 - band5) / (band3 + band5) 实际情况下需要回归的数…

C++多线程编程:跨线程操作全解析

C中的"线程"通常指单个执行流&#xff08;如std::thread对象&#xff09;&#xff0c;而"多线程"指程序中同时存在多个这样的执行流&#xff0c;并涉及它们的创建、管理和同步。实现跨线程操作的核心在于安全地处理共享数据和线程间通信。 以下是实现跨线程…

【脑电分析系列】第13篇:脑电源定位:从头皮到大脑深处,EEG源定位的原理、算法与可视化

前言脑电信号&#xff08;Electroencephalography, EEG&#xff09;是一种非侵入性的神经成像技术&#xff0c;能够实时捕捉大脑的电活动。然而&#xff0c;头皮上记录到的信号是脑源活动经过头皮、颅骨等介质“模糊”后的投影。想要从这些头皮EEG信号追溯到大脑深处的电活动&a…

MySQL知识笔记

DATE_ADD(date,INTERVAL expr type) date 参数是合法的日期表达式。expr 参数是您希望添加的时间间隔。多查官方手册&#xff01;&#xff01;命令行启动和停止sql服务net start 数据库名&#xff1b; 这是启动服务命令&#xff1b; 例如&#xff1a;net start Mysql56…

2025算法八股——深度学习——MHA MQA GQA

MHA、MQA、GQA 都是深度学习中注意力机制的相关概念&#xff0c;其中 MHA 是标准的多头注意力机制&#xff0c;MQA 和 GQA 则是其优化变体&#xff0c;以下是它们的区别、优缺点介绍&#xff1a;区别MHA&#xff08;多头注意力&#xff09;&#xff1a;是 Transformer 架构的核…

Vue3》》eslint Prettier husky

安装必要的依赖 npm install -D eslint eslint/js vue/eslint-config-prettier prettier eslint-plugin-vue 初始化 ESLint 配置 npm init eslint/config// eslint.config.js // 针对 JavaScript 的 ESLint 配置和规则。保持 JavaScript 代码的一致性和质量 import js from &qu…

Custom SRP - Point and Spot Lights

https://catlikecoding.com/unity/tutorials/custom-srp/point-and-spot-lights/Lights with Limited Influence1 Point Lights1.1 Other Light Data (Point )同方向光一样,我们支持有限数量的 Other Light.尽管场景中可能有很多 Other Lights,可能有超过光源上限的光源时可见的…

hive数据仓库的搭建

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、内嵌模式二、本地模式三、远程模式前言 HIVE是基于HDFS的数据仓库&#xff0c;要首先搭建好HADOOP的集群才可以正常使用HIVE&#xff0c;HADOOP集运搭建详见…

域名SSL证书免费申请lcjmSSL

.-.lcjmSSL&#xff08;又名“来此加密”&#xff09;是一个提供免费SSL证书申请的一站式平台。它支持单域名、多域名以及泛域名证书申请&#xff0c;且单张证书最高可覆盖100个域名&#xff0c;让您轻松实现全站HTTPS加密。为什么您的网站必须安装SSL证书&#xff1f;数据加密…

“能量逆流泵”:一种基于电容阵与开关矩阵的超高效大功率降压架构

摘要本文提出并验证了一种面向大功率降压应用的革命性电源架构——"能量逆流泵"&#xff08;Energy Inversion Pump, EIP&#xff09;。该架构摒弃了传统Buck转换器中的电感元件&#xff0c;通过高速开关矩阵控制的电容阵列&#xff0c;将高压侧能量以"分时、分…

打造精简高效的 uni-app 网络请求工具

在 uni-app 开发中&#xff0c;网络请求是连接前端与后端的核心桥梁。一个设计良好的请求工具能够显著提升开发效率&#xff0c;减少重复代码。本文将分享一个精简版的 uni-app 网络请求工具实现&#xff0c;它保留了核心功能同时保持了足够的灵活性。设计思路一个优秀的网络请…

【面试场景题】交易流水表高qps写入会有锁等待或死锁问题吗

文章目录一、先明确交易流水表的核心特性二、InnoDB的锁机制在流水表写入场景的表现1. 行锁&#xff08;Record Lock&#xff09;&#xff1a;基本不涉及2. 间隙锁&#xff08;Gap Lock&#xff09;与Next-Key Lock&#xff1a;几乎不触发3. 表锁&#xff1a;仅在极端场景出现三…