3.复杂对象的使用与this指针
3.1 动态对象与对象指针
3.1.1 对象指针
◼对象指针指向对象存放的地址
◼ 定义与使用
类名 *对象指针名;
对象指针名->数据成员;
对象指针名->数据函数;
◼ 优点:地址传递,效率高
3.1.2 动态对象
CCircle *g_pc = NULL; //定义了一个对象指针 void display() { g_pc->Draw(); //使用对象指针,CCirle里面的Draw函数 } void keyboard(unsigned char key) { switch (key) { case '1': if (g_pc!=NULL) //指针的使用 delete g_pc; //杯子里倒水,换杯子 g_pc = new CCircle(400, 300, 100, PURPLE); //动态对象 break; //就是新建和释放空间 case '2': if (g_pc!=NULL) delete g_pc; g_pc = new CCircle(500, 200, 150, RED); break; } }
CCircle *g_c=NULL; int g_n = 0; void LoadCircles(const char *fileName) { FILE *fp = NULL; float x, y, r; int clr; fp = fopen(fileName, "r"); //打开并读取文件,因为有很多的数 fscanf(fp, "%d", &g_n); cout <<g_n <<endl; g_c = new CCircle[g_n]; //连续的数列,g_c指向首地址 for(int i=0; i<g_n; i++) { fscanf(fp, "%f %f %f %d", &x, &y, &r, &clr); g_c[i].Set(x, y, r, clr); } fclose(fp); } delete []g_c; //new时有【】,delete时也有
3.2 对象引用
3.3 对象数组
◼ 与对象为元素的数组
◼ 定义与初始化
类名 对象数组名[n];
初始化:
数组名[n] = { 类名(初始值1,初始值2,..),
类名(初始值1,初始值2,..),
… 类名(初始值1,初始值2,..) } ;
CCircle g_cir[2] = {CCircle(300,200,100,RED),CCircle(200,280,30,BLUE)}; int a[2] = { 1 , 2 }; void display() { // g_pc->Draw(); for(int i=0;i<2;i++) g_cir[i].Draw(); }
3.4 this指针
◼ 一个系统预定义的指针,指向当前对象(即当前对象的地址)
this指针:哪里需要哪里搬,就是指向结构体首地址的,v0和v1用的是同一个成员函数
v1和v0都有自己各自的地址,x和y虽然名字一样但所在的地址也不一样,一样的是this指针只有一个,所以是到处指的。
*this:返回当前的对象
3.5 组合对象
3.5.1 定义
就是在一个类1(组合类)中,调用了别的类2(成员类):类2 p(组合对象)
class CPoint //传说中的成员类 { float x; float y; public: CPoint(float _x=0, float _y=0) //初始化 { x = _x; y = _y; } float GetX() {return x;} float GetY() {return y;} void SetX(float _x) {x=_x;} void SetY(float _y) {y=_y;} void Move(float dx, float dy) { x+=dx; y+=dy; } }; class CCircle { CPoint p; //来啦来啦!组合对象! unsigned long clr; float r; public: CCircle(float x, float y, int _r, unsigned long _clr=0x00FF00):p(x, y) { r = _r; //p.x=x;p.y=y;❌为私有的,能不能直接操作,若改为公有的 clr = _clr; //在使用p的时候,会自动调用带默认参数的构造函数,所以多了几步, cout << "Circle con1" << endl; } CCircle(CPoint _p, int _r):p(_p) { r = _r; cout << "Circle con2" << endl; } double GetArea(); double GetPerimeter(); void Move(float dx, float dy); void Set(float x, float y); void Scale(float s); }; //代码重用:不仅是圆类,三角形类、巨星类都可以用,Move函数只有一个版本。只用写一次 void CCircle::Move(float dx, float dy) { p.Move(dx, dy); }
■ 成员对象按照在其组合类的声明中出现的次序,依次调用各自的构造函数, 而不是按初始化列表中的顺序
void Set(float x, float y) { p.x = x; p.y = y; } //不可以访问,私有的 void Set(float x, float y) { p.SetX(x); p.SetY(y); } //写个函数,在函数里访问就可以啦