析构和友元函数

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=9

	update_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 创建的对象,并调用对象的析构函数。

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

相关推荐

  1. 函数

    2023-12-30 15:38:05       52 阅读
  2. 【C++】函数

    2023-12-30 15:38:05       62 阅读
  3. 函数详解

    2023-12-30 15:38:05       39 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-30 15:38:05       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-30 15:38:05       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-30 15:38:05       82 阅读
  4. Python语言-面向对象

    2023-12-30 15:38:05       91 阅读

热门阅读

  1. 第22课 类和对象

    2023-12-30 15:38:05       55 阅读
  2. 一个简易的SpringAOP实例

    2023-12-30 15:38:05       55 阅读
  3. C# json 转匿名对象及C#关键字的处理

    2023-12-30 15:38:05       62 阅读
  4. Docker 镜像命令总汇

    2023-12-30 15:38:05       49 阅读
  5. Mysql创建新用户并赋予权限

    2023-12-30 15:38:05       64 阅读
  6. 从C到C++1

    2023-12-30 15:38:05       52 阅读
  7. 每日一练:LeeCode-239. 滑动窗口最大值(难)

    2023-12-30 15:38:05       55 阅读
  8. Mysql子查询 , 内连接

    2023-12-30 15:38:05       51 阅读
  9. 【机器学习前置知识】二项分布

    2023-12-30 15:38:05       51 阅读
  10. ESP32常用库之<WiFi.h>库详解

    2023-12-30 15:38:05       50 阅读
  11. linux iptables简介

    2023-12-30 15:38:05       59 阅读
  12. linux C 线程池

    2023-12-30 15:38:05       52 阅读