一.构造函数
构造函数是特殊的成员函数,其主要任务为初始化对象(不开空间)。
特性:
1.函数名与类名相同
2.无返回值
3.对象实例化时(创造类变量时),编译器自动调用构造函数
4.构造函数可以重载(多种初始化方式,但可以总合为全缺省)
5.如果类中没有显示定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,若用户显示定义了构造函数,则编译器不在默认生成。(默认构造函数对内置类型不会处理,其赋值的仍然是随机数,其中的随机数设置取决于编译器,有些编译器可能会初始化为0,但是C++标准并没有规定)
注:无参的构造函数和全缺省的构造函数都是默认构造函数,并且默认构造函数只能有一个。
6.无参构造,全缺省构造和用户没写编译器自动生成的构造函数都可以叫默认构造函数(即不传参数就可以调用的构造函数就是默认构造函数)
内置类型自动默认生成构造函数,自定义类型调用默认构造函数
class Date
{
public:
Date(int year=2024,int month=8,int day=8)//构造函数
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << _year << " " << _month << " " << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
C++11针对内置类型成员不能初始化打了补丁,即内置成员变量在类声明中可以给默认值
class Date
{
public:
void Print()
{
cout << _year << " " << _month << " " << _day << endl;
}
private:
//给默认值
int _year=1;
int _month=1;
int _day=1;
};
二.析构函数
析构函数的功能与构造函数相反,析构函数不是完成对对象的销毁,局部对象销毁是编译器的工作,而在对对象销毁时会自动调用析构函数,完成对象中资源清理的工作。
特性:
1.析构函数名为类名前加上字符‘~’
2.无参数,无返回值类型
3.一个类只能有一个析构函数,若为显示定义,则编译器自动生成默认的析构函数。
注:析构函数不能重载
4.对象生命周期结束时,C++编译器自动调用析构函数
注:无需资源清理的不需要析构函数
class Stack
{
public:
//析构函数
~Stack()
{
if (_a)
{
_top = 0;
_capacity = 0;
free(_a);
_a = nullptr;
}
}
private:
int* _a;
int _top;
int _capacity;
};
三.拷贝构造函数
特性:
1.拷贝构造函数是构造函数的一个重载形式
2.拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器会报错,会引发无穷递归调用
3.若未显示定义,编译器会生成默认的拷贝函数。默认的拷贝函数对象按内存存储,按字节完成拷贝,这种拷贝叫做浅拷贝或者值拷贝
注:在编译器默认生成的拷贝函数中,内置类型是按照字节方式直接拷贝的,而自定义类型是调用其拷贝函数完成的
总结:
1.如果没有资源需要管理,一般不用写拷贝构造
2.一般情况下不需要写析构函数的就不需要写拷贝构造
3.如果内部含有指针,或者有值指向资源则需要显示的写析构函数进行释放,也需要显示的写拷贝函数完成深拷贝。
//日期类浅拷贝
Date(const Date& d1)
{
_year = d1._year;
_month = d1._month;
_day = d1._year;
}
//栈的深拷贝
Stack(const Stack& s1)
{
_a = (int*)malloc(sizeof(int) * s1._capacity);
if (_a == nullptr)
{
perror("copy:malloc()");
return;
}
memcpy(_a, s1._a, sizeof(int) * s1._top);
_top = s1._top;
_capacity = s1._capacity;
}