中国大学MOOC程序设计与算法(三):C++ 面向对象程序设计 第四周 运算符重载 笔记 之 运算符重载实例:可变长数组类的实现

第四周 运算符重载
1.运算符重载的基本概念
2.赋值运算符的重载
3.运算符重载为友元函数
4.运算符重载实例:可变长数组类的实现
5.流插入运算符和流提取运算符的重载
6.类型转换运算符、自增自减运算符的重载

4.运算符重载实例:可变长数组类的实现

int main() { //要编写可变长整型数组类,使之能如下使用:
	CArray a; //开始里的数组是空的
	for( int i = 0;i < 5;++i)
		a.push_back(i);
	CArray a2,a3;
	a2 = a;
	for( int i = 0; i < a.length(); ++i )
		cout << a2[i] << " " ;
	a2 = a3; //a2是空的
		for( int i = 0; i < a2.length(); ++i ) //a2.length()返回0
	cout << a2[i] << " ";
	cout << endl;
	a[3] = 100;
	CArray a4(a);
		for( int i = 0; i < a4.length(); ++i )
	cout << a4[i] << " ";
	return 0;
}

程序输出结果是:
0 1 2 3 4
0 1 2 100 4
要做哪些事情?
1)a.push_back(i);->要用动态分配的内存来存放数组元素,需要一个指针成员变量,在析构函数里面释放内存
2) i < a.length();->要定义成员函数length
3)a2 = a;->要重载“=”
4)cout << a2[i] << " " ;->要重载“[ ]”
5)CArray a4(a);->要自己写复制构造函数,不能是缺省的

class CArray {
	int size; //数组元素的个数
	int *ptr; //指向动态分配的数组
	public:
		CArray(int s = 0); //构造函数,s代表数组元素的个数
		CArray(CArray & a);//复制构造函数
		~CArray();//析构函数
		void push_back(int v); //用于在数组尾部添加一个元素v
		CArray & operator=( const CArray & a);//用于数组对象间的赋值,深拷贝
		int length() { return size; } //返回数组元素个数
		int & CArray::operator[](int i) //返回值为 int 不行!不支持 a[i] = 4,所以得是引用
		{
			//用以支持根据下标访问数组元素,
			// 如n = a[i] 和a[i] = 4; 这样的语句
			return ptr[i];
			//非引用的函数返回值不能作为左值使用
		}
};
CArray::CArray(int s):size(s)
{
	if( s == 0)
		ptr = NULL;
	else
		ptr = new int[s];
}
CArray::CArray(CArray & a)
 {
	//如果不自己定义复制构造函数,那么程序会自动默认的复制构造函数,当执行CArray a2(a1);语句时,结果是a2的所有成员都和a1相同,那就会二者指向同一块内存,这是无法接受的。
	if( !a.ptr) {
		ptr = NULL;
		size = 0;
		return;
	}
	ptr = new int[a.size];
	memcpy( ptr, a.ptr, sizeof(int ) * a.size);
	size = a.size;
}
CArray::~CArray()
{
	if( ptr) 
		delete [] ptr;
}
CArray & CArray::operator=( const CArray & a)
{  
	// 赋值号的作用是使“=” 左边对象里存放的数组,大小和内容都和右边的对象一样
	if( ptr == a.ptr) // 防止a=a 这样的赋值导致出错
		return * this;
	if( a.ptr == NULL) { // 如果a 里面的数组是空的
		if( ptr )//如果原数组非空,要先收回存储空间
			delete [] ptr;
		ptr = NULL;
		size = 0;
		return * this;
	}
	if( size < a.size) {// 如果原有空间不够大,需要重新分配空间
		 if(ptr)
			delete [] ptr;
		ptr = new int[a.size];
	}
	// 如果原有空间够大,就不用分配新的空间
	memcpy( ptr,a.ptr,sizeof(int)*a.size);
	size = a.size;
	return * this;
} // CArray & CArray::operator=( const CArray & a)
void CArray::push_back(int v)
{ 
	// 在数组尾部添加一个元素
	if( ptr) {
		int * tmpPtr = new int[size+1]; // 重新分配空间
		memcpy(tmpPtr,ptr,sizeof(int)*size); // 拷贝原数组内容
		delete [] ptr;
		ptr = tmpPtr;
	}
	else // 数组本来是空的
		ptr = new int[1];
	ptr[size++] = v; // 加入新的数组元素
}

注意:void CArray::push_back(int v)这个函数每次执行都要重复性地申请新的空间、销毁原有空间,效率较低,可以从初始化开始,每次分配n(如32)个空间,当size达到n时才执行一次申请、销毁,其余是不需要的,这样可以提高效率。STL里面的vector就是这样的一种高效的可变长数组。

你可能感兴趣的:(中国大学MOOC程序设计与算法(三):C++ 面向对象程序设计 第四周 运算符重载 笔记 之 运算符重载实例:可变长数组类的实现)