详解C++类与对象(二)

文章目录

  • 前言
  • 1.构造函数
    • 1.1构造函数的使用
    • 1.2构造函数的初始化列表
  • 2.析构函数

前言

在C++中,类中存在 默认成员函数 ,那什么是 默认成员函数

默认成员函数就是用户没有显示实现,编辑器会自动生成的成员函数。

一个类,在不写的情况下,会默认生成下面6个 默认成员函数 。其次,C++11以后还会增加两个 默认成员函数移动构造移动赋值 。这两个本篇文章不讲解。

默认成员函数 是公认的C++较难学习的部分。因此,我们在学习 默认成员函数 时,应从两个方面来学习:

  1. 我们不写时,默认生成的函数是否够用?
  2. 若是不够用,我们应该如何实现一个够用的成员函数?
    默认成员函数的分类

1.构造函数

构造函数是特殊的成员函数。虽然名称里面带了构造,但是构造函数的主要任务不是开空间创建对象,而是对象实例化时初始化对象。构造函数的本质就是要替代我们以前StackDate类中的Init函数的功能。

构造函数的优点:

  1. 函数名与类名相同。

  2. 无返回值。 (返回值啥都不需要给,也不需要写void,不要纠结,C++规定如此)

在这里插入图片描述

  1. 对象实例化时系统会自动调用对应的构造函数。
    在这里插入图片描述

  2. 构造函数可以重载。
    在这里插入图片描述

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

  4. 无参构造函数、全缺省构造函数、我们不写构造时编译器默认生成的构造函数,都叫做默认构造函
    数。无参构造函数和全缺省构造函数虽然构成函数重载,但是调用时会存在歧义。要注意很多同学会
    认为默认构造函数是编译器默认生成那个叫默认构造,实际上无参构造函数、全缺省构造函数也是默
    认构造,总结⼀下就是不传实参就可以调用的构造就叫默认构造。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    注意:这三个函数不能同时存在,只能存在一个。

  5. 我们不写,编译器默认生成的构造,对内置类型成员变量的初始化没有要求,也就是说是是否初始
    化是不确定的,看编译器。对于自定义类型成员变量,要求调用这个成员变量的默认构造函数初始
    化。如果这个成员变量,没有默认构造函数,那么就会报错,我们要初始化这个成员变量,需要用
    初始化列表才能解决。

1.1构造函数的使用

#include<iostream>
using namespace std;

typedef int STDateType;
class Stack {
public:
	Stack(int n = 4)
	{
		_a = (STDateType*)malloc(sizeof(STDateType) * n);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败");
			return;
		}

		_capacity = n;
		_top = 0;
	}
private:
	STDateType* _a;
	size_t _capacity;
	size_t _top;
};

//两个Stack实现队列
class MyQueue {
public:

private:
	Stack pushst;
	Stack popst;
};

int main()
{
	MyQueue mq;
	return 0;
}

1.2构造函数的初始化列表

typedef int stdatetype;
class stack {
public:
	stack(int n = 4)//初始化列表
		:_capacity(n)
	    ,_top(0)
	{
		_a = (stdatetype*)malloc(sizeof(stdatetype) * n);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败");
			return;
		}
	}
private:
	stdatetype* _a;
	size_t _capacity;
	size_t _top;
};

2.析构函数

析构函数与构造函数功能相反,析构函数不是完成对对象本身的销毁。比如局部对象存在局部栈帧,函数结束栈帧销毁,函数占用的资源得到释放。C++规定:对象结束时调用析构函数,完成对象中的资源清理释放工作。

析构函数的特点:

  1. 析构函数名是在类名前加上字符 ~。

  2. 无参数无返回值。 (这里跟构造类似,也不需要加void)

  3. 一个类只能有⼀个析构函数。若未显式定义,系统会自动生成默认的析构函数。
    在这里插入图片描述

  4. 对象生命周期结束时,系统会自动调用析构函数。
    在这里插入图片描述

  5. 跟构造函数类似,我们不写编译器自动生成的析构函数对内置类型成员不做处理,自定类型成员会
    调用他的析构函数。

  6. 还需要注意的是我们显示写析构函数,对于自定义类型成员也会调用他的析构,也就是说自定义类
    型成员无论什么情况都会自动调用析构函数。

  7. 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,如Date;如
    果默认生成的析构就可以用,也就不需要显示写析构,如MyQueue;但是有资源申请时,⼀定要
    自己写析构,否则会造成资源泄漏,如Stack。

Stack:

class Stack {
public:
	Stack(int n = 4)
	{
		_a = (STDateType*)malloc(sizeof(STDateType) * n);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败");
			return;
		}

		_capacity = n;
		_top = 0;
	}

	~Stack()
	{
		cout << "~Stack()" << endl;//析构函数被调用时,打印“~Stack”

		free(_a);
		_a = nullptr;
		_capacity = 0, _top = 0;
	}

private:
	STDateType* _a;
	size_t _capacity;
	size_t _top;
};

MyQueue:

class MyQueue {
public:
	//编译器默认调用Stack的析构,即使显示析构,调用的依然是Stack的析构
	~MyQueue()
	{
	}

private:
	Stack pushst;
	Stack popst;
};

  1. 一个局部域的多个对象,C++规定后定义的先析构。

总结:一般情况下,显示申请了资源,才需要自己实现析构函数,其他情况下基本都不需要自己实现。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值