从0开始C++(三):构造函数与析构函数详解
目录
构造函数
构造函数的基本使用
构造函数也支持函数重载
构造函数也支持函数参数默认值
构造初始化列表
拷贝构造函数
浅拷贝和深拷贝
析构函数
总结
练习一下ヽ( ̄▽ ̄)ノ
构造函数
构造函数的基本使用
构造函数是一种特殊的成员函数,用于创建对象时初始化,写法上有以下要求:
● 函数名称必须与类名完全一样。
● 构造函数不写返回值
● 如果程序员不手动编写构造函数,编译器就会自动添加一个默认无参数的构造函数。
● 手动添加构造函数后,编译器就不会自动添加默认无参构造函数。
class Car
{
private://权限:最私有的权限string brand; // 品牌string modle; // 型号int weight; // 重量
public: // 权限:最开放的权限Car(string b,string m,int w) //手动添加的构造函数{brand=b;modle=m;weight=w;}string get_brand() //外部函数接口{return brand;}string get_modle(){return modle;}int get_weight(){return weight;}
};
int main()
{Car *myCar = new Car; // 创建堆内存对象//cout << Car.brand << endl; //错误,brand是私有成员 不能外部访问cont << Car.get_brand << endl; //可以使用预留的接口访问
}
构造函数也支持函数重载
class Car
{
private://权限:最私有的权限string brand; // 品牌string modle; // 型号int weight; // 重量
public: // 权限:最开放的权限Car(string b,string m,int w) // 有参构造函数{brand=b;modle=m;weight=w;}Car() // 无参构造函数{brand="xiaomi";modle="su7";weight=1500;}string get_brand() // 外部函数接口{return brand;}string get_modle(){return modle;}int get_weight(){return weight;}
};
int main()
{Car *myCar = new Car; // 调用无参构造函数Car *myCar2 = new Car("HuaWei","问界","2000"); // 此时调用有参构造函数}
构造函数也支持函数参数默认值
从第一个设置默认值的变量开始,在其变量之后的所有参数都要加默认值,在他之前的变量可以不加默认值。
class Car
{
private://权限:最私有的权限string brand; // 品牌string modle; // 型号int weight; // 重量
public: // 权限:最开放的权限Car(string b="xiaomi",string m="su7",int w=1500) // 全缺省时,不能和无参构造函数同时存在{brand=b;modle=m;weight=w;}// Car() // 无参构造函数// {// brand="xiaomi";// modle="su7";// weight=1500;// }string get_brand() // 外部函数接口{return brand;}string get_modle(){return modle;}int get_weight(){return weight;}
};
int main()
{Car *myCar = new Car; // 全缺省Car *myCar2 = new Car("问界","M7","2000"); // 此时调用有参构造函数}
构造初始化列表
当构造函数的局部变量与成员变量重名时可以使用构造初始列表的方式区分,此外,使用构造初始化列表还可以给被 const 修饰的成员变量赋值。
class Car
{
private://权限:最私有的权限const string brand; // 品牌string modle; // 型号int weight; // 重量
public: // 权限:最开放的权限Car(string b,string modle,int w):brand(b),modle(modle),weight(w){} // 用构造初始化列表的方式赋值string get_brand() // 外部函数接口{return brand;}string get_modle(){return modle;}int get_weight(){return weight;}
};
int main()
{Car *myCar = new Car("问界","M7","2000"); // 此时调用有参构造函数}
拷贝构造函数
C++的拷贝构造函数是一种特殊的成员函数,用于创建一个对象的副本。它的参数是一个对象的引用,通过这个参数可以将一个对象的值复制给另一个对象。
拷贝构造函数通常在以下情况下被调用:
1、当用一个对象初始化另一个对象时,会调用拷贝构造函数。例如:
class MyClass {
public:MyClass(const MyClass& obj) {// 拷贝构造函数的实现}
};MyClass obj1;
MyClass obj2 = obj1; // 调用拷贝构造函数
2、当将一个对象作为函数参数传递给函数时,会调用拷贝构造函数。例如:
void func(MyClass obj) {// 函数体
}MyClass obj;
func(obj); // 调用拷贝构造函数
3、当函数返回一个对象时,会调用拷贝构造函数。例如:
MyClass func() {MyClass obj;// 对 obj 进行初始化和操作return obj; // 调用拷贝构造函数
}
需要注意的是,默认情况下,C++会生成一个默认的拷贝构造函数,该函数会将对象的所有成员变量进行一一拷贝。但如果类中存在指针或其他资源,需要手动编写拷贝构造函数来处理这些资源的拷贝问题,以防止浅拷贝带来的问题。
浅拷贝和深拷贝
C++中的拷贝操作有浅拷贝和深拷贝两种方式。
浅拷贝是指拷贝对象时,只是简单地将一个对象的数据成员的值复制给另一个对象的对应数据成员,而不会复制指向动态分配内存的指针。这意味着两个指针将指向同一块内存,当其中一个对象释放这块内存时,另一个对象的指针将成为悬空指针。例如:
class MyClass {
public:int* data;MyClass(const MyClass& other) : data(other.data) {// 拷贝构造函数的实现}
};MyClass obj1;
obj1.data = new int(5);MyClass obj2 = obj1; // 浅拷贝delete obj1.data; // 释放内存
cout << *obj2.data; // 可能会输出无效的值
深拷贝是指拷贝对象时,除了复制数据成员的值外,还会为每个指针成员分配一块新的内存,并将源对象的值复制到新的内存中,以确保两个对象之间的指针成员指向不同的内存块。这样即使一个对象释放了内存,另一个对象的指针仍然有效。例如:
class MyClass {
public:int* data;MyClass(const MyClass& other) : data(new int(*other.data)) {// 拷贝构造函数的实现}~MyClass() {delete data;}
};MyClass obj1;
obj1.data = new int(5);MyClass obj2 = obj1; // 深拷贝delete obj1.data; // 释放内存
cout << *obj2.data; // 仍然可以正常输出
析构函数
C++中的析构函数是一种特殊的成员函数,用于在对象的生命周期结束时执行清理操作。析构函数的名称与类的名称相同,前面加上一个波浪号(~)作为前缀,没有返回类型,也没有参数。
析构函数在以下情况下被调用:
- 当对象的作用域结束时,例如,当对象在函数中定义并在函数结束时销毁。
- 当对象是另一个对象的成员,并且该对象的析构函数被调用时。
- 当使用delete关键字显式释放通过new关键字配分的内存时。
析构函数的主要目的是释放对象分配的资源,例如动态分配的内存、打开的文件等。它可以通过在析构函数中使用delete关键字来释放内存,或者通过关闭文件句柄等操作来释放资源。
以下是一个示例,展示了一个类的析构函数的基本用法:
class MyClass {
public:MyClass() {cout << "构造函数被调用" << endl;}~MyClass() {cout << "析构函数被调用" << endl;}
};int main() {MyClass obj; // 创建一个对象// 在此处执行其他操作return 0; // 对象的作用域结束,析构函数被调用
}
当对象的作用域结束时,析构函数将被自动调用,输出如下结果:
构造函数被调用
析构函数被调用
需要注意的是,如果类中使用了动态分配的内存或其他资源,在析构函数中应该对这些资源进行释放,以避免内存泄漏或资源泄漏的问题。
总结
构造函数 | 析构函数 |
创建对象时手动调用 | 当对象销毁时,自动调用 |
函数名称是类名 | 函数名称是~类名 |
构造函数可以重载 | 析构函数没有参数,不能重载 |
用于创建对象时并初始化 | 用于销毁对象时释放资源 |
有返回值但是不写,返回值是新创建的对象 | 没有返回值 |
练习一下ヽ( ̄▽ ̄)ノ
写一个Dog类,要求有性别、年龄和品种三个属性,属性值封装,使用构造函数传参初始化。增加函数Dog* birth(const Dog& d),在函数体内部判断d与当前狗对象的属性值,当满足以下条件时,返回新创建的狗对象:
● 两条狗的年龄2-5
● 一公一母
新创建的狗对象的属性满足以下条件:
● 年龄:1岁
● 性别:随意
● 品种:
○ 如果父母的品种一样,品种就是父母的品种
○ 如果父母的品种不一样,品种是父母品种的拼合(自己制定拼合逻辑,或者直接是父母的品种之一)
如果两条狗不能生育,返回NULL。
参考代码
#include <iostream>
#include<string.h>
#include<time.h>
using namespace std;class Dog
{
private:int sex; //0母 1公int age; //小于2或大于5不能生育char *variety=new char[20];public:Dog(int s,int a,char *v){if(s==3) // 性别随机{sex=time(NULL)%2;}else{sex=s;}age=a;strcpy(variety,v);}Dog* brith(const Dog &D){if(sex != D.sex){if( age < 2 || age > 5 || D.age < 2 || D.age > 5 ){return NULL;}Dog* NewDog = new Dog(3,1,D.variety);return NewDog;}return NULL;}int get_sex(){return sex;}int get_age(){return age;}char *get_variety(){return variety;}};int main()
{int sex,age;char variety[20];while(1){cout << "请输入狗A的 性别(0:母 1:公) 年龄 品种" << endl;cin >> sex >> age >> variety;Dog dogA(sex,age,variety);cout << "请输入狗B的 性别(0:母 1:公) 年龄 品种" << endl;cin >> sex >> age >> variety;Dog dogB(sex,age,variety);Dog* NewDog=dogB.brith(dogA);if(NewDog==NULL){cout << "dogA和dogB无法生育" << endl;continue;}cout << "小狗的属性:" << endl;cout << "sex:" << NewDog->get_sex() << endl;cout << "age:" << NewDog->get_age() << endl;cout << "variety:" << NewDog->get_variety() << endl;}return 0;
}
相关文章:

从0开始C++(三):构造函数与析构函数详解
目录 构造函数 构造函数的基本使用 构造函数也支持函数重载 构造函数也支持函数参数默认值 构造初始化列表 拷贝构造函数 浅拷贝和深拷贝 析构函数 总结 练习一下ヽ( ̄▽ ̄)ノ 构造函数 构造函数的基本使用 构造函数是一种特殊的成…...

行车记录仪文件夹“0字节”现象解析与恢复策略
一、行车记录仪文件夹“0字节”现象描述 行车记录仪作为现代驾驶中的必备设备,其储存的视频数据对于事故记录和取证至关重要。然而,有时车主们可能会遇到这样一个问题:行车记录仪的某个文件夹内的文件突然变成了0字节大小,无法正…...

呼叫中心系统的功能都有哪些?okcc呼叫中心pscc磐石云呼叫系统部署
当前电话营销普及到各行各业,方便快捷成了大部分企业在宣传自己公司的产品时必用的一种营销方式,但是电话营销在管理上也存在许多问题。例如:销售员与客户沟通前,未能详细了解客户的资料;多名销售员重复拨打同一个客户…...

2024.06.08校招 实习 内推 面经
绿*泡*泡VX: neituijunsir 交流*裙 ,内推/实习/校招汇总表格 1、提前批 | 中电锦江2025届提前批招聘 提前批 | 中电锦江2025届提前批招聘 2、实习 | 国电电力2025届暑期实习生计划启动! 实习 | 国电电力2025届暑期实习生计划启动&#x…...

Polyplus——转染试剂专业供应商
PolyPlus-transfection是一家专业的转染试剂研发和生产的生物技术公司,拥有20年的的转染试剂研发经验,通过创新的核酸转染解决方案支持基因和细胞治疗、生物制剂制造和生命科学研究。目前已经通过了ISO 9001: 2000质量体系认证,已经开发了一系…...

微服务架构-线上治理、线下治理与架构演进
目录 一、线上治理 1.1 概述 1.2 线上预案体系 1.2.1 概述 1.2.2 变更引起的故障 1.2.3 流量和容量变化引起的故障 1.2.4 依赖故障 1.2.5 机房、网络等硬件和环境故障 1.2.6 其他 1.2.7 故障的场景化 1.3 基于Metric的预案自动触发 1.4 治理参数动态调整 1.4.1 举例…...

网络安全:什么是SQL注入
文章目录 网络安全:什么是SQL注入引言SQL注入简介工作原理示例代码 攻击类型为什么SQL注入危险结语 网络安全:什么是SQL注入 引言 在数字化时代,数据安全成为了企业和个人最关心的问题之一。SQL注入(SQL Injection)是…...

从零开始精通Onvif之网络配置
💡 如果想阅读最新的文章,或者有技术问题需要交流和沟通,可搜索并关注微信公众号“希望睿智”。 概述 网络配置是Onvif规范中的重要组成部分,允许用户通过网络远程配置和管理设备的网络设置,比如:DHCP、IP地…...

在 macOS 上使用 Homebrew 安装和配置 Python 及 Tk 库
在 macOS 上,系统自带的 /usr/bin/python3 版本较旧,且直接升级系统自带的 Python 版本可能会影响系统稳定性。因此,推荐使用 Homebrew 来安装和管理 Python 及其相关库。本文将详细介绍如何通过 Homebrew 安装和配置 Python 3 及 Tk 库&…...

【机器学习 复习】第2章 线性回归及最大熵模型
一、概念 1.回归就是用一条曲线对数据点进行拟合,该曲线称为最佳拟合曲线,这个拟合过程称为回归。 2.一个自变量 叫 一元线性回归,大于一个自变量 叫 多元线性回归。 (1)多元回归:两个x,一个…...

关于椭圆的方程(有Python画的动图)
关于椭圆的方程(有Python画的动图) flyfish 几何定义 椭圆是平面上所有到两个固定点(焦点)的距离之和为常数的点的集合。这两个固定点叫做焦点。 解析几何描述 设椭圆的两个焦点为 F 1 F_1 F1 和 F 2 F_2 F2ÿ…...

selenium常见难点解决方案
勾选框勾选问题 勾选框代码逻辑实现过程: 第一步:首先找到勾选框的元素; 第二步:检查它是否已经被勾选。如果已经勾选,则进行取消勾选操作;如果未勾选,则进行点击勾选操作; 以下是一…...

【Python高级编程】 综合练习-使用OpenCV 进行视频数据处理
综合练习 读取一个视频文件,对其进行处理后保存为一个新的视频文件。具体的处理步骤包括调整帧大小、转换为灰度图像、垂直翻转画面以及添加高斯噪声。 下面是代码的详细实现: import cv2 import numpy as np# 定义一个函数,用来给图像添加…...

rs232和can的区别
在电机通讯和升级固件时我们经常用到RS232和CAN两种通讯模式,那这两种有何不同吗? RS232和CAN的主要区别在于通信方式、应用场景、传输距离、通信速度以及网络结构。 通信方式: RS232是一种串行通信接口标准,支持全双工通信&…...

嵌入式软件stm32面试
一、STM32的内核型号有哪些? STM32系列是STMicroelectronics(意法半导体)生产的基于ARM Cortex-M内核的微控制器产品线。这些产品按照不同的内核架构和性能特点分为了主流产品、超低功耗产品和高性能产品。 1.1 主流产品 STM32F0 系列&…...

【Git】-- 添加公钥到 github 或者gitlab上
仅针对系统:mac os 、 unix、linux 1、检查是否有 id_rsa.pub $ cd ~ $ ls -al ~/.ssh 注意:若已有 id_rsa.pub,则必要执行 第二步,避免覆盖掉原有正常的公钥。 配置多个 git 账号请参考:同一台电脑配置多个git账…...

Vue页面生成PDF后调起浏览器打印
一、安装依赖 首先,需要安装 html2canvas 和 jsPDF 库。 npm install html2canvas jspdf二、创建公共方法引入 在utils文件夹下创建两个文件分别为pdfExport.js和printPDF.js,代码如下: pdfExport.js import html2canvas from html2canv…...

纯前端实现导出excel
项目背景: vue2 插件: xlsx;xlsx-style;file-saver 说明: 单独使用 xlsx插件,也可以将网页上的table导出成excel,但是导出的excel,没有样式 结合xlsx-style;file-saver&a…...

QT windows 5.12.0 安装包
这个是在线包,需要有账号的。 没有也没事,安装界面可以现场注册 百度网盘链接: 链接:https://pan.baidu.com/s/1QvXDert4b94GbUfD2f2G4g?pwd8888 提取码:8888...

改进YOLOv7 | 在 ELAN 模块中添加【Triplet】【SpatialGroupEnhance】【NAM】【S2】注意力机制 | 附详细结构图
改进 YOLOv7 | 在 ELAN 模块中添加【Triplet】【SpatialGroupEnhance】【NAM】【S2】注意力机制:中文详解 1. 简介 YOLOv7 是目前主流的目标检测算法之一,具有速度快、精度高的特点。但 YOLOv7 的原始模型结构中缺乏注意力机制,导致模型对全…...

windows系统停止更新办法
windows系统停止更新 双击启动下载的文件 然后再回到系统-更新这里,选择日期就行。...

数据标注概念
数据标注的步骤 数据清洗:处理数据中的噪声、缺失值和异常值,确保数据的质量和完整性。 数据转换:将数据从原始格式转换为适合机器学习模型处理的格式。 数据标注:根据应用需求,为数据添加标签或注释,标识…...

网络安全复习笔记
概述 要素 CIA:可用性;完整性;保密性。 可控性;不可否认性;可审查性。 攻击 被动:窃听 - 保密性;监听 - 保密性主动:假冒 - 完整性;重放 - 完整性;改写 -…...

Laravel - excel 导入数据
在Laravel中,可以使用maatwebsite/excel这个库来处理Excel文件的导入。 1.用命令行窗口打开项目根目录,使用 Composer 安装 maatwebsite/excel composer require maatwebsite/excel --ignore-platform-reqs 在你的config/app.php文件中注册服务提供者&…...

移动语义和完美转发
C11 引入了许多新特性,使得编写高效且现代的 C 代码变得更加容易。其中,移动语义(Move Semantics)和完美转发(Perfect Forwarding)是两个重要的特性,极大地提升了 C 的性能和灵活性。 移动语义…...

【IDEA】Spring项目build失败
通常因为环境不匹配需要在file->projectstructure里面调整一下。...

【无标题】安卓app 流量
该工具可以用于安卓app 流量,内存,cpu,fps等专项内容测试,并且有整机内存,cpu对比,还可监控手机网速,app流量,数据导出等功能,重点还是免费,毕竟PerfDog收费了…...
国产化ETL产品必备的特性(非开源包装)
ETL负责将分布的、异构数据源中的数据如关系数据、平面数据文件等抽取到临时中间层后进行抽取、清洗(净化)、转换、装载、标准、集成(汇总)...... 最后加载到数据仓库或数据集市中,成为联机分析处理、数据挖掘的基础。…...

flink 操作mongodb的例子
Apache Flink 是一个流处理和批处理的开源框架,它通常用于处理大量数据流。然而,Flink 本身并不直接提供对 MongoDB 的原生支持,因为 MongoDB 是一个 NoSQL 数据库,而 Flink 主要与关系型数据库(如 JDBC 连接器&#x…...

【笔记】打卡01 | 初学入门
初学入门:01-02 01 基本介绍02 快速入门库处理数据集网络构建模型训练保存模型加载模型打卡-时间 01 基本介绍 MindSpore Data(数据处理层) ModelZoo(模型库) MindSpore Science(科学计算),包含…...