对于Point类
显然是将b的坐标值赋值给a的坐标
Point a,b;
a = b;
看下一个demo:
TextFile a, b;
a.Open( "FILE1.DAT" );
b.Open( "FILE2.DAT" );
b = a;
前面的代码可能表示“将 FILE1.DAT 的内容复制到 FILE2.DAT”,也可能表示“忽略 FILE2.DAT 并使 b
成为 FILE1.DAT 的另一个句柄”。
这里的歧义需要自己去实现 复制构造函数和复制赋值运算符 来达到想要的效果。
一般的:
复制构造函数:T(const T& x);
复制赋值运算符:T & operator=(const T & x);
如果不声明复制构造函数,编译器将为你生成 member-wise 复制构造函数。 如果不声明复制赋值运算符,编译器将为你生成 member-wise 复制赋值运算符。
对于复制构造函数,需要知道:何时调用和有何功能
何时调用:
新建一个对象并将其初始化为同类现有对象
表现形式有:
other是一个T类的对象
①T x(other);
②T x = other;
③T x = T(other);
④T *x = new T(other);
说明:
②和③:可以直接创建T类x对象,也可以创建一个临时对象将其成员的值赋给x
④创建匿名对象,x是其指针。
由于按值传递对象调用复制构造函数,因此应该按引用传递对象。这样可以节省调用构造函数的时间以及存储新对象的空间。
一、如果没有实现复制构造函数,那么系统有隐式复制构造函数 实现的是 对象的”浅拷贝”
如果遇到成员变量是指针,那么两者的指针指向位置相同。
当类调用析构函数时,会释放同一个地址,导致程序崩溃。
二、为了避免上述问题,解决方案是实现显式复制构造函数
新开辟一个相同大小的空间,利用内存(或字符串)拷贝给新开辟的空间。该方法也成“深拷贝”
三、一般的,如果类中包含了使用new初始化的指针成员,需要实现复制构造函数,反之则使用默认复制构造函数。
赋值运算符的功能和何时调用
一、首先初始化一个对象T x;
x = other; //other是T类对象
这时候调用了赋值运算符函数
与复制构造函数会遇到的问题相同:数据受损。
解决方法与前面类似。
总结:复制构造函数在对象初始化的时候调用,之后用到“=”赋值运算符的时候调用赋值函数
贴上demo:
#include <iostream>
#include <string>
using namespace std;
class Rect
{
public:
Rect()//默认构造函数
{
_m_byte = NULL;
memset(_byte, 0, sizeof(_byte));
}
Rect(int x, int y, int width, int height, char * byte, char * m_byte)//普通构造
: _x(x), _y(y), _width(width), _height(height)
{
strcpy(_byte, byte);
_m_byte = new char[strlen(m_byte) + 1];//开辟空间记得+1防止数组越界
strcpy(_m_byte, m_byte);
}
Rect(const Rect& other)//复制构造函数
{
strcpy(_byte, other._byte);
_m_byte = new char[strlen(other._m_byte) + 1];
strcpy(_m_byte, other._m_byte);
}
Rect& operator=(const Rect & other)//赋值运算符函数
{
if(this == &other) //先进行判定是否相同的对象
return *this;
if(_m_byte) //判断是否开辟过空间
delete []_m_byte;
strcpy(_byte, other._byte);
_m_byte = new char[strlen(other._m_byte) + 1];
strcpy(_m_byte, other._m_byte);
return *this;
}
~Rect() //析构函数 释放new出来的_m_byte 防止内存泄露
{
_x = 0;
_y = 0;
_width = 0;
_height = 0;
memset(_byte, 0, sizeof(_byte));
delete []_m_byte;
_m_byte = NULL;
}
/********************************************************************************/
/*偷懒就直接写成共有成员了,一般是私有变量,使用get(),或set()方法提取或设置成员变量的值*/
/********************************************************************************/
int _x;
int _y;
int _width;
int _height;
char _byte[100];
char *_m_byte;
private:
};
int main()
{
Rect r(1,1,1,1,"123","234");//调用普通构造
Rect r2 = r; //调用复制构造函数
Rect r3; //调用默认构造
r3 = r; //调用赋值运算符函数
cout << string(r._m_byte) << endl;
cout << string(r2._m_byte) << endl;
cout << string(r3._m_byte) << endl;
system("pause");
}