构造函数引出
类中什么都不写会被我们成为空类,但是空类的意思真的就是里面是空的吗,并不是的,假如我们没有显示定义,会自动生成6个默认成员函数。当我们对于默认生成的不满意,便可以自己定义其中不满意的函数。下面我们来看构造函数。
构造函数
构造函数是特殊的成员函数,名字与类名相同,创造自己类型的对象时由编译器自动调用,在对象的每个生命周期只调用一次,让其每个数据成员都有一个合适的初始值。虽然他的名字叫构造但他不负责开空间创建对象,而是初始化对象。
特点:
1.函数名与类名相同
2.无返回值
3.对象实例化编译器自动调用对应的构造函数
4.构造函数可以重载
当我们什么都不写,他会默认生成一个构造函数,初始化对象。
并没有什么用,不满意,所以我们需要自己去自己写一个。
构造函数的重载与缺省
这就是构造函数的基本形式。而且这三个函数构成了重载,有多种初始化方式。
构造函数可以重载,也可以给缺省值。
Date()
{
}
Date(int month,int day)
{
_month = month;
_day = day;
}
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
调用的时候根据参数自动识别,需要注意的是当定义d1对象时调用无参构造函数并不需要带(),因为带了括号,与函数声明的形式一模一样。必须区分开。
假如全缺省这两个默认构造函数是不能同时存在的,因为他们两个都可以用Date d1;
调用,调用会有歧义。
//Date(){
//}
Date(int year=2012, int month=3, int day=20)
{
_year = year;
_month = month;
_day = day;
}
重载的半缺省:
假如这种情况,也会出现有歧义的调用情况
写测试用例的时候差点举了这个例子,草率了,连重载都不是。
时刻记住重载的定义,参数列表的类型不同或个数不同或顺序不同
时刻记住调用重载函数的时候要注意有歧义的情况。
通常只用全缺省的构造函数(形参都给上默认值但是并不是所有的成员变量都要对应的写成形参,视场景而定)
补充:前面提到,我们不写,使用编译器自动生成的构造函数不满意,我们被迫写了一个。实际上他真的什么都不干吗,并不是的。
class Time
{
public:
Time()
{
_time = 0;
_minute = 0;
_second = 0;
}
private:
int _time;
int _minute;
int _second;
};
class Date
{
public:
void print()
{
cout << _year << " " << _month << " " << _day << endl;
}
private:
int _year;
int _month;
int _day;
Time time_t;
};
int main()
{
Date d;
return 0;
}
在前面代码基础上加了一个自定义时间类,删掉我们自己的构造函数,给日期类加入了一个自定义类型。
本类(Date类)自动生成的构造函数它不管自己的内置类型,他管我们编的自定义类型。所以并不是什么都不做
注:无参或者全缺省的构造函数函数(同时存在一个)都称为默认构造函数
在调用的时候我们d对象的构造函数(这里我们想看以为什么都不干的那个编译期自动生成的构造函数所以删掉自己写的)调用了成员变量 time_t的默认成员函数,去找支持无参调用的默认构造函数
像上图假如自己在Time类写了一个不是全缺省的,那么Time类也不会生成无参的,d对象的构造函数调用Time类默认成员函数(我只能用无参(默认构造函数),你给我搞了个需要传参数的,编译器报错)
析构函数引出
我们知道局部变量的生命周期就是他自己的代码块,生命周期结束后由编译器完成对他的销毁工作,那么析构函数是干什么的呢,销毁对象吗,不是的,销毁是系统做的,析构函数是做清理工作,比如free(),fclose(),等
析构函数
析构函数是特殊的成员函数
特点:
- 析构函数名在类名前加上字符~
- 无参数无返回值(不能重载)
- 一个类有且只有一个析构函数,若未显示定义,系统会自动生成默认的析构函数】
- 对象生命周期结束时,C++编译系统自动调用析构函数。
像之前写的日期类,都是开辟在栈上面的,不需要我们自己定义析构函数,下面我们写一个栈
class Stack
{
public:
Stack(int capacity=4)
{
_a=(int*)malloc(sizeof(int)*capacity);
_size=0;
_capacity=capacity;
}
private:
int* _a;
int _size;
int _capacity;
}
int main()
{
Stack s1;
return 0;
}
这里就需要自己写析构函数,对a所指向的堆上的空间进行清理
~Stack()
{
free(_a);
_a=nullptr;
_size=_capacity=0;
}
总结
- 构造函数不是创建对象,而是初始化对象。
- 析构函数不是销毁对象,而是完成资源清理工作。
- 无参或全缺省的构造函数都被称为默认构造函数
- 自己生成的构造函数并不是什么都不做,假如有自定义类型的话,会调用自定义类型里的默认构造函数
- 假如有自定义类型,析构函数与构造函数类似。