我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C++修炼之构造函数与析构函数

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C++修炼之构造函数与析构函数

?默认成员函数

上一章中我们谈到,如果一个类中什么成员也没有,那么这个类就叫作空类。其实这么说是不太严谨的,因为一个类不可能什么都没有

当我们定义好一个类,不做任何处理时,编译器会自动生成以下6个默认成员函数

  • 默认成员函数:如果用户没有手动实现,则编译器会自动生成的成员函数

  • 构造函数:主要完成初始化工作;

  • 析构函数:主要完成清理工作;

  • 拷贝构造:使用一个同类的对象初始化创建一个对象;

  • 赋值重载:把一个对象赋值给另一个对象;

  • 取地址重载普通对象取地址操作;

  • 取地址重载(const):const对象取地址操作;

本章我们将学习两个默认成员函数——构造函数析构函数

?构造函数

?引例

在C语言阶段,我们实现的数据结构时,有一件事很苦恼,就是每当创建一个stack对象(之前叫作定义一个stack类型的变量)后,首先得调用它的专属初始化函数StackInit来初始化对象。

typedef int dataOfStackType;

typedef struct stack
{
	dataOfStackType* a;
	int top;
	int capacity;
}stack;

void StackInit(stack* ps);
//...

 int main()
 {
	 stack s;
	 StackInit(&s);
	 //...
	 return 0;
 }

这不免让人觉得有点麻烦。在C++中,构造函数为我们很好的解决了这一问题。

?构造函数的概念及特性

构造函数是一个特殊的成员函数。构造函数虽然叫作构造,但是其主要作用并不是开辟空间创建对象,而是初始化对象

构造函数之所以特殊,是因为相比于其它成员函数,它具有如下特性

  1. 函数名与类名相同
  2. 无返回值
  3. 对象实例化时,编译器自动调用对应的构造函数
  4. 构造函数可以重载

?举例?

class Date
{
public:
	//无参的构造函数
	Date()
	{};
	//带参的构造函数
	Date(int year,int month,int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

private:
	int _year;
	int _month;
	int _day;
};

void TestDate()
{
	Date d1;//调用无参构造函数(自动调用)
	Date d2(2023, 3, 29);//调用带参构造函数(自动调用)
}

?特别注意?

  • 创建对象时编译器会自动调用构造函数,若是调用无参构造函数,则无需在对象后面使用()。否则会产生歧义:编译器无法确定你是在声明函数还是在创建对象

?错误示例?

//错位示例
Date d3();
  1. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成
class Date
{
public:
	//若用户没有显示定义,则编译器自动生成。
	

private:
	int _year;
	int _month;
	int _day;
};
  1. 默认生成构造函数,对内置类型成员不作处理;对自定义类型成员,会调用它的默认构造函数
  • C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型,如:int、char、double…,自定义类型就是我们使用class、struct、union等自己定义的类型。

?举例?

?默认构造函数对内置类型?

class Date
{
public:
	//此处不对构造函数做显示定义,测试默认构造函数
	

	void print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

private:
	int _year;
	int _month;
	int _day;
};
void TestDate1()
{
	Date d1;
	d1.print();
}

  • 如图所示,默认构造函数的确未对内置类型做处理。

 ?默认构造函数对自定义类型?

class stack
{
public:
	//此处对stack构造函数做显示定义
	stack()
	{
		cout <<"stack()" << endl;
		_a = nullptr;
		_top = _capacity = 0;
	}
private:
	int* _a;
	int _top;
	int _capacity;
};
class queue
{
public:
	//此处不对queue构造函数做显示定义,测试默认构造函数
	
private:
	//自定义类型成员
	stack _s;
};

void TestQueue()
{
	queue q;
}

  • 如图所示,在创建queue对象时,默认构造函数对自定义成员_s做了处理,调用了它的默认构造函数stack()

 这一波蜜汁操作让很多C++使用者感到困惑与不满,为什么要针对内置类型和自定义类型做不同的处理呢?终于,在C++11中针对内置类型成员不初始化的缺陷,又打了补丁,即:

  1. 内置类型成员变量在类中声明时可以给默认值

?举例?

class Date
{
public:
//...
	void print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	//使用默认值
	int _year = 0;
	int _month = 0;
	int _day = 0;
};
void TestDate2()
{
	Date d2;
	d2.print();
}

  • 默认值:若不对成员变量做处理,则使用默认值。
  1. 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个

?举例?

class Date
{
public:
	//无参的默认构造函数
	//Date()
	//{

	//}

	//全缺省的默认构造函数
	Date(int year = 0, int month = 0, int day = 0)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

private:
	int _year = 0;
	int _month = 0;
	int _day = 0;
};

?析构函数

析构函数构造函数的特性相似,但功能有恰好相反。构造函数是用来初始化对象的,析构函数是用来销毁对象的。

  • 需要注意的是,析构函数并不是对对象本身进行销毁(因为局部对象出了作用域会自行销毁,由编译器来完成),而是在对象销毁时会自动调用析构函数,对对象内部的资源做清理(例如stack _s中的int* a)。

同样,有了析构函数,我们再也不用担心创建对象(或定义变量)后由于忘记释放内存而造成内存泄漏了。

?举例?

class Stack
{
public:
	Stack()
	{
		//...
	}
	void Push(int x)
	{
		//...

	}
	bool Empty()
	{
		// ...

	}
	int Top()
	{
		//...
	}
	void Destory()
	{
		//...
	}
private:
	// 成员变量
	int* _a;
	int _top;
	int _capacity;
};

void TestStack()
{
	Stack s;
	st.Push(1);
	st.Push(2);
	//过去需要手动释放
	st.Destroy();
}

?析构函数的特性

  1. 析构函数名是在类名前加上字符 ~
  2. 无参数
  3. 无返回值
  4. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数
  5. 析构函数不能重载

?举例?

class Date
{
public:
	Date()
	{
		cout << "Date()" << endl;
	}
	~Date()
	{
		cout << "~Date()" << endl;
	}
private:
	int _year = 0;
	int _month = 0;
	int _day = 0;
};
void TestDate3()
{
	Date d3;
	//d3生命周期结束时自动调用构造函数
}

为便于观察,我们可以在析构函数内部写点儿东西。

  1. 编译器生成的默认析构函数,对自定类型成员调用它的析构函数

?举例?

class stack
{
public:
	//此处对stack构造函数做显示定义
	stack()
	{
		cout <<"stack()" << endl;
		_a = nullptr;
		_top = _capacity = 0;
	}
	~stack()
	{
		cout << "~Stack()" << endl;
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}
private:
	int* _a;
	int _top;
	int _capacity;
};
class queue
{
public:
	//此处不对queue构造函数做显示定义,测试默认构造函数
	
private:
	//自定义类型成员
	stack _s;
};

void TestQueue1()
{
	queue q;
}

  • 这里可能有小伙伴会好奇:为什么析构函数不像构造函数那样区分内置类型与自定义类型呢
    答案是:因为内置类型压根不需要我们担心清理工作,在其生命周期结束时会自动销毁。而自定义类型需要担心,因为自定义类型里可能含有申请资源(例如:malloc申请内存须手动释放)。
  1. 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如stack

 到此这篇关于C++修炼之构造函数与析构函数的文章就介绍到这了,更多相关C语言 构造函数与析构函数内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C++修炼之构造函数与析构函数

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C++修炼之构造函数与析构函数

本章节我们将学习类的6个默认成员函数中的构造函数与析构函数,并对比C语言阶段的内容来学习它们的各自的特性,感兴趣的同学可以参考阅读
2023-05-14

C++修炼之拷贝构造函数

这篇文章主要内容是6个默认成员函数之一的拷贝构造函数的认识与学习,让同学们充分理解浅拷贝与深拷贝,感兴趣的小伙伴可以参考阅读
2023-05-14

C++构造函数与析构函数怎么使用

这篇文章主要讲解了“C++构造函数与析构函数怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++构造函数与析构函数怎么使用”吧!对象的初始化和清理生活中我们买的电子产品都基本会有出厂
2023-07-02

Python构造函数与析构函数超详细分析

在python之中定义一个类的时候会在类中创建一个名为__init__的函数,这个函数就叫做构造函数。它的作用就是在实例化类的时候去自动的定义一些属性和方法的值,而析构函数恰恰是一个和它相反的函数,这篇文章主要介绍了Python构造函数与析构函数
2022-11-13

C++的构造函数和析构函数是什么

本篇内容主要讲解“C++的构造函数和析构函数是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++的构造函数和析构函数是什么”吧!目录一、构造函数二、C++类的内存模型2.1、只定义成员函数
2023-06-20

C++类与对象及构造函数析构函数基础详解

这篇文章主要为大家介绍了C++类与对象及构造函数析构函数基础详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-05-16

C++ 函数重载是否适用于构造函数和析构函数?

c++++ 构造函数支持重载,而析构函数不支持。构造函数可具有不同的参数列表,而析构函数只能有一个空参数列表,因为它在销毁类实例时自动调用,不需输入参数。C++ 中函数重载是否适用于构造函数和析构函数?引言函数重载允许函数在名称相同的情
C++ 函数重载是否适用于构造函数和析构函数?
2024-04-14

C++中构造函数和析构函数有什么作用

构造函数是一种特殊的成员函数,用于在创建对象时初始化对象的数据成员。构造函数的作用是初始化对象的状态,为对象的数据成员赋初值,确保对象在创建时具有合适的状态。析构函数是一种特殊的成员函数,用于在对象被销毁时清理对象所占用的资源。析构函数的
C++中构造函数和析构函数有什么作用
2024-03-11

C#中构造函数和析构函数的区别是什么

这篇文章将为大家详细讲解有关C#中构造函数和析构函数的区别是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。C#构造函数和析构函数在你可以访问一个类的方法、属性或任何其它东西之前, ***
2023-06-18

C#中构造函数和析构函数的作用是什么

本篇文章给大家分享的是有关C#中构造函数和析构函数的作用是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。C#构造函数(constructor)包括实例C#构造函数和静态C#
2023-06-17

C#如何构造函数

本篇内容主要讲解“C#如何构造函数”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#如何构造函数”吧!CLR Via C#中构造函数是可以将类型实例初始化为有效状态的特殊方法。构造函数在元数据中
2023-06-17

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录