C++学习笔记:构造函数和析构函数

 

 

前言:在日常生活中,我们用的电子产品基本都有出厂设置,方便我们使用。当我们不再使用,更或者拿它换剪刀换不锈钢盆时候,我们会把手机里的信息清空来保证我们的浏览器记录不会泄露,毕竟要留清白在人间。而在C++中,对象的初始化和清理也是两个非常重要的问题,因此有了构造函数和析构函数

文章目录

一:使用构造函数和析构函数的目的是什么?

二、认识构造函数和析构函数

1.定义

2.语法格式

构造函数的语法

析构函数的语法

3.构造函数的分类

无参构造函数(默认构造函数):

有参构造函数

拷贝构造函数

4.三种调用方法

括号法

显示法

隐式转换法

5.构造函数调用规则

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


 

 

 

 

 

 

 

 

 

 

 

一:使用构造函数和析构函数的目的是什么?

C++的面向对象来源与生活,每个对象也有初始设置 以及 对象销毁前的清理数据的设置(即对象的初始化销毁),在C++里利用了构造函数和析构函数解决上述问题

二、认识构造函数和析构函数

1.定义

  • 构造函数:主要作用在于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无需手动调用。
  • 析构函数:主要作用在于对象销毁前系统自动调用,执行一些清理工作,同样由编译器自动调用,无需手动调用。

2.语法格式

从函数的角度讲其语法格式:即返回值类型,函数名,参数,函数使用方法

构造函数的语法

类名(){}

1.构造函数没有返回值,也不写void。

2.构造函数的函数名与类名相同;

3.构造函数可以写参数,因此可以发生重载(有参数就成为有参构造函数,后边介绍构造函数分类会讲到)

4.程序在调用对象时会自动调用构造,无需手动调用,且自动调用一次

析构函数的语法

~类名(){}

1.析构函数没有返回值,也不写void。

2.构造函数的函数名与类名相同,不过需在名称前加符号~

3.在参数这点,析构函数与构造函数不同,析构函数不可以有参数

4.程序在对象销毁前会自动调用析构,无需手动调用,且自动调用一次

3.构造函数的分类

总体就三类:默认构造函数,有参构造函数,拷贝构造函数

两种分类方式:

        按参数分:有参构造函数(后两种)和无参构造函数(第一种)

        按类型分:普通构造函数(前两种)和拷贝构造函数(第三种)

注意:1.如果我们不提供构造和构析,编译器会提供

           2.编译器提供的构造函数和构析函数是空实现

空实现:如果定义函数时只给出一对花括号{}而不给出其局部变量和函数体语句,则称该函数为“空函数”。简单来说:啥也不是。

无参构造函数(默认构造函数):

class Person
{
public:
	Person()
	{
		cout << "无参构造函数的调用" << endl;
	}
	
	~Person()
	{
		cout << "构析函数的调用" << endl;
	}
	int age;
};

有参构造函数

class Person
{
public:
	
	Person(int a)
	{
		age = a;
		cout << "有参构造函数" << endl;
	}
	
	~Person()
	{
		cout << "构析函数的调用" << endl;
	}
	int age;
};

拷贝构造函数

class Person
{
public:
	Person()
	
	Person(const Person& p)
	{
		age = p.age;
		cout << "拷贝构造函数的调用" << endl;
	}
	~Person()
	{
		cout << "构析函数的调用" << endl;
	}
	int age;
};

4.三种调用方法

分别是括号法、显示法隐式转换法。

下面用这三种方法来调用三种已经讲过的三种构造函数

class Person
{
public:
	Person()
	{
		cout << "无参构造函数的调用" << endl;
	}
	Person(int a)
	{
		age = a;
		cout << "有参构造函数" << endl;
	}
	Person(const Person& p)
	{
		age = p.age;
		cout << "拷贝构造函数的调用" << endl;
	}
	~Person()
	{
		cout << "构析函数的调用" << endl;
	}
	int age;
};

括号法

//括号法
void test01()
{
	Person p;
	Person p2(10);
	Person p3(p2);
}

显示法

//显示法
void test01()
{
	Person p1;
	Person p2 = Person(10);
	Person p3 = Person(p2);
}

隐式转换法

//隐式转换法
void test01()
{
	Person p4 = 10; //相当于Person p4 = Person(10);系统会自动给你转成显示法
	Person p5 = p4;
}

1.使用括号法调用默认函数时,不可加(), 如Person p1();系统会以为你这是函数的一个声明,返回值为Person、名称为p1、无参数,不会认为你是在创建对象

2.当Person(10)放在等式左边时,为匿名对象。对于匿名对象,在当前行执行结束后系统立即回收匿名对象

3.不要利用拷贝构造函数初始化匿名对象:Person(p3);,编译器会认为Person (p3) == Person p3;这相当于你在实例化一个对象p3,若此时你上边已经有一个p3的话会重定义。

5.构造函数调用规则

默认情况下:编译器至少给一个类添加四个函数:

1.默认构造函数(空实现)

2.默认析构函数(空实现)

3.默认拷贝构造函数

4.赋值运算符operator=,对属性进行值拷贝


非默认的调用规则:
 如果用户定义有参构造函数,C++就不再提供默认无参构造,但是会提供默认拷贝构造
 如果用户定义拷贝构造函数,C++就不会再提供其他构造函数
此处读者可把前边定义的三个构造函数,依照调用规则,删除一些并运行一下,看编译器在两种情况下提供的构造函数各自有哪些

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

1.使用一个已经创建完毕的对象来初始化一个新对象

//使用一个已经创建完毕的对象来初始化一个新对象;
void test01()
{
	Person p1(20);//有参构造
	Person p2(p1);//拷贝构造的使用
	cout << "p1:" << p1.m_Age << endl;
	cout << "p2:" << p2.m_Age << endl;
}

2.值传递的方式给函数参数传值

void doWork(Person p) 
{	
}

void test02()
{
	Person p;
	doWork(p);
}

3.以值方式返回局部对象

//dowork2中,返回值并不是p1,而是p1的一个拷贝值
//我们可以输出p和p1的地址,会发现两个地址不同

Person doWork2() {

	Person p1;
	cout << (int*)&p1 << endl;
	return p1;

}

void test03() {

	Person p = doWork2();
	cout << (int*)&p<< endl;

}


以上就是今天要讲的内容,本文介绍了构造函数和析构函数的相关知识点

如果帮到了你,可以点一个关注,后续学习笔记将每日更新哦。

也可以留下一个赞,你的赞是笔者更新的动力

如果文章有用的话,也可以收藏起来,代表自己学习过的痕迹,这块知识点遗忘时候可以方便查看 

 

你可能感兴趣的:(C++学习笔记,学习,笔记,c++)