默认的拷贝构造函数:
默认的拷贝构造不是空函数,默认进行浅拷贝,是比较危险的行为;
浅拷贝:只进行变量之间的简单的赋值操作,没有将变量绑定的外部资源进行分配,比如说:一个指针指向一块堆内存,然后该指针将值赋给了另外一个指针;
int *p = new int;
int * q = p;
如上图。
我们接着上一篇文章来讲:
class CGoods
{
public:
CGoods(char *const name, int count, float price)
{
if (name == NULL)
{
_name = new char;
*_name = '\0'; //如果是空也给分配一个字节内存,避免操作空指针挂掉
}
else
{
_name = new char[strlen(name) + 1];
strcpy(_name, name);
}
_count = count;
_price = price;
}
CGoods(CGoods const &src);
void show();
void setname(char *name){ strcpy(_name, name); }
void getname(char *name){ strcpy(name, _name); }
//char *getname(){ return _name ;}
//该函数会将_name的地址返回回去,如果类外拿到地址,可以通过地址解引用来修改内存中的值,不满足面向对象的封装
float getprice(){ return _price; }
private:
char *_name;
int _count;
float _price;
};
//类外定义,函数名前加上类的作用域,告诉编译器产生的这个函数符号是类的作用域下的
void CGoods::show()
{
cout << "name: " << _name << "price: " << _price << "count:" << _count << endl;
}
int main()
{
CGoods c1("苹果", 10, 8.9);
CGoods c2("香蕉", 11, 9.8);
CGoods c3 = c2;
c1.show();
c2.show();
return 0;
}
执行结果:
name: 苹果price: 8.9count:10
name: 香蕉price: 9.8count:11
请按任意键继续. . .
我们将拷贝构造函数单独拿出来说:
//类外实现 拷贝构造函数
//拷贝构造函数,生成新对象,
//该方法属于this和src两个对象共有的,所以可以直接访问对象的成员变量和方法
CGoods :: CGoods(CGoods const &src)//src指向的是右值,this指向的是左值
{
//开辟一个和src一样大的内存,不能和src指向同一块内存,各自有各自的内存
_name = new char[strlen(src._name) + 1];
//将this指针的内存中数据初始化为src对象的内存中的数据
strcpy(_name,src._name);
_count = src._count;
_price = src._price;
}
关于拷贝构造函数参数为什么是引用的原因:见上一篇文章
还是上面的程序,我们进行下面的操作:
c1 = c2 ; //赋值操作
从上图我们可以看到:
对象c1和对象c2都有着各自的堆内存,如果将c1 = c2,c1将指向c2的堆内存,那么c1原来的内存该怎么办?是不是就泄露了?嗯是的。
所以,为了解决这个问题,赋值运算符函数 才需要我们重新实现,也就是重载;
默认的赋值运算符重载函数:
只进行简单的赋值,被赋值的对象原来的内存没有释放将被泄露,所以需要我们重载该实现;
赋值运算符函数重载的实现:
//赋值运算符函数参数可以传值吗?const CGoods src
//可以运行 但是给src开辟新的内存,到时候操作的就不是实参的src,而是形参
void CGoods :: operator=(const CGoods &src)
{
//1.防止自赋值,this保存的地址和src引用的对象的地址一样时
if (this == &src)
return;
//2.在接收其他对象的数据之前,先要删掉自己原来已有的外部资源
delete _name;
//3.防止浅拷贝,重新申请新的空间,并用src的数据给赋过去
_name = new char[strlen(src._name) + 1];
strcpy(_name, src._name);
_count = src._count;
_price = src._price;
}
int main()
{
CGoods c1("苹果", 10, 8.9);
CGoods c2("香蕉", 11, 9.8);
c2 = c1;
c1.show();
c2.show();
return 0;
}
执行结果:
name: 苹果price: 8.9count:10
name: 苹果price: 8.9count:10
请按任意键继续. . .