拷贝构造函数
定义:
只有单个形参,是该形参是对本类类型的引用;即是用一个已经存在的对象去初始化一个新的对象。
Date d1(2000,1,1);
Date d2(d1); //拷贝构造函数
特征:
- 拷贝构造函数是构造函数的一个重载形式;
- 参数只有一个,必须使用应用传参,若用传值传参会引发无穷递归调用。
Date(Date d) //传值传参
//传值前需要传参Date d,这时一个拷贝构造,会形成一个无穷递归
Date(Date& d) //传引用传参
{
_year = d._year;
_month = d._month;
_day = d._day;
}
注:在建立拷贝构造函数时,可以加上const进行修饰,这样可以防止构造函数过程中传值传反了。(如果传值传反了,编译器会自动报错,因为const修饰的Date d是只能读的,就是对权限进行了了缩小)
小结
- 自定义对象在函数传参时,一般推荐引用传参;传值传参也可以,但它每次都会调用拷贝构造;
- 拷贝构造是默认成员函数,我们不写,编译器会自动生成,但这个拷贝构造函数会对内置类型进行浅拷贝(值拷贝);对自定义类型成员,会调用它自己的拷贝构造完成拷贝;
- 像日期类Date这样的类,只需要进行浅拷贝,我们可以不写,默认生成的拷贝构造函数就能用;但像Stack这样的类(栈、链表),需要进行深拷贝,拷贝构造函数就需要自己写。
运算符重载
引入:为了增强代码的可读性。
定义:函数名是特殊的,关键字operator+运算符符号;具有返回值类型、函数名以及参数列表。
注:
- 不能通过其他连接符号来创建新的操作符,例如operator@;
- 重载操作符必须有一个类类型或枚举类型的操作数;
- 用于内置类型的操作符,其含义不能改变;
- 作用类成员的重载函数时,其 形参看起来比操作数目少1成员函数的操作符,是因为有一个默认的形参this,用它限定为第一个形参;
- “.* “、” ::”、"?:"、"."、sizeof 这五个不能进行重载;
- 区分函数重载和运算符重载: 函数重载是支持定义同名函数;运算符重载是为了让自定义类型向内置类型一样去使用运算符。
赋值运算符的重载
定义:
两个已经初始化过的对象,将其中一个对象赋值给另一个对象。
Date& operator=(const Date& d)
{
if(this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
retyrn *this;
}
连续赋值:遵循右结合原理,即赋值从右边开始。
d1=d2=d3;
//d3先赋给d2,d2再赋给d1;表达式的最终返回值为d2
小结:
- 赋值运算符的重载也是一个默认成员函数,可自动生成,自动生成的针对内置类型完成浅拷贝,对自定义类型会调用他自己的拷贝;
- 拷贝构造和赋值运算符重载特性相似,内置类型完成浅拷贝,自定义类型会调用他们的拷贝构造和运算符重载。
- 区分拷贝构造和赋值运算符重载:
拷贝构造是用一个已经初始化过的对象去初始化一个新对象;赋值运算符的重载是用两个已经初始化过的对象,将一个对象赋值给另一个对象。
Date d2(d1); //拷贝构造
d2 = d1; //赋值运算符重载
Date d2 = d1; //拷贝构造(因为d2没有被初始化)
**