构造函数和复制构造函数
构造函数
对于需要传值的构造函数,如
class box{
protected:
int X;
int Y;
int Z;
public:
box(int,int,int);
};
box::box(int x,int y,int z){
X=x;
Y=y;
Z=z;
}
可以使用初始化列表
box::box(int x,int y,int z):X(x),Y(y),Z(z){
}
在函数后加冒号,然后是成员变量名(形参名)
的格式
复制构造函数
复制构造函数是用已经实例化的对象来初始化新的对象的函数
如:box b2(b1);
,格式:classname (const classname &obj){}
参数一般都是引用类型&
,不能是不同传值,用指针也能但会出错
const也可以不加,还可以有两个复制构造函数,一个是const的,一个非const
即使没有定义复制构造函数,也可以使用对象初始化新对象,因为编译器会自动生成默认的复制构造函数,如果自己定义了,则会覆盖默认的
实例:
class box{
public:
int a;
int b;
box(const box & c):a(c.a),b(c.b){};
};
复制构造函数被调用的三种情况:
- 当用一个对象去初始化另一个同类对象,会调用复制构造函数
box b2(b1);
box b2=b1;
注:第二条语句是初始化语句,不是赋值.赋值语句的左边是已经初始化的变量.
box b1,b2;
b2=b1;
像上面这样就不会调用赋值构造函数,因为b2已经初始化过了
- 作为函数的参数时,会调用复制构造函数
class box{
...
};
void func(box b){
...
}
int main(){
box b1;
func(b1);
}
- 作为函数的返回值时也会调用复制构造函数
class box{
...
};
box func(){
box b;
...
return b;
}
关于为什么当类成员中含有指针类型成员且需要对其分配内存时,一定要有自定义的复制构造函数?
默认的复制构造函数实现的只是浅拷贝,即直接将原对象的数据成员值依次复制给新的对象中对应的数据成员,并没有给新对象分配另外的内存空间.这样就导致,如果对象的数据成员 是指针的话,两个指针实际指向同一块内存空间
所以,这样就需要我们自己定义复制构造函数,为指针分配新的内存
例如:
#include<iostream>
using namespace std;
typedef struct{
int a;
}T,*TP;
class box{
public:
TP tp=(TP)malloc(sizeof(T));
box(){};
};
int main(){
box b1;
b1.tp->a=21;
box b2=b1;
b2.tp->a=22;
cout<<b1.tp->a;
}
类box中有一个TP指针,我们先初始化b1,并给b1的tp结构体中的变量a赋值21,然后复制一个b2,给b2中的结构体的变量a赋值22,再输出b1的变量值,就是看看对b2操作能否改变b1
结果:
说明了两个tp指向同一个内存地址
自定义复制构造函数深拷贝:
#include<iostream>
using namespace std;
typedef struct{
int a;
}T,*TP;
class box{
public:
TP tp=(TP)malloc(sizeof(T));
box(){};
box(const box& b);
};
box::box(const box& b){
free(tp);
tp=(TP)malloc(sizeof(T));
tp->a=b.tp->a;
}
int main(){
box b1;
b1.tp->a=21;
box b2(b1);
b2.tp->a=22;
cout<<b1.tp->a;
}
重新给tp分配内存,再输出: