对象数组的实例。
class Coordinate
{
public:
int m_iX;
int m_iY;
};
int main()
{
Coordinate coord[3];//栈中实例化
coord[1].m_iX = 10;
Coordinate *p = new Coordinate[3];//堆中实例化
p[0].m_iY = 20; p->m_iY = 20
delete[]p;
p = NULL;
return 0;
}
在用new申请数组空间后,要用delete []p来释放掉内存,那为什么要加[]呢。
在申请一个对象数组时,分别调用了n次的构造函数,在释放时也要调用n次析构函数,如果不加[],那么只销毁指针指向的第一个元素。
在实际应用中,对象中包含对象是很常见的,如一个房间有桌子等家具。以下为代码实例。
class Coordinate//坐标系上的点
{
public:
Coordinate();
private:
int m_iX;
int m_iY;
};
class Line//坐标系上的线
{
public:
line();
private:
Coordinate m_coorA;
Coordinate m_coorB;
};
int main()
{
Line *p = new Line();
delete p;
p = NULL;
return 0;
}
那么,在实例化对象时,是先实例化点还是先实例化线呢》
在实例化线时,先实例化A,再实例化B,最后实例化Line。销毁时正好与创建的过程相反。
拷贝构造函数分为深拷贝和浅拷贝。一个浅拷贝的实例代码。
class Array
{
public:
Array(){ m_iCount = 5; m_pArr = new int[m_iCount]; }//构造函数,指向堆申请的内存
Array(const Array& arr)//拷贝构造函数
{
m_iCounta = arr.m_iCount;
m_pArr = arr.m_pArr;
}
private:
int m_iCount;
int *m_pArr;//指针
};
int main()
{
Array arr1;
Array arr2 = arr1;//这种情况下,浅拷贝
return 0;
}
这种情况很危险,因为两个指针指向统一内存,当改变arr1的内存,arr2的内容也势必会被改变,当释放arr1时,arr2也会释放,会引起崩溃。因此要实现深拷贝,即两个指针指向不同的内存,如图。
要实现深拷贝,代码如下。
class Array
{
public:
Array(){ m_iCount = 5; m_pArr = new int[m_iCount]; }//构造函数,指向堆申请的内存
Array(const Array& arr)//拷贝构造函数,深拷贝
{
m_iCounta = arr.m_iCount;
m_pArr = new int[m_iCount];
for (int i = 0; i < m_iCount; i++)
{
m_pArr[i] = arr.m_pArr[i];
}
}
private:
int m_iCount;
int *m_pArr;//指针
};
int main()
{
Array arr1;
Array arr2 = arr1;//这种情况下,浅拷贝
return 0;
}
对象指针,就是指针指向一个对象。
class Coordinate//坐标系上的点
{
public:
int m_iX;
int m_iY;
};
Coordinate *p = new Coordinate;//在堆中实例化
在实例化是,p的指针实际指向的是m_iX,在实例化对象时,下列代码中的注释部分也是符合语法的。
int main()
{
Coordinate *p = new Coordinate;//在堆中实例化
p->m_iX = 10;//(*p).m_iX=10;
p->m_iY = 20;//(*p).m_iY=20;
delete p;
p = NULL;
return 0;
}
对象成员指针,在累的成员中包含指针,如下代码。
class Coordinate//坐标系上的点
{
public:
Coordinate(int x, int y);
private:
int m_iX;
int m_iY;
};
class Line//坐标系上的线
{
public:
Line();
~Line();
private:
Coordinate *m_pCoorA;
Coordinate *m_pCoorB;
};
Line::Line() :m_pCoorA(NULL), m_pCoorB(NULL)//初始化列表初始
{
}
Line::Line()//普通初始化
{
m_pCoorA=NULL;
m_pCoorB=NULL;
}
当然更一般的是赋予指针值。
Line::Line()//普通初始化
{
m_pCoorA=new Coordinate(1,3);
m_pCoorB=new Coordinate(5,6);
}
Line::~Line()
{
delete m_pCoorA;
delete m_pCoorB;
}
特别值得注意的是,如果用sizeof查看line的话,那么打印出为8,因为每个指针地址是4个内存单元。而不是16(4个int)。
this指针。
一般来说,类函数的传递参数和成员不同名,如下代买所示。
class Array
{
public:
Array(int _len){ len = _len; }
int getLen(){ return len; }
void setLen(int _len){ len = _len; }
private:
int len;
};
那么,如果同名的话,会发生什么,如下代码,编译器会报错,因为无法分辨哪个是作为参数的Len。
class Array
{
public:
Array(int len){ len = len; }
int getLen(){ return len; }
void setLen(int len){ len = len; }
private:
int len;
};
因此,我们需要一种技术来标注出参数或者标注出数据成员。这就是this指针。