【C++】类和对象-类的成员函数

类的默认六个成员函数

在对象的存储方式和this指针那节中,测试发现空类的大小为1,那么空类中真的什么都没有吗?
其实不是的,在类中什么都不写的时候,编译器会自动生成6个默认的成员函数。
默认的成员函数:当用户没有显式定义的时候,编译器会自动生成的成员函数。在这里插入图片描述

构造函数

构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成员都有 一个合适的初始值,并且在对象整个生命周期内只调用一次。

那么就有一个问题,为什么要设置这样的一个构造函数呢?
如果当前有这样一个Data类,这个类当中有一个Init初始化函数,若我们每次创建一个对象的时候,就必须都要调用这个Init函数对对象进行初始化,这样会非常麻烦,因此我们就需要有一个构造函数,使得我们在创建对象的时候,不需要调用任何函数,就可以实现对对象的初始化。

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.Init(2022, 7, 5);
 	d1.Print();
 	Date d2;
 	d2.Init(2022, 7, 6);
 	d2.Print();
	return 0;
}

我们需要按照要求,去定义构造函数,函数名称和类名相同,函数不能有返回值,但是可以有不同的参数,从而可以实现重载,并且形参可以使用缺省参数。

class Date
{
public:
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;
};

此外,当我们并没有显式定义构造方法,编译器会自动生成一个默认的构造方法,生成的默认构造方法有两个特点:

1.并不会初始化内置类型的变量
2.只会初始化自定义类型的变量(需要注意的是,自定义类型的变量所属的类必须有无参的构造方法,否则就会编译报错)
3.默认的构造方法是无参的

当用户显式定义了构造方法,那么编译器就不会再构造默认的无参构造方法了。
通过上述代码可以发现,当用户没有定义构造方法时,编译器自动定义的默认构造方法也并没有将变量初始化,还是一些随机值,是不是意味着,默认构造方法是没用的?

其实不是没用,类中定义的变量分为内置类型变量和自定义类型变量,默认的构造方法不会对内置类型变量进行初始化,但是默认的构造方法会调用自定义类型变量的类中的默认构造方法,从而对自定义类型变量进行初始化。

注意:::上述的默认构造方法可以是无参的构造函数,全缺省的构造函数,编译器默认生成的构造函数。

析构函数

析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。

那么,也会有同样的问题,我们为什么需要析构函数呢?
实际上,类中可能会有动态申请的内存空间,这些内存空间在对象销毁时如果没有进行释放,那么会造成内存泄漏,如果我们编写一个destroy函数,每次销毁对象时都需要调用这个函数,未免有些麻烦,而且容易忘记。
析构函数就是为我们解决了这个问题,当对象被销毁时,自动调用析构函数释放开辟的空间,防止内存泄漏。


析构函数有一些特点:

1.如果类中没有涉及到资源的管理,析构函数就不需要定义
2.如果涉及到了资源的管理,那么必须要进行析构函数的定义,否则就会出现内存泄漏(因为,用户如果没有定义析构函数,编译器生成的默认析构函数是无法进行资源的释放的)
析构函数没有参数,也没有返回值,不能重载,书写方式是~+类名

这样就会产生和构造函数一样的疑问,编译器生成的默认析构函数并不能对资源进行释放,那么是否意味着默认析构函数就没有用呢?

其实不是的,一个没有涉及到资源管理的对象,如果没有生成默认的析构函数,如果这个对象中存在一些自定义变量,这些自定义变量所属的类却涉及到了资源管理,那么当前类是无法去释放内部的那些自定义变量的资源的(因为当前类中没有其他类的析构函数,无法调用其他类的析构函数),这样岂不是造成内存泄漏了吗?
因此,就需要在当前类中默认生成一个析构函数,目的是在当前对象销毁时,调用析构函数完成内部一些对象的销毁工作

拷贝构造函数

拷贝构造函数:
只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

在c语言中,如果需要创建一个变量,并且给变量赋值,有以下几种方式

int a;
a = 10;

int b = 20;

int c(b);

而在c++中,如果需要创建一个对象,也有以下几种方式

class Data
{
public:
	int _year;
	int _month;
	int _day;
	Data(int year = 2023, int month = 4, int day = 4)
	{
		_year = year;
		_month = month;
		_day = day;
	}
};
Data d1;
d1._year = 2023;
d1._month = 4;
d1._day = 4;

Data d2(2023, 4, 5);

Data d3(d2);

对于前两种创建对象进行初始化的方式我们比较明白了,但是对于第三种方法,到底是如何将d3对象创建出来,并且将d2对象的值拷贝给d3的呢?
这就涉及到了拷贝构造函数

拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型
对象创建新对象时由编译器自动调用。

这里就说明了,拷贝构造函数就是在编译器自动执行,实现创建出来的对象和已有的对象一模一样。

拷贝构造函数有几个特点
1.拷贝构造函数实际上是构造函数的一个重载形式
2.拷贝构造函数的参数只有一个,必须要是类类型对象的引用,使用传值方式时编译器会直接报错,因为会引发无穷递归调用

当用户没有显式定义拷贝构造函数,默认生成的拷贝构造函数按内存存储字节序完成拷贝,而这种拷贝被称为浅拷贝,或者值拷贝。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值