构造函数:
是一个特殊的成员函数,名字与类名相同,创建类类型对象时,由编译器自动调用,在对象的生命周期内只且只调用一次,以保证每个数据成员都有一个合适的初始值。
class CDate
{
public:
CDate()
{}
CDate( const int year, const int month, const int day)
{
_iYear = year;
_iMonth = month;
_iDay = day;
}
private:
int _iYear;
int _iMonth;
int _iDay;
};
【构造函数特性】
1、函数名与类名相同。
2、没有返回值。
3、有初始化列表(可以不用)。
4、新对象被创建,由编译器自动调用,且在对象的生命期
内仅调用一次。
5、构造函数可以重载,实参决定了调用那个构造函数。
6、如果没有显式定义时,编译器会提供一个默认的构造函
数。
7、无参构造函数和带有缺省值得构造函数都认为是缺省构
造函数,并且缺省构造函数只能有一个。
【默认构造函数】
类如果没有显式定义构造函数时,编译器会合成一个默认的构造函数,该构造函数中什么工作都不做。只要显式定义了,即使该构造函数什么也不做,编译器也不会为该类合
成默认的构造函数。编译器生成的默认构造函数使用与变量初始化相同的规则来初始化成员,具有类类型的成员通过运行各自的默认构造函数来进行初始化。内置和复合类型的成员如指针、数组,只对定义在全局作用域中的对象初始化,当对象定义在局部作用域时,内置和符合类型的成员不进行初始化。在某些情况下,默认构造函数是由编译器隐式使用的。
拷贝构造函数
只有单个形参,而且该形参是对本类类型对象的引用(常用const修饰),这样的构造函数称为拷贝构造函数。拷贝构造函数是特殊的构造函数,创建对象时使用已存在的同类对象来进行初始化,由编译器自动调用。
class CDate
{
public:
CDate()
{}
CDate( const int year, const int month, const int day)
{
_iYear = year;
_iMonth = month;
_iDay = day;
}
CDate( const CDate& date)
{
_iYear = date._iYear;
_iMonth = date._iMonth;
_iDay = date._iDay;
}
private:
int _iYear;
int _iMonth;
int _iDay;
};
【使用场景】
1、对象实例化对象
CDate d1(1990, 1, 1);
CDate d2(d1);
2、传值方式作为函数的参数
void FunTest(const CDate date)
{}
3、传值方式作为函数返回值
CDate FunTest()
{
CDate date;
return date;
}
析构函数
与构造函数功能相反,在对象被销毁时,由编译器自动调用,完成类的一些资源清理和汕尾工作
class CArray
{
public:
CArray(size_t capacity)
: _capacity(capacity)
{
_pData = ( int*)malloc(capacity*sizeof (int));
_size = 0;
}
~CArray()
{
if (NULL != _pData)
{
free(_pData);
_pData = NULL;
}
_size = 0;
_capacity = 0;
}
private:
int* _pData;
size_t _size;
size_t _capacity;
};
【特性】
a、析构函数在类名(即构造函数名)加上字符~。
b、析构函数无参数无返回值。
c、一个类有且只有一个析构函数。若未显示定义,系统会
自动生成缺省的析构函数。
d、对象生命周期结束时,C++编译系统系统自动调用析构函
数。
e、注意析构函数体内并不是删除对象,而是做一些清理工
作。
赋值运算符重载
【操作符重载】
重载操作符是具有特殊函数名的函数,关键字operator后面接需要定义的操作符符号。
操作符重载也是一个函数,具有返回值和形参表。它的形参数目与操作符的操作数目相同,函数调用操作符可以接受任意数目的操作数。
使用运算符重载可以提高代码的可读性。
如果对象在申明的同时马上进行的初始化操作,则称之为拷贝运算。
例如:
class1 A("af"); class1 B=A;
此时其实际调用的是B(A)这样的浅拷贝操作。
如果对象在申明之后,在进行的赋值运算,我们称之为赋值运算。
例如:
class1 A("af"); class1 B;
B=A;
Complex &operator=( const Complex &rhs )
{
// 首先检测等号右边的是否就是左边的对象本,若是本对象本身,则直接返回
if ( this == &rhs )
{
return *this;
}
// 复制等号右边的成员到左边的对象中
this->m_real = rhs.m_real;
this->m_imag = rhs.m_imag;
// 把等号左边的对象再次传出
// 目的是为了支持连等 eg: a=b=c 系统首先运行 b=c
// 然后运行 a= ( b=c的返回值,这里应该是复制c值后的b对象)
return *this;
}