观前提醒:得提前了解构造函数和析构函数的写法,以及运算符重载和引用的部分知识。
拷贝构造的功能:
默认的的拷贝构造主要用于,直接用一个已知的类的数据初始化另一个类的数据,是构造函数的一个重载。
在下面的情况主要有几种下会调用拷贝构造:
Date是一个类名,b是事先声明的一个类
Date a(b); ****情况1 直接调用拷贝构造
Date a = b; ****情况2 定义的时候使用赋值符号,注意这个跟后面的赋值重载没关系,与情况一等价
get是一个函数,函数的行参中有Datie类型,比如get(Date a);
get(b); ****情况3 调用函数时,函数形参的初始化
说了这么多,那么默认生成的拷贝构造会干什么呢,它会对类做一个浅拷贝,什么是浅拷贝呢,就是直接把已知的类的浅层数据放到要初始化的对象里面去。
比如,如果你的类中数据都像这样
class CSDN{
public:
int a;
int b;
}
那么浅拷贝完全是够用的。
但是如果你的类像这样:
class CSDN{
public:
int a;
int *b; //b指向的是一块用于存数据的空间
}
那么浅拷贝会直接把已知类,里面的,指针的值赋值到要初始化的类里面,相当于俩个类指向的是同一块空间,这显然与我们的意图不同。
拷贝构造的书写:
拷贝构造函数就是构造函数的重载,下面是一个日期类。
class Date
{
public:
Date(Date& d){//注意这里用的是引用
year = d.year;
month = d.month;
day = d.day;
}
private:
int year;
int month;
int day;
}
注意:
为什么拷贝构造的参数是引用呢,那是因为我们先前提到的情况三里提到参数的初始化也会调用拷贝构造,
当我们用类型做参数时,就会发生:调用拷贝构造 -:> 构造的行参初始换又要调用拷贝构造-:> 。。。形成无限的嵌套。
所以我们用引用来做参数(引用的初始化不会调用拷贝构造,只是一个别名)
赋值运算符重载的特点:
我们都知道赋值运算符的用途,也知道它是可以重载的,但是这里讲的重载是对类作为参数的重载:
首先我们要知道类的默认函数里面就有赋值运算符的重载,也就是说,如果你在类的里面没有写赋值运算符重载,编译器会自动生成一个。
所以就是说:类的赋值运算符重载只能作为一个成员函数。(因为你在外头编译器会在类里面自动生成一个,会产生冲突。
另外,默认的运算符重载也是浅拷贝。
和全局重载的不同点:
另外作为成员函数的运算符重载的参数和全局的运算符重载有一些区别
a+b;
在全局重载函数中的参数传递为如下为:
operator=(a,b); //最多两个参数
但是如果a和b是两个类
a+b
参数传递如下
a.operator=(b); // 调用a的成员函数,所以只需要一个参数
你问a的参数咋调用,当然是用高级的this指针了(好吧直接变量名就可以调用a里面的)
相同点:
可以有返回值
所以我们可以快乐的实现出
a = b = c =0;
这样的操作
其他的地方都差不多。
重点回顾: