C++中,什么成员都没有的类称为空类。然而,编译器会自动生成6个默认成员函数。
默认成员函数:用户没有显示实现,编译器会生成的成员函数。
构造函数 | 初始化 |
析构函数 | 清理 |
拷贝构造 | 使用同类对象初始化创建对象 |
赋值重载 | 把一个对象赋值给另一个对象 |
取地址重载 | 普通对象取地址 |
const对象取地址 |
一、构造函数
特点
·构造函数并不是开空间创建对象,而是初始化对象
·构造函数名字与类名相同
·无返回值
·对象实例化时编译器自动调用对应的构造函数
·构造函数可以重载
用户自己写构造函数(代码如下)
//日期类
class Date
{
public:
//无参构造函数
Date()
{}
//带参构造函数
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;//调用无参构造函数
Date d2(2023, 4, 9);//调用带参构造函数
return 0;
}
不可写成Date d3();
这样就变成了函数声明
如果用户自己不写构造函数(类中没有显示定义构造函数),则C++会自动生成一个无参的默认构造函数。
//日期类
class Date
{
public:
无参构造函数
//Date()
//{}
带参构造函数
//Date(int year, int month, int day)
//{
// _year = year;
// _month = month;
// _day = day;
//}
void Print()
{
cout << _year << '-' << _month << '-' << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;//调用无参构造函数
//Date d2(2023, 4, 9);//调用带参构造函数
d1.Print();
//d2.Print();
return 0;
}
d1调用了编译器生成的默认构造函数,但_year _month _day依旧是随机值
因为C++把类型分为了内置类型(int/char...)和自定义类型(class/struct/union...)
编译器生成的默认构造函数会对自定义类型成员调用它的默认成员函数
二、析构函数
析构函数不是对对象本身进行销毁,而是在对象销毁时会自动调用析构函数,完成对象中资源的清理工作。(局部对象销毁是由编译器完成的)
特点
·析构函数名是在类名前加~
·无参数无返回值
·一个函数只能有一个析构函数
·对象生命周期结束,C++编译系统自动调用析构函数
以栈为例,用户自己写的析构函数如下
class Stack
{
public:
//构造函数
Stack(int capacity = 3)
{
_array = (int*)malloc(sizeof(int) * capacity);
if (_array == NULL)
{
perror("maollpc fail");
return;
}
_capacity = capacity;
_size = 0;
}
void Push(int data)
{}
//其他操作。。。
//析构函数
~Stack()
{
if (_array)
{
free(_array);
_array = NULL;
_capacity = 0;
_size = 0;
}
}
private:
int* _array;
int _capacity;
int _size;
};
int main()
{
Stack s;
s.Push(1);
}
三、拷贝构造函数
创建一个和已存在对象一模一样的新对象。
特点
·拷贝构造是构造函数的一个重载形式
·拷贝构造的参数唯一,必须是类类型对象的引用
用户自己写的拷贝构造函数如下
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
Date d2(d1);
return 0;
}
如果用户未写(为显示定义),编译器会生成默认的拷贝构造函数,这种拷贝按内存存储按字节序完成拷贝(称为浅拷贝或值拷贝)
但在一些情况下,需要进行深拷贝
四、赋值运算符重载
命名:关键字operate后面接需要重载的运算符符号
函数原型:返回值类型 operate 操作符(参数列表)
bool operator==(const Date& d1, const Date& d2)
{
return d1._year == d2._year
&& d1._month == d2._month
&& d1._day == d2._day;
}
注:赋值运算符只能重载成类的成员函数,不能重载成全局函数(因为类内会默认生成,与类外冲突)
用户没有显示实现时,编译器会自动生成一个默认赋值运算符重载,以值的方式逐字节拷贝,但有些情况需要深拷贝
运算符++重载
以日期类对象为例
前置++:返回+1之后的结果
Date& operator++()
{
_day += 1;
return *this;
}
后置++:先使用,后+1
Date& operator++(int)
{
Date tmp(*this);
_day += 1;
return tmp;
}