前言
下面笔者带领大家学习类和对象(中)前两个成员函数:构造函数和析构函数。
1.构造函数
第一个函数是构造函数,构造函数是类的一个成员函数,专门用来初始化,但是不会用来创建对象(类似于Init函数不过可以自动调用)
特点
首先看四个基本的构造函数特点
- 函数名与类名相同
- 无返回值(void也不用写)
- 实例化时自动调用
- 构造函数可以重载
下面展示一些更重要的构造函数特点 - 构造函数分为无参,带参,全缺省三个形式
class Date
{
public:
// 1.无参构造函数
Date()
{
_year = 1;
_month = 1;
_day = 1;
}
// 2.带参构造函数
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
// 3.全缺省构造函数
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << _year << "/" << _month << "/" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
- 类中没有显示定义构造函数时,会自动默认生成无参的构造函数
- 无参构造函数实例化不能加括号,因为与函数声明分不清
- 全缺省和无参不能同时存在,因为会有歧义
- 无参,全缺省构造,不写构造时编译器默认生成的构造函数都叫默认构造函数,也就是不传实参就可以调用的就是默认构造函数
- 编译器默认生成的构造函数对内置类型成员变量初始化无要求,但是对于自定义类型必须调用其构造函数,而且大多数情况下需要自己写构造函数,不过有特殊情况,比如下面:
typedef int STDataType;
class Stack
{
public:
Stack(int n = 4)
{
_a = (STDataType*)malloc(sizeof(STDataType) * n);
if (nullptr == _a)
{
perror("malloc申请空间失败");
return;
}
_capacity = n;
_top = 0;
}
}
private:
STDataType* _a;
size_t _capacity;
size_t _top;
};
class MyQueue
{
public:
// 编译器默认生成MyQueue的构造函数调用了Stack的构造,完成了两个成员的初始化
private:
Stack pushst;
Stack popst;
//int size;
};
int main()
{
MyQueue mq;
//Stack st1;
//Stack st2;
return 0;
}
如果调试不难发现MyQueue的确自动调用Stack的构造,但是如果加上int,那么int的值就是随机的
2.析构函数
然后就是析构函数了,其实析构函数和构造函数就是功能相反的两个很相似的函数,完成的是对象资源的清理释放而不是销毁对象
特点:
- 析构函数名是类名+~
- 无参数无返回值(没有函数重载)
- 对象生命周期结束自动调用
- 编译器自动生成的析构函数对内置类型不处理,对自定义类型调用其析构
- 类中没有资源折申请可以不写析构(Date),但是类中有资源申请一定要写(Stack)
- 有多个对象时,遵循先定义的先析构的原则(因为对象在栈上,和数据结构的栈有着相同特点)
结语
本文到此就结束了,作者的源码放在GitHub和Gitee了,读者可以从简介自取。