【C++入门篇 - 4】:构造和析构

构造函数

构造函数进行初始化


构造函数,它是一种特殊的函数,主要用来在创建对象时初始化对象,即为对象的成员变量赋初始值。

也可以将对象在创建之初需要执行的逻辑写在构造函数中。

构造函数的特殊性

  1. 没有(不是缺省)函数返回值类型
  2. 函数名和类名相同
  3. 对象存在时会自动调用构造函数,刚好可以帮助完成初始化的功能
  4. 构造函数的调用时机:一个栈区对象产生,一个指针动态一个堆区内存对象产生
  5. 构造函数可以重载,在调用时根据实际调用时给的参数来决定执行哪一个构造函数。构造函数在对象创建时,调用是唯一的。
  6. 构造在没有主动书写的情况下,系统会提供一个隐式的什么都不干的默认构造函数。

代码示例

#include<iostream>

class MyStu
{
private:
	int id;
	int age;
public:
	MyStu() //构造函数
	{
		id = 0;
		age = 123;
		setStuID(id); //函数体内可以再次调用函数
	}
	MyStu(int i, int a)
	{
		id = i;
		age = a;
	}
	void setStuID(int i)
	{
		id = i;
	}
	int getStuID()
	{
		return id;
	}
	int getStuAge()
	{
		return age;
	}

};

void main()
{
	MyStu m(208, 18); // 对象产生,栈区的对象产生 -- 会触发构造函数
	printf("m 的id=%d, age=%d\n", m.getStuID(), m.getStuAge());

	MyStu *pm; //这个不是对象,叫对象指针
	pm = new MyStu(209, 20); //这个也是对象,堆区的无名对象产生 -- 会触发构造函数
	printf("pm 的id=%d, age=%d\n", pm->getStuID(), pm->getStuAge());

	MyStu m1[10]; //对象数组。数组中在初始化每一个元素时会调用默认无参构造
}

运行结果

在这里插入图片描述

拷贝构造函数

拷贝构造函数也是构造函数,是一种特殊的构造函数。

拷贝构造调用时机

  1. 主动调用拷贝构造
  2. 函数的实参到形参是拷贝,这时会调用拷贝构造
  3. 函数的返回值时,也是拷贝构造

没有写拷贝构造,系统会提供一个隐式的拷贝构造,该拷贝构造函数会把参数的数据全部拷贝一份到自己身上。

代码示例:

#include<string.h>
class MyStu
{
private:
	int id;
	int age;
	char*name;
public:
	MyStu()
	{
		id = 0;
		age = 0;
	}
	MyStu(MyStu const &other) //拷贝构造的写法
	{
		id = other.id;
		age = other.age;
		if (other.name)
		{
			name = new char[strlen(other.name) + 1];
			strcpy(name, other.name);
		}
	}
	void setStuId(int i)
	{
		id = i;
	}
	void setStuName(char *n)
	{
		name = new char[strlen(n)+1];
		strcpy(name, n);
	}
	~MyStu()
	{
		if (name != NULL)
		{
			delete []name;
			name = NULL;
		}
	}
};

void main()
{
	int a = 10; //变量的初始化赋值(在C++里面可以理解为整数a的拷贝构造)
	MyStu m;
	m.setStuId(101);
	m.setStuName("li si");
	MyStu m1(m); //拷贝构造的显式调用
	MyStu m2 = m; //拷贝构造的隐式调用
}

当我们注释自定义的拷贝构造函数时,运行程序,会报错:
在这里插入图片描述
原因如下图所示:
在这里插入图片描述

即默认的拷贝叫浅拷贝,只拷贝类对象的内存数据。所以,对象中有堆内存,必须重写构造函数,来实现深拷贝。深拷贝就是把对象中的堆内存、对象内存、逻辑内存都拷贝过来。

析构函数


析构函数和构造函数一样,也是一种特殊的函数。

主要的作用是在对象生命周期结束时,做一些清理工作,也可以将对象生命周期最后要做的事情写在析构函数中。

析构函数的调用时机

  1. 栈区对象出作用域死亡时调用。
  2. 主动通过delete函数去释放掉堆区的无名对象时调用。

当对象中会存在堆区数据,必须写析构函数,且在析构函数中去主动释放堆区数据。
代码示例

class MyStu
{
	int id;
	int age;
	char *name; //堆区数据
public:
	~MyStu() //析构函数
	{
		if (name != NULL)
		{
			delete[]name;
			name = NULL;
		}
	}
};

this指针


  1. this指针是系统自动生成,且隐藏,我们看不到定义,但是可以使用。
  2. this指针并不是对象本身的一部分,它的作用域在类的内部。当类的普通函数在访问类的普通成员的时候,该this指针总是指向调用者对象。

观察如下代码,id=id出现了同名,运行时会导致代码出错。

在这里插入图片描述
将id = id改为 this->id = id即可

this->id = id;

this指针指向调用者对象的首地址。
在这里插入图片描述
this指针的使用

  1. 在类中使用,不能在类外使用。
  2. this->类中成员数据;this->类中成员函数;通过this指针找到调用者对象的某个成员。
  3. return this:表示在类中返回该调用者对象的首地址。
  4. return *this:表示在类中返回该调用者对象。

类的分文件编写(类的标准写法)


可通过VS软件快速创建类的分文件:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
这时会看到有两个文件生成:class_one.h、class_one.cpp,class_one.h主要用来声明和定义函数,不写有内存的数据,class_one.cpp中写带内存的数据。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

街 三 仔

你的鼓励是我创作的最大动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值