前面我们讲了最基本的两个类中的默认成员函数--构造函数和析构函数。接下来我们来看两个最重要的默认成员函数--拷贝构造函数和运算符重载函数。
一.拷贝构造
顾名思义,就是涉及拷贝的函数,那么具体是什么呢?拷贝构造是将一个已经存在的对象去初始化另一个对象。这个一般来说,需要自己写,如果不写的话,内置类型会自己完成值拷贝,如果是自定义类型,那么就会调用此类型的拷贝构造。
听起来不是很难对不对,我们来看看它的写法:
A aa;
A a1 = aa;
A a2(aa);
aa.Print();
a1.Print();
a2.Print();
第二行和第三行的写法是等价的,我们写代码时两种选其一就可以。
这个涉及的仅仅是简单的值拷贝,我们不写在类中也没关系,但是一般情况下,我们要根据需求来自己写拷贝构造函数,我们要注意:
A(A a)
{
_a = a._a;
_b = a._b;
}
A a1(1, 2);
A a2 = a1;
我们可以发现一系列错误,这些错误其实是因为构造函数参数没有用引用导致的,这样会无限调用构造函数,跟无限递归类似,永无止境,所以编译器强行检查了。正确的应该是这样写:
A(A& a)
{
_a = a._a;
_b = a._b;
}
这便是拷贝构造。
二.运算符重载
运算符重载也是非常重要的一个默认成员函数,它可以增强代码的可读性,它的形式是这样写的:
operator+运算符。
其中有几点需要注意:
1.不能通过其他符号来创建新的运算符。
2.重载操作符必须有一个类类型数据。
3.用于内置类型的运算符,其含义不能改变。
4.作为类函数重载时,其形式看起来比操作数数目少1.
5.不能改变操作符的操作个数,一般操作符是几个操作数,那么重载时就有几个参数。
我们来举几个例子:
// >运算符重载
bool operator>(const Date& d);
// ==运算符重载
bool operator==(const Date& d);
// >=运算符重载
bool operator >= (const Date& d);
// <运算符重载
bool operator < (const Date& d);
// <=运算符重载
bool operator <= (const Date& d);
// !=运算符重载
bool operator != (const Date& d);
我们以日期类为例,看到有这几个operator。一般来说,这些操作符是不能比较自定义类型的,但是这些操作符被运算符重载了之后,那么就可以用这些操作符来操作对象与对象直接的关系了。我们拿日期类为例。
void test4()
{
Date d1(2023, 12, 9);
Date d2(2023, 12, 10);
int ret = (d2 >= d1);
cout << ret << endl;
}
可以看到,这是可以比较成功的。当然运算符重载的作用远不止这些,运算符可以复用,也就是在成员函数中,可以大量反复使用这些操作符,大大提高了效率。
当然具体的还得实践见真知,理论都不难,实践才是最重要的。