构造函数的初始化、清理及const修饰成员函数

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

构造函数的初始化和清理

1.构造函数和析构函数

构造函数

1.没有返回值,不用写void
2.可以有参数,可以发生重载
3.函数名和类名相同
4.创造对象的时候,编译器自动调用构造函数,而且只调用一次

在这里插入图片描述

析构函数

1.函数名和类名相同,在名称前面加~
2.没有返回值,不用写void
3.不可以有参数,也不可以发生重载(相区别与构造函数)
4.在对象销毁之前,会调用析构函数,而且只调用一次

在这里插入图片描述

总结: 构造函数和析构函数都是必须有的实现,如果我们自己不提供,编译器会自己提供一个空实现的构造和析构。

2.构造函数的分类及调用

无参构造

在这里插入图片描述
当我们创建对象的时候,想要调用无参构造函数,对象后面不可以加()
举个例子:
在这里插入图片描述

有参构造,支持函数重载

在这里插入图片描述
在这里插入图片描述

拷贝构造

在这里插入图片描述

调用方式(括号法,显示法,隐式转换法)

在这里插入图片描述

注意的的点: 不能利用拷贝构造函数来初始化匿名对象,编译器会认为是对象声明, //Person p5(p4)
拷贝构造函数 要加const
我们一般平时用得多的是括号法

3.拷贝构造函数的调用时机

C++拷贝构造函数的调用时机通常有三种情况:

  1. 使用一个创建完毕的对象来初始化一个新的对象
  2. 值传递的方式给函数参数传值
  3. 以值方式来返回局部对象

在这里插入图片描述

4.构造函数调用规则

默认情况下,C++编译器会自动给一个类添加三个函数
1.默认构造函数(无参,函数体为空)
2.默认析构函数(无参,函数体为空)
3.默认拷贝函数(对类里面的属性进行拷贝)

调用规则如下:
1.如果用户定义有参构造函数,那么编译器不会提供无参构造函数,但是会提供拷贝构造函数
2.如果用户自定义拷贝构造函数,那么将无法提供其他构造函数

5.深拷贝和浅拷贝

深拷贝是面试的经典问题,也是常见的一个坑
浅拷贝:简单的赋值操作
深拷贝:在堆区重新new空间,进行拷贝操作
在这里插入图片描述
这就是利用深拷贝解决浅拷贝的问题

//构造函数
class Person
{
public:
	//无参
	Person()
	{
		cout << "调用无参构造函数" << endl;
	}
	//有参
	Person(int a,int high)
	{
		cout << "调用有参构造函数" << endl;
		m_age = a;
		m_high = new int(high);
	}
	
	//拷贝构造函数
	Person(const Person& p)
	{
		cout << "调用拷贝构造函数" << endl;
		m_age = p.m_age;
		//利用深拷贝在堆区重新开辟一个空间,避免内存重复释放
		m_high = new int(*p.m_high);
	}
	//析构
	~Person()
	{
		cout << "调用析构函数" << endl;
	if (m_high != NULL)
	{
		delete m_high;
		}
	}
	
public:
	int m_age;
	int* m_high;
};

int main()
{
	Person p1(18, 180);
	Person p2(p1);
	cout << "年龄:" << p1.m_age << "身高" << *p1.m_high << endl;
	cout << "年龄:" << p2.m_age << "身高" << *p2.m_high << endl;
	return 0;
}

在这里插入图片描述
成功调用两个析构函数,完美解决问题。

总结: 如果属性中有需要用到堆区开辟空间的,自己定义拷贝构造函数,防止浅拷贝带来的问题

6.初始化列表

功能:用来初始化类型属性
语法:构造函数():属性1(值1),属性2(值2),属性3(值3)…{}

在这里插入图片描述

7.类对象作为类成员

顾名思义:C++类中的成员可以是另一个类的对象,我们称该成员时对象成员
例如:
在这里插入图片描述

在B类中有A类的对象a 那么问题来了,那么当创建B对象时候,A与B的构造和析构的顺序是谁先谁后呢?
代码说话!

class A 
{
public:
	A()
	{
		cout << "调用A默认构造函数" << endl;
	}
	~A()
	{
		cout << "调用A析构函数" << endl;
	}
};

class B
{
	
public:
	B()
	{
		cout << "调用B默认构造函数" << endl;
	}
	~B()
	{
		cout << "调用B析构函数" << endl;
	}
public:
	A a;
};

int main()
{
	B b;
	return 0;
}

在这里插入图片描述

总结:
当B类中存在A类对象,那么在创建B类对象的时候先执行A类对象的默认构造函数,再执行B类的默认构造函数,结束之后,先执行B类的析构函数,再执行A类析构函数
上图:
在这里插入图片描述

8.静态成员

静态成员就是在成员函数或者成员变量前面加上关键字static 静态成员含有的特点:
1.所有对象共享共一份数据
2.在编译截断分配内存
3.类内声明,类外初始化

静态成员变量

在这里插入图片描述

静态成员函数

静态成员函数特点:
1.所有对象共享同一个函数
2.静态成员函数只能访问静态成员变量
![在这里插入图片描述](https://img-blog.csdnimg.cn/01f21e96233e4ccba36e569cd4dd1554.png

const修饰成员函数

常函数:

1.成员函数后面加上const后 我们称这个函数是常函数
2.常函数内不可以修改成员属性
3.成员属性声明时候加上关键组mutable之后,在常函数中依然可以修改

在这里插入图片描述

常对象

1.声明对象前面加上const,称为常对象
2.常对象只能调用常函数
在这里插入图片描述

如有错误,欢迎各位大佬指点!

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值