版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/z_x_m_m_q/article/details/82490658
类的构造函数:
构造函数是一种随着对象创建而自动被引用的共有成员函数,有且仅在对象创建时自动执行一次,它的功能是初始化创建的对象
构造函数是特殊的成员函数,其特征如下:
- 函数名与类名相同
- 无返回值
- 对象创建时系统自动调用对应的构造函数
- 构造函数可以重载
- 构造函数的定义可以在类内,也可以在类外
- 如果类定义中没有给出构造函数,则C++编译器会自动产生一个缺省的构造函数,只要我们定义了一个构造函数,系统就不会自动生成缺省的构造函数
- 无参的构造函数和全缺省值的构造函数都认为是缺省构造函数,并且缺省构造函数只能有一个
以下是几种构造函数的定义及调用
class Date
{
public:
//无参构造函数(缺省构造函数)
//Date()
//{}
//带参构造函数
//Date(int year,int month,int day)
//{
// _year = year;
// _month = month;
// _day = day;
//}
//全缺省值的构造函数(缺省构造函数)
//Date(int year = 2018,int month = 1,int day = 1)
//{
// _year = year;
// _month = month;
// _day = day;
//}
//半缺省值的构造函数
Date(int year,int month,int day = 1)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
void test()
{
//调用无参构造函数(缺省构造函数)
//Date d1;
//调用带参构造函数
//Date d2(2018,9,7);
//调用全缺省值的构造函数(缺省构造函数)
//Date d3;
//Date d4(2018,9,7);
//Date d5(2018,9);
//调用半缺省值构造函数
Date d6(2018,9,7);
Date d7(2018,9);
}
备 注:若默认参数声明和定义分离,则可以在声明或定义中给默认参数
类的析构函数:
当一个对象的生命周期结束时,C++编译器系统会自动调用析构函数,它的功能是做一些对象删除前的清理工作
析构函数是特殊的成员函数,其特征如下:
- 析构函数名是在类名前加上字符~
- 无参数、也无返回值
- 一个类有且只能有一个析构函数,若未显示定义,系统会自动生成默认的构造函数
- 对象生命周期结束时,C++编译系统系统自动调用析构函数
class Vector
{
public:
Vector(int size)
{
_pStr = (char*)malloc(size*sizeof(char));
}
~Vector()
{
if (_pStr)
{
free(_pStr); //此种情况下析构函数完成的是释放空间
_pStr = NULL;
}
}
private:
char* _pStr;
};
类的拷贝构造函数:
创建对象时使用同类对象进行初始化,这时所用的函数称为拷贝构造函数
拷贝构造函数是特殊的成员函数,其特征如下:
- 拷贝构造函数其实是构造函数的重载
- 拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归
- 若未显示定义,系统会默认生成默认的拷贝构造函数。 默认的拷贝构造函数会 按照成员的声明顺序依次拷贝 类成员进行初始化
class Date
{
public:
Date()
{}
//拷贝构造函数
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
private:
int _year;
int _month;
int _day;
};
void test()
{
Date d1;
//拷贝构造函数的两种调用方式
Date d2(d1);
Date d3 = d1;
}
解析:为什么拷贝构造函数的参数使用传值方式会引发无穷递归调用?
因为函数的普通参数只是实参的一份临时拷贝,在函数调用时形参需根据实参创建出自己,这个创建的过程实际上就是一个拷贝的过程。拷贝构造函数参数如果是传值方式其实就变成了一个不断调用自己的过程。
运算符重载:
为了增强程序的可读性,C++支持运算符重载
运算符重载的特征:
- operator + 合法的运算符 构成函数名(重载 < 运算符的函数名:operator < )
- 重载运算符以后,不能改变运算符的优先级、结合性、操作个数
class Date
{
public:
Date()
{}
//拷贝构造函数
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
// == 运算符重载
bool operator == (const Date& d)
{
return _year == d._year && _month == d._month && _day == d._day;
}
private:
int _year;
int _month;
int _day;
};
void test()
{
Date d1;
//拷贝构造函数的调用方式
Date d3 = d1;
//调用 == 运算符重载
d1 == d3;
}
5个C++不能重载的运算符是:.* / :: / sizeof / ?: / .
类的赋值操作符重载:
赋值运算符的重载是给一个已经存在的对象进行赋值
当程序没有显式提供一个以本类或本类的引用为参数的赋值运算符重载函数时,编译器会自动生成这样一个赋值运算符重载函数
class Date
{
public:
Date()
{}
//拷贝构造函数
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
//赋值运算符重载
Date& operator =(const Date& d)
{
if (this != &d)
{
this->_year = d._year;
this->_month = d._month;
this->_day = d._day;
}
return *this;
}
private:
int _year;
int _month;
int _day;
};
void test()
{
Date d1;
Date d2;
//拷贝构造函数的调用方式
Date d3 = d1;
//调用赋值运算符重载函数
d3 = d2;
d3 = d2 = d1; //赋值运算符重载函数设计返回值是可以进行连续的赋值
}
类的取地址操作符重载 及 const修饰的取地址操作符重载:
这两个默认成员函数一般不用重新定义 ,用编译器默认生成的就行了
class Date
{
public:
Date* operator &()
{
return this;
}
const Date* operator &() const
{
return this;
}
private:
int _year;
int _month;
int _day;
};
只有一种情况下,才会需要你自己重载这两个操作符,那就是你只想让别人获取到你指定的内容