析构和友元函数

1. 类的析构函数

析构函数的作用,用于释放该类所占用的资源(或者说释放对象)在类的对象使用完时(当类的对象超出了作用域),会自动调用析构函数;如果是在堆区实例化的对象,那么当手动释放对象时,会自动调用析构函数

析构函数的原型:~类名()  //析构函数{}
例如:
~People() {//释放指针占用的空间delete p;}

2. 友元

C++提供友元目的是给类的外部提供一个访问类的私有成员的接口,即可以通过友元访问类的私有成员

友:friend

2.1 友元函数

将一个类的成员函数可不可以声明为另外一个类的友元?一个类的成员函数声明为另外一个类的友元,可不可以访问另外一个类的私有成员?

编译器提示错误:不可访问

关键字:friend
格式:friend  函数返回值   函数名(参数列表); //声明一个友元函数
例如:friend  void  function();//function函数是一个友元函数

注意:

友元函数属不属于类的成员?友元函数不是类的成员函数

friend_main.cpp

//友元函数
class People {
public://将function函数声明为People的友元//注意:友元函数不是类的成员函数friend void function(People& people);private:int a=10;//普通类型变量
};//定义一个函数去访问a,因为a是类中私有,一般是访问不到的
//所以我们需要将此函数在类中声明为友元函数
void function(People& people) {cout << "友元函数访问到a = " << people.a << endl;
}int main()
{People people1;function(people1);return 0;
}

2.1.2  练习

使用类和对象以及友元实现算数表达式的求值

例如:2+5+6 -4+4-40的和

main5.cpp
#include "iostream"
using namespace std;//使用类和对象以及友元实现算数表达式的求值
//例如:
//2 + 5 + 6 - 4 + 4 - 40的和class Jia
{
public://构造函数,给属性赋值Jia(int m, int n){a = m;b = n;}//声明友元函数friend void jiaFa(int a1, Jia& jia);void print(){cout << "temp=" << temp << endl;}//声明友元函数friend void update_a(Jia& jia, int a1);int temp;//临时存储结果,方便减法加法之间传递private:int a;int b;
};//加法
void jiaFa(int a1, Jia& jia)
{jia.b = a1;jia.a = jia.a + jia.b;//我们使用a来临时存储结果jia.temp = jia.a; //因为a是私有的在做减法时,需要将之前的结果传递给减法所以我们取出a的值给tmp,时tmp为公有方可传递给减法
}//更新a的值
void update_a(Jia& jia, int a1)
{jia.a = a1;
}class Jian
{
public://声明友元函数friend void jianFa(int a1, int b1, Jian& jian);int temp;//临时存储结果,方便减法加法之间传递
};//减法
void  jianFa(int a1, int b1, Jian& jian)
{jian.temp = a1 - b1;
}int main()
{Jia jia(2, 5);jiaFa(5, jia);jiaFa(6, jia);jia.print();Jian jian;jianFa(jia.temp, 4, jian);//jian.temp=9update_a(jia, jian.temp);//更新a的值,使a中的临时结果,保持最新jiaFa(4, jia);jianFa(jia.temp, 40, jian);cout << "最终的结果:" << jian.temp << endl;return 0;
}

2.2 友元类

关键字:friend
格式:friend  class   类名;   //将类声明为友元
例如:friend class People; 

friend_main.cpp

//友元类
class People {
public://将function函数声明为People的友元//注意:友元函数不是类的成员函数friend void function(People& people);//将Animal声明为友元类friend class Animal;private:int a = 10;//普通类型变量
};class Animal {
public:void print(const People& people) {cout << "animal类中访问到a = " << people.a << endl;}
};//定义一个函数去访问a,因为a是类中私有,一般是访问不到的
//所以我们需要将此函数在类中声明为友元函数
void function(People& people) {cout << "友元函数访问到a = " << people.a << endl;
}int main()
{People people1;function(people1);//友元函数访问Animal animal;animal.print(people1);//友元类访问return 0;
}

3. 经典问题

3.1 构造函数和普通函数的区别:

(1)目的:

构造函数用于在对象被创建时初始化对象的成员变量。它确保对象在被使用之前处于一个合适的状态。

普通函数用于执行一般的任务和操作,它们不关心对象的创建和销毁。

(2)调用时机:

构造函数在对象创建时自动调用,无需显式调用。它们确保对象在被使用前处于有效状态。

普通函数需要在代码中显式调用。

(3)返回类型:

构造函数没有返回类型,包括没有 void。它们只是在对象创建时执行,初始化对象的状态。

普通函数有返回类型,可以返回一个值。

(4)命名:

构造函数的名称与类的名称相同。

普通函数有自定义的名称。

(5)用法:

构造函数主要用于初始化对象的状态,通常包括分配资源、设置默认值等。

普通函数可以执行各种任务,而不涉及对象的创建和销毁。

3.2 析构函数和普通函数的区别:

(1)目的:

析构函数用于在对象被销毁时释放资源、清理对象状态。

普通函数执行一般任务,通常不涉及对象的销毁。

(2)调用时机:

析构函数在对象生命周期结束时自动调用,无需显式调用。

普通函数需要在代码中显式调用。

(3)返回类型:

析构函数没有返回类型,包括没有 void。它们只是在对象销毁时执行清理操作。

普通函数有返回类型,可以返回一个值。

(4)命名:

析构函数的名称与类的名称相同,但前面有一个波浪线 ~。

普通函数有自定义的名称。

(5)用法:

析构函数主要用于释放对象在其生命周期中分配的资源,如动态分配的内存、打开的文件等。

普通函数可以执行各种任务,而不涉及对象的销毁。

3.3 malloc/new和free/delete的区别

    malloc: 

是一个函数。

用于分配一块指定大小的内存块。

返回 void* 类型的指针,因此在使用时通常需要显式地进行类型转换。(需要手动进行类 型转换

不会调用对象的构造函数或析构函数,因为它主要用于分配原始内存。

    new: 

只是一个操作符。

用于在堆上创建一个对象,并调用对象的构造函数。

返回具体类型的指针,不需要显式类型转换。

用于在堆上创建一个对象,并调用对象的构造函数。

    free: 

是一个函数。

用于释放先前由 malloc 分配的内存。

    delete: 

是一个操作符。

用于释放先前由 new 创建的对象,并调用对象的析构函数。

会调用对象的析构函数,用于对象的清理和资源释放。

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

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

相关文章

Redis 持久化—RDB

文章目录 1. 为什么需要Redis持久化&#xff1f;2. Redis持久化的几种方式3. RDB简介4. 持久化触发4.1 手动触发4.1.1 save命令4.1.2 bgsave 命令 4.2 自动触发4.2.1 save m n4.2.2 flushall4.2.3 主从同步触发 5. 配置说明6. 配置配置7. 配置配置8. RDB 文件恢复9. RDB 优缺点…

如何计算非线性负载的功率需求?

非线性负载的功率需求计算是一个相对复杂的过程&#xff0c;因为非线性负载的电流和电压之间的关系不是简单的正比关系。在计算非线性负载的功率需求时&#xff0c;需要考虑负载的特性、工作状态以及电源电压等因素。 确定负载的类型&#xff1a;首先需要了解负载的具体类型&am…

基于Kettle开发的web版数据集成开源工具(data-integration)-部署篇

目录 &#x1f4da;第一章 前言&#x1f4d7;背景&#x1f4d7;目的&#x1f4d7;总体方向 &#x1f4da;第二章 下载编译&#x1f4d7;下载&#x1f4d7;编译 &#x1f4da;第三章 部署&#x1f4d7;准备工作&#x1f4d5; 安装数据库&redis&consul&#x1f4d5; 修改…

四则运算 C语言xdoj20

问题描述&#xff1a; 输入两个整数和一个四则运算符&#xff0c;根据运算符计算并输出其运算结果&#xff08;和、差、积、商、余之一&#xff09;。注意做整除及求余运算时&#xff0c;除数不能为零。 输入说明&#xff1a; 使用scanf()函数输入两个整数和一个运算符&#xf…

Application layer

title: 应用层 date: 2023-12-20 21:03:48 tags: 知识总结 categories: 计算机网络 应用层&#xff1a;负责最直观的应用请求的封装、发起 一、域名系统DNS 连接在互联网上的主机不仅有IP地址&#xff0c;还有便于用户记忆的主机名字。域名系统DNS能够把互联网上的主机的名字…

Wireshark本地回环网络抓包

背景 因为发往本机的数据包是通过回环地址的&#xff0c;即&#xff1a;数据包不会通过真实的网络接口发送&#xff0c;因此我们需要通过设置路由规则来让本来发到虚拟网络接口的数据包发送到真实网络接口即可。 场景描述&#xff1a;在网络程序开发的过程中&#xff0c;有时…

深入理解可变参数

1.C语言方式 1.1.宏介绍 C语言中的可变参数是指函数可以接受可变数量的参数。这些参数的数量在编译时是未知的。在这些可变参数中的参数类型可以相同&#xff0c;也可以不同&#xff1b;可变参数的每个参数并没有实际的名称与之相对应&#xff0c;用起来是很灵活&#xff1b;…

Docker安装sentinel控制台

1、拉取镜像&#xff0c;直接使用run命令&#xff0c;如果说本地没有镜像就会直接去远程仓库拉取&#xff1a; docker run -d \ -p 8858:8858 \ --name sentinel-dashboard \ --network demo \ -e AUTH_USERNAMEsentinel \ -e AUTH_PASSWORD123456 \ bladex/sentinel-dashboa…

听GPT 讲Rust源代码--compiler(7)

File: rust/compiler/rustc_infer/src/infer/sub.rs 文件rust/compiler/rustc_infer/src/infer/sub.rs是Rust编译器的类型推断模块的一部分&#xff0c;它包含了类型推断的具体实现。 类型推断是编程语言中的重要步骤&#xff0c;它通过分析代码中的上下文信息来确定变量、表达…

清风数学建模笔记-时间序列分析

内容&#xff1a;时间预测分析 一.时间序列 1.时点时间序列 2.时期时间序列&#xff1a;可相加 二.时间趋势分解 1.季节趋势 拓展&#xff1a;百度指数&#xff1a; 2.循环变动趋势&#xff08;和季节很像但是是以年为单位&#xff09; 3.不规则变动趋势&#xff08;像扰…

跨国公司为什么要部署SD-WAN

随着全球化进一步加深&#xff0c;越来越多的企业开始实施跨国战略&#xff0c;但要在各个地区建立分支机构、数据中心&#xff0c;跨国企业可能会遇到各地区之间网络性能差异大、导致数据传输效率低下的问题&#xff0c;而且由于网络场景复杂&#xff0c;网络设备和运维成本高…

jmeter使用心得(一)

jmeter作为接口测试的常用工具之一&#xff0c;在我们的测试中经常会用到&#xff0c;往期的文章中&#xff0c;我们也分享过jmeter的各种功能和用法&#xff0c;基本覆盖了方方面面&#xff0c;可以满足各种接口测试的需求。但实际测试中我们也会发现&#xff0c;jmeter这么强…