构造函数:
构造函数是特殊的成员函数,,虽然函数名称叫构造,但是函数的主要任务并不是开空间创建对象,而是初始化对象。
特征如下:
1.函数名与类名相同
2.无返回值(不需要写void)
3.对象实例化时编译器自动调用对应的构造函数
4.构造函数可以重载(本质就是写多个构造函数,提供多种初始化方式)


析构函数:
析构函数与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成,而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。
特征如下:
1.析构函数名时在类名前加上字符 ~
2.无参数无返回值类型
3.一个类只能有一个析构函数。若未显示定义,系统会自动生成默认的析构函数。注意析构函数不能重载
4.对象生命周期结束时,C++编译系统系统自动调用析构函数
后定义的先析构
自定义类型参数传参时会遇到问题,比如栈这样的,C语言中自定义类型参数没什么问题,但C++中存在析构函数,


传参是将s1中的值赋值给s,也就是它们的_a都指向同一块空间,当func2结束时s会自动调析构函数,_a这块空间会释放,但s1中的_a依旧指向这块被释放的空间,然后程序结束s1再调用析构,导致二次析构野指针问题,程序出错
拷贝构造:
拷贝构造函数:只有单个形参,该形参是对本类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用
特征:(拷贝构造函数也是特殊的成员函数)
1.拷贝构造函数时构造函数的一个重载形式
2.拷贝构造函数的参数只有一个且必须是类 类型对象的
引用(
同类型的对象),使用传值方式编译器直接报错,因为会引发
无穷递归调用

自定义类型传参时要调用拷贝构造(
上图调用拷贝构造函数需要传参,但是给拷贝构造函数传参又会调用拷贝构造。。。)因为如果不调用拷贝构造,,直接传值拷贝可能会遇到栈那样二次析构
深拷贝,不想通过引用改变原数据:
Stack(const Stack& s) 防止误改原数据可以加const
{
_array = (DataType*)malloc(s._capacity);
if (NULL == _array)
{
perror("malloc申请空间失败!!!");
return;
}
mamcpy(_array,s._array,sizeof(DataType)*s._size);
_size = s._size;
_capacity = s._capacity;
}
编译器默认生成的拷贝构造:

C++
为了增强代码的可读性引入了运算符重载
,
运算符重载是具有特殊函数名的函数
,也具有其
返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字
operator
后面接需要重载的运算符符号
。
函数原型:
返回值类型
operator
操作符
(
参数列表
)。
比如下面是比较日期类大小的运算符重载:
bool operator<(const Date& x1,const Date& x2)
{
if (x1._year < x2._year)
{
return true;
}
else if(x1._year == x2._year && x1._month < x2._month)
{
return true;
}
else if (x1._year == x2._year && x1._month == x2._month && x1._day < x2._day)
{
return true;
}
else
{
return false;
}
}
写成 成员函数的 < : 写为成员函数必须比原函数少一个参数,有一个是隐含的this
//d1 < d2
//d1.operator < ( d2)
bool operator<(const Date& d)
{
if (_year < d._year)
{
return true;
}
else if (_year == d._year && _month < d._month)
{
return true;
}
else if (_year == d._year && _month == d._month && _day < d._day)
{
return true;
}
else
{
return false;
}
}