首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【C++】构造函数和析构函数详解

【C++】构造函数和析构函数详解

作者头像
zxctscl
发布2024-02-24 09:38:38
发布2024-02-24 09:38:38
5260
举报
文章被收录于专栏:zxctscl个人专栏zxctscl个人专栏

1. 类的6个默认成员函数

如果一个类中什么成员都没有,简称为空类。 空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。 默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。

重点关注前面四个。

2. 构造函数

在写栈或者队列时可能会忘记初始化,就会开始其他操作,所以c++就提出构造函数。

2.1 概念

对于以下Date类:

代码语言:javascript
复制
class Date
{
public:	
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

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

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

int main()
{

	Date d1;
	d1.Print();

	Date d2(2024, 2, 23);
	d2.Print();

	Date d3(2024);
	d3.Print();

	return 0;
}

对于Date类,可以通过 Init 公有方法给对象设置日期,但如果每次创建对象时都调用该方法设置信息,未免有点麻烦,那能否在对象创建时,就将信息设置进去呢? 构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成员都有 一个合适的初始值,并且在对象整个生命周期内只调用一次。

2.2 构造函数特性

构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象。

2.2.1 语法特性

语法定义其特征如下:

  1. 函数名与类名相同。
  2. 无返回值。(这里并不是指void,而是直接不需要写)
  3. 对象实例化时编译器自动调用对应的构造函数。
  1. 构造函数可以重载。
代码语言:javascript
复制
class Date
{
public:
//无参构造函数
	Date()
	{
		_year = 1;
		_month = 1;
		_day = 1;
	}
	
	//带参构造函数
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

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

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

int main()
{

	Date d1;// 调用无参构造函数
	d1.Print();

	Date d2(2024, 2, 23);// 调用带参的构造函数
	d2.Print();

	return 0;
}

还可以直接写成全缺省

代码语言:javascript
复制
class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

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

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

int main()
{
	Date d3(2024);
	d3.Print();

	return 0;
}

还能只传部分参数。

代码语言:javascript
复制
class Date
{
public:
	Date()
	{
		_year = 1;
		_month = 1;
		_day = 1;
	}

	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

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

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

int main()
{

	Date d1;
	d1.Print();
	return 0;
}

无参和全缺省的能不能同时存在呢? 可以,他们构成函数重载。但是实践中不能同时存在,会出现对重载函数调用不明确。 一般情况下不会同时写出来。

2.2.2 其他特性
  1. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。
  2. 关于编译器生成的默认成员函数,很多童鞋会有疑惑:不实现构造函数的情况下,编译器会生成默认的构造函数。但是看起来默认构造函数又没什么用?d对象调用了编译器生成的默认构造函数,但是d对象_year/_month/_day,依旧是随机值。也就说在这里编译器生成的 默认构造函数并没有什么用?? 解答:C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型,如:int/char…,自定义类型就是我们使用class/struct/union等自己定义的类型,看看下面的程序,就会发现编译器生成默认的构造函数会对自定类型成员_t调用的它的默认成员函数。
  3. 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。

我们理解构造函数是默认成员函数,我们不写编译器会生成一个。 所以会认为在不给值时,会自动初始化日期为0或者负一,但是并没有。

代码语言:javascript
复制
class Date
{
public:	
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

private:
	int _year;
	int _month;
	int _day;
};
int main()
{

	Date d1;
	d1.Print();

	return 0;
}
  1. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。

在c++中将数据分为内置类型也叫基本类型,像 int/char/double/指针 ,语言自己自身定义的类型。 还有自定义类型,像struct/class。 在c++98中规定了:默认生成的构造函数,对于内置类型不做处理,自定义类型回去调用他的默认构造。

在C++11 委员会对这个语法进行打补丁, 在声明的位置给缺省值,像这样。

所以分析一个类型成员和初始化需求 需要写构造函数我们就自己写;不需要时就用编译器自己生成的 结论:绝大多数场景下面都需要自己实现构造函数 如果我们没写任何一个构造函数,编译器才会自动生成的,如果我们写了就不会生成了

  1. 关于编译器生成的默认成员函数,很多童鞋会有疑惑:不实现构造函数的情况下,编译器会生成默认的构造函数。但是看起来默认构造函数又没什么用?d对象调用了编译器生成的默认构造函数,但是d对象_year/_month/_day,依旧是随机值。也就说在这里编译器生成的 默认构造函数并没有什么用?? 解答:C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型,如:int/char…,自定义类型就是我们使用class/struct/union等自己定义的类型,看看下面的程序,就会发现编译器生成默认的构造函数会对自定类型成员_t调用的它的默认成员函数。
代码语言:javascript
复制
class Time
{
public:
	Time()
	{
		cout << "Time()" << endl;
		_hour = 0;
		_minute = 0;
		_second = 0;
	}
private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{
private:
	// 基本类型(内置类型)
	int _year;
	int _month;
	int _day;
	// 自定义类型
	Time _t;
};
int main()
{
	Date d;
	return 0;
}
  1. 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。 注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。
代码语言:javascript
复制
class Date
{
public:
	Date()
	{
		_year = 1900;
		_month = 1;
		_day = 1;
	}
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

void Test()
{
	Date d1;
}

3. 析构函数

3.1 概念

通过前面构造函数的学习,我们知道一个对象是怎么来的,那一个对象又是怎么没呢的? 析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-02-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 类的6个默认成员函数
  • 2. 构造函数
    • 2.1 概念
    • 2.2 构造函数特性
      • 2.2.1 语法特性
      • 2.2.2 其他特性
  • 3. 析构函数
    • 3.1 概念
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档