赞
踩
Objective-C是C语言的超集,具有面向对象的特性,也许也是通过函数指针什么的实现的!
面向对象三大特性:封装、继承、多态。要想实现面向对象,先把这三个东西实现再说。之后再想如何让它变得简单好用。
文中用的封装方法的模式和python一样,在写方法的时候需要把对象实例 self 传递进去。
void func(OBJ* self,int x,int y);
因为固定了参数 self 的类型,所以也就相当于封装了方法。
至于对于变量的封装 … \dots …
//Shape.h #ifndef _SHAPE_H_ #define _SHAPE_H_ #include<stdio.h> #include<stdlib.h> typedef struct _Shape { int x; int y; }Shape; Shape* ShapeCreate(int x, int y); void ShapeSet(Shape* self, int x, int y); void ShapeMove(Shape* self, int dx, int dy); void ShapeShow(Shape* self); #endif
//Shape.c #include "Shape.h" Shape* ShapeCreate(int x, int y) { Shape* s = (Shape*)malloc(sizeof(Shape)); s->x = x; s->y = y; return s; } void ShapeSet(Shape* self, int x, int y) { self->x = x; self->y = y; } void ShapeMove(Shape* self, int dx, int dy) { self->x += dx; self->y += dy; } void ShapeShow(Shape* self) { printf("(%3d,%3d)\n", self->x, self->y); }
//main.c #include"Shape.h" int main() { //创建Shape对象 Shape* s = ShapeCreate(0, 0); ShapeShow(s); //设置Shape对象 ShapeSet(s, 5, 5); ShapeShow(s); //移动Shape对象 ShapeMove(s, 10, 10); ShapeShow(s); system("pause"); return 0; }
显示结果:
( 0, 0)
( 5, 5)
( 15, 15)
请按任意键继续. . .
如果我在主函数中,直接访问两个变量这是没有问题的。也就是,这样的封装和python真是很相似呢!不能私有化变量,能封装的只有方法。而达到封装变量的目的,就只有大家心照不宣的通过函数来间接访问。
这个继承有点意思,定义一个新的结构体,把基类的结构体给包括进去。这样就达到了继承变量的目的。
在定义这样一个结构体时,基类的结构体必须放在头部。这个下面再讲!
//Shape.h #ifndef _SHAPE_H_ #define _SHAPE_H_ #include<stdio.h> #include<stdlib.h> typedef struct _Shape { int x; int y; }Shape; typedef struct _Rectangle { struct _Shape base; int width; int height; }Rectangle; Shape* ShapeCreate(int x, int y); void ShapeSet(Shape* self, int x, int y); void ShapeMove(Shape* self, int dx, int dy); void ShapeShow(Shape* self); Rectangle* RectangleCreate(int x, int y, int width, int height); void RectangleShow(Rectangle* r); #endif
//Shape.c #include "Shape.h" Shape* ShapeCreate(int x, int y) { printf("ShapeCreate......\n"); Shape* s = (Shape*)malloc(sizeof(Shape)); s->x = x; s->y = y; return s; } void ShapeSet(Shape* self, int x, int y) { self->x = x; self->y = y; } void ShapeMove(Shape* self, int dx, int dy) { printf("Moved....\n"); self->x += dx; self->y += dy; } void ShapeShow(Shape* self) { printf("info > (x = %3d, y = %3d)\n", self->x, self->y); } Rectangle* RectangleCreate(int x, int y, int width, int height) { printf("RectangleCreate.......\n"); Rectangle* r = (Rectangle*)malloc(sizeof(Rectangle)); ShapeSet(r, x, y); r->width = width; r->height = height; return r; } void RectangleShow(Rectangle* r) { printf("info > (x = %3d, y = %3d, width = %3d, height = %3d)\n", r->base.x, r->base.y, r->width, r->height); }
//main.c #include"Shape.h" int main() { //创建Shape对象 Shape* s = ShapeCreate(0, 0); ShapeShow(s); //设置Shape对象 ShapeSet(s, 5, 5); ShapeShow(s); //移动Shape对象 ShapeMove(s, 10, 10); ShapeShow(s); //创建Rectangle对象 Rectangle* r = RectangleCreate(0, 0, 2, 2); RectangleShow(r); //移动Rectangle对象 ShapeMove(r, 10, 10); RectangleShow(r); system("pause"); return 0; }
运行结果:
ShapeCreate......
info > (x = 0, y = 0)
info > (x = 5, y = 5)
Moved....
info > (x = 15, y = 15)
RectangleCreate.......
info > (x = 0, y = 0, width = 2, height = 2)
Moved....
info > (x = 10, y = 10, width = 2, height = 2)
请按任意键继续. . .
在RectangleCreate里用了基类的方法,在主函数里也用了ShapeMove。为什么这样包装一下结构体就能除了继承基类的变量,还能继承其方法呢?
在RectangleCreate函数中,r 是Rectangle类型,而使用ShapeSet传递过去的是 _Shape* 类型,所以存在强制类型转换。这个转换就存在使用的隐患。
如果把结构体_Rectangle定义成下面这样:
显示结果:
ShapeCreate......
info > (x = 0, y = 0)
info > (x = 5, y = 5)
Moved....
info > (x = 15, y = 15)
RectangleCreate.......
info > (x = 1629209996, y = -2147481600, width = 2, height = 2)
Moved....
info > (x = 1629209996, y = -2147481600, width = 12, height = 12)
请按任意键继续. . .
通过调试,发现在RectangleCreate内的ShapeSet运行时,_Rectangle对象实例的前面两个变量被当做了 _Shape 对象的变量。ShapeSet操作的就成了 width 和 height
原理就是下面这样:类型转换总是取的头部部分,且大小和转换后的类型大小一样。
这个也挺有意思,使用的是函数指针的方法。毕竟函数指针只要返回类型和参数定义好,那么这个函数指针就能和这一类的函数对应起来。
重载函数也是这样,子类重载的函数和基类的函数返回类型和参数定义都一样,所以可以用函数指针来实现。
//Shape.h #ifndef _SHAPE_H_ #define _SHAPE_H_ #include<stdio.h> #include<stdlib.h> struct _Shape; //虚函数表 struct _ShapeFuncTable { float(*area)(struct _Shape* self); void(*show)(struct _Shape* self); }; //实现封装 typedef struct _Shape { struct _ShapeFuncTable funcPtr; //实现多态 int x; int y; }Shape; //实现继承 //一个子类 typedef struct _Rectangle { struct _Shape base; int width; int height; }Rectangle; //又一个子类 typedef struct _Square { struct _Shape base; int side; }Square; //基类的方法 Shape* ShapeCreate(int x, int y); void ShapeSet(Shape* self, int x, int y); void ShapeMove(Shape* self, int dx, int dy); void ShapeShow(Shape* self);//实现多态的函数 float ShapeArea(Shape* self);//实现多态的函数 //子类的方法 Rectangle* RectangleCreate(int x, int y, int width, int height); void RectangleShow(Shape* self);//子类的重载的函数 float RectangleArea(Shape* self);//子类的重载的函数 //子类的方法 Square* SquareCreate(int x, int y, int side); void SquareShow(Shape* self);//子类的重载的函数 float SquareArea(Shape* self);//子类的重载的函数 #endif
//Shape.c #include "Shape.h" Shape* ShapeCreate(int x, int y) { printf("ShapeCreate......\n"); Shape* s = (Shape*)malloc(sizeof(Shape)); //基类不需要配置函数指针 s->funcPtr.area = NULL; s->funcPtr.show = NULL; //配置属性 s->x = x; s->y = y; return s; } void ShapeSet(Shape* self, int x, int y) { printf("ShapeSet.......+++\n"); self->x = x; self->y = y; } void ShapeMove(Shape* self, int dx, int dy) { printf("ShapeMove....>>>\n"); self->x += dx; self->y += dy; } //两个多态的基类的函数 void ShapeShow(Shape* self) { if (self->funcPtr.show != NULL) self->funcPtr.show(self); else { printf("ShapeShow.......\n"); printf("info > (x = %3d, y = %3d)\n", self->x, self->y); } } float ShapeArea(Shape* self) { if (self->funcPtr.area != NULL) return self->funcPtr.area(self); else { printf("ShapeArea.......\n"); return (self->x * self->y); } } Rectangle* RectangleCreate(int x, int y, int width, int height) { printf("RectangleCreate.......\n"); Rectangle* r = (Rectangle*)malloc(sizeof(Rectangle)); //配置函数指针 r->base.funcPtr.area = RectangleArea; r->base.funcPtr.show = RectangleShow; //配置Rectangle属性 ShapeSet(r, x, y); r->width = width; r->height = height; return r; } void RectangleShow(Shape* self) { printf("RectangleShow.......\n"); Rectangle* r = (Rectangle*)self; printf("info > (x = %3d, y = %3d, width = %3d, height = %3d)\n", r->base.x, r->base.y, r->width, r->height); } float RectangleArea(Shape* self) { printf("RectangleArea.......\n"); Rectangle* r = (Rectangle*)self; return (r->width * r->height); } Square* SquareCreate(int x, int y, int side) { printf("SquareCreate.......\n"); Square* s = (Square*)malloc(sizeof(Square)); //配置函数指针 s->base.funcPtr.area = SquareArea; s->base.funcPtr.show = SquareShow; //配置Square属性 ShapeSet(s, x, y); s->side = side; return s; } void SquareShow(Shape* self) { printf("SquareShow.......\n"); Square* s = (Square*)self; printf("info > (x = %3d, y = %3d, side = %3d)\n", s->base.x, s->base.y, s->side); } float SquareArea(Shape* self) { printf("SquareArea.......\n"); Square* s = (Square*)self; return (s->side * s->side); }
//main.c #include"Shape.h" int main() { //创建Shape对象 Shape* s = ShapeCreate(0, 0); ShapeShow(s); //设置Shape对象 ShapeSet(s, 5, 5); ShapeShow(s); //移动Shape对象 ShapeMove(s, 10, 10); ShapeShow(s); //创建Rectangle对象 Rectangle* r = RectangleCreate(0, 0, 2, 2); RectangleShow(r); ShapeShow(r);//和上面一条效果一样 r->base.funcPtr.show(r);//和上面一条效果一样 //移动Rectangle对象 ShapeMove(r, 10, 10); RectangleShow(r); ShapeShow(r);//和上面一条效果一样 printf("Rectangle面积是 > %3f\n", ShapeArea(r)); //创建Square对象 Square* sq = SquareCreate(0, 0, 55); SquareShow(sq); ShapeShow(sq);//和上面一条效果一样 printf("Square面积是 > %3f\n", ShapeArea(sq)); system("pause"); return 0; }
运行结果:
ShapeCreate...... ShapeShow....... info > (x = 0, y = 0) ShapeSet.......+++ ShapeShow....... info > (x = 5, y = 5) ShapeMove....>>> ShapeShow....... info > (x = 15, y = 15) RectangleCreate....... ShapeSet.......+++ RectangleShow....... info > (x = 0, y = 0, width = 2, height = 2) RectangleShow....... info > (x = 0, y = 0, width = 2, height = 2) ShapeMove....>>> RectangleShow....... info > (x = 10, y = 10, width = 2, height = 2) RectangleShow....... info > (x = 10, y = 10, width = 2, height = 2) RectangleArea....... Rectangle面积是 > 4.000000 SquareCreate....... ShapeSet.......+++ SquareShow....... info > (x = 0, y = 0, side = 55) SquareShow....... info > (x = 0, y = 0, side = 55) SquareArea....... Square面积是 > 3025.000000 请按任意键继续. . .
注意为指针变量分配内存
用指针的时候,一定要为这个指针申请一块内存。而我之前用了指针,但是没有申请内存,那么这个这个指针的值所代表的单元就不是我能够访问的了。
还有需要注意类型转换的问题。
在使用多态的函数时,比如ShapeArea,传入的子类对象实例会被强制转换成Shape对象,然后经过函数指针又被转换成子类对象,这样的过程存在内存冲突的风险。
要想把结构体变量都给私有化倒是挺简单!!!
把几个结构体的声明放在头文件内,把定义放在源文件内。
这样就把结构体内所有的变量都给私有化了。
//Shape.h #ifndef _SHAPE_H_ #define _SHAPE_H_ #include<stdio.h> #include<stdlib.h> typedef struct _Shape Shape; typedef struct _Rectangle Rectangle; typedef struct _Square Square; //虚函数表 struct _ShapeFuncTable { float(*area)(struct _Shape* self); void(*show)(struct _Shape* self); }; //基类的方法 Shape* ShapeCreate(char* name, int x, int y); void ShapeSet(Shape* self, int x, int y); //设置公有变量 void ShapeNameSet(Shape* self, char* name);//设置私有变量 name void ShapeMove(Shape* self, int dx, int dy); char* ShapeNameGet(Shape* self); //获取私有变量 void ShapeShow(Shape* self);//实现多态的函数 float ShapeArea(Shape* self);//实现多态的函数 //子类的方法 Rectangle* RectangleCreate(char* name, int x, int y, int width, int height); void RectangleShow(Shape* self);//子类的重载的函数 float RectangleArea(Shape* self);//子类的重载的函数 //子类的方法 Square* SquareCreate(char* name, int x, int y, int side); void SquareShow(Shape* self);//子类的重载的函数 float SquareArea(Shape* self);//子类的重载的函数 #endif
//Shape.c #include "Shape.h" //实现封装 typedef struct _Shape { struct _ShapeFuncTable funcPtr; //实现多态 //变量都是私有的 char* name; int x; int y; }Shape; //实现继承 //一个子类 typedef struct _Rectangle { struct _Shape base; int width; int height; }Rectangle; //又一个子类 struct _Square { struct _Shape base; int side; }; Shape* ShapeCreate(char* name, int x, int y) { printf("ShapeCreate......)))\n"); Shape* s = (Shape*)malloc(sizeof(Shape)); //配置属性 s->funcPtr.area = NULL; s->funcPtr.show = NULL; s->name = name; s->x = x; s->y = y; return s; } void ShapeSet(Shape* self, int x, int y) { printf("ShapeSet.......+++\n"); self->x = x; self->y = y; } void ShapeNameSet(Shape* self, char* name) { //设置私有变量 name self->name = name; } void ShapeMove(Shape* self, int dx, int dy) { printf("ShapeMove....\n"); self->x += dx; self->y += dy; } char* ShapeNameGet(Shape* self) { //获取私有变量 return self->name; } //两个多态的基类的函数 void ShapeShow(Shape* self) { if (self->funcPtr.show != NULL) (self->funcPtr.show)(self); else { printf("ShapeShow.......\n"); printf("info > (%10s ,x = %3d, y = %3d)\n", ShapeNameGet(self), self->x, self->y); } } float ShapeArea(Shape* self) { if (self->funcPtr.area != NULL) return (self->funcPtr.area)(self);//每次调用ShapeArea时,让这个函数指针指向不同的函数表,就实现了多态 else{ printf("ShapeArea.......\n"); return (self->x * self->y); } } Rectangle* RectangleCreate(char* name, int x, int y, int width, int height) { printf("RectangleCreate.......)))\n"); Rectangle* r = (Rectangle*)malloc(sizeof(Rectangle)); //配置函数指针 r->base.funcPtr.area = RectangleArea; r->base.funcPtr.show = RectangleShow; //配置Rectangle属性 ShapeSet(r, x, y); ShapeNameSet(r, name); r->width = width; r->height = height; return r; } void RectangleShow(Shape* self) { printf("RectangleShow.......\n"); Rectangle* r = (Rectangle*)self; printf("info > (%10s ,x = %3d, y = %3d, width = %3d, height = %3d)\n", ShapeNameGet(r), r->base.x, r->base.y, r->width, r->height); } float RectangleArea(Shape* self) { printf("RectangleArea.......\n"); Rectangle* r = (Rectangle*)self; return (r->width * r->height); } Square* SquareCreate(char* name, int x, int y, int side) { printf("SquareCreate.......)))\n"); Square* s = (Square*)malloc(sizeof(Square)); //配置函数指针 s->base.funcPtr.area = SquareArea; s->base.funcPtr.show = SquareShow; //配置Square属性 ShapeSet(s, x, y); ShapeNameSet(s, name); s->side = side; return s; } void SquareShow(Shape* self) { printf("SquareShow.......\n"); Square* s = (Square*)self; printf("info > (%10s ,x = %3d, y = %3d, side = %3d)\n", ShapeNameGet(s), s->base.x, s->base.y, s->side); } float SquareArea(Shape* self) { printf("SquareArea.......\n"); Square* s = (Square*)self; return (s->side * s->side); }
//main.c #include"Shape.h" int main() { //创建Shape对象 Shape* s = ShapeCreate("Shape", 0, 0); //printf("%d,%d,%s\n", s->x, s->y,s->name); //非法访问 ShapeShow(s); //设置Shape对象 ShapeSet(s, 5, 5); ShapeNameSet(s, "NewShape"); ShapeShow(s); //移动Shape对象 ShapeMove(s, 10, 10); ShapeShow(s); //创建Rectangle对象 Rectangle* r = RectangleCreate("Rectangle", 0, 0, 2, 2); ShapeShow(r); //移动Rectangle对象 ShapeMove(r, 10, 10); ShapeShow(r); printf("Rectangle面积是 > %3f\n", ShapeArea(r)); //创建Square对象 Square* sq = SquareCreate("Square", 0, 0, 55); ShapeShow(sq); printf("Square面积是 > %3f\n", ShapeArea(sq)); system("pause"); return 0; }
显示结果:
ShapeCreate......))) ShapeShow....... info > ( Shape ,x = 0, y = 0) ShapeSet.......+++ ShapeShow....... info > ( NewShape ,x = 5, y = 5) ShapeMove.... ShapeShow....... info > ( NewShape ,x = 15, y = 15) RectangleCreate.......))) ShapeSet.......+++ RectangleShow....... info > ( Rectangle ,x = 0, y = 0, width = 2, height = 2) ShapeMove.... RectangleShow....... info > ( Rectangle ,x = 10, y = 10, width = 2, height = 2) RectangleArea....... Rectangle面积是 > 4.000000 SquareCreate.......))) ShapeSet.......+++ SquareShow....... info > ( Square ,x = 0, y = 0, side = 55) SquareArea....... Square面积是 > 3025.000000 请按任意键继续. . .
简单的把声明和定义分开就私有化了所有变量,实现封装似乎也不过如此。
但是,这样就满足要求了吗?
但是这样就把结构体内所有的变量都封装了,私有化所有的变量不是我所期望的!我想要的是访问x,y这样的公有变量没有问题,而访问name这样的私有变量才报错。
那么,如何设计这样一个结构体,能既有私有的(定义在Shape.c中的结构体)也有公共的(定义在Shape.h的结构体)这两个部分呢?
\;
\;
\;
\;
\;
为了访问公有化变量,这个“总”的结构体一定要定义在Shape.h内,然后私有化变量的结构体定义在Shape.c内,所以只需要在_Shape结构体内定义一下私有的结构体就好。
说来也奇怪,如果像下面这样定义,那么会报错:
错误(活动) E0070 不允许使用不完整的类型 HHH E:\Can\HHH\HHH\Shape.h 27
此时27行这一直报错,使用了未定义的结构体。但是加了个星号后,又没错了???
是否可以每次遇到未定义结构体的时候就试试加星号呢?
我猜猜,凡是指针类型的变量,编译器就不管其类型是否之前声明过!!!
//Shape.h #ifndef _SHAPE_H_ #define _SHAPE_H_ #include<stdio.h> #include<stdlib.h> struct _Shape; //虚函数表 struct _ShapeFuncTable { float(*area)(struct _Shape* self); void(*show)(struct _Shape* self); }; //实现封装 typedef struct _Shape { struct _ShapeFuncTable funcPtr; //实现多态 //私有变量 struct _PrivateVariable* pVar; //公有变量 int x; int y; }Shape; //实现继承 //一个子类 typedef struct _Rectangle { struct _Shape base; int width; int height; }Rectangle; //又一个子类 typedef struct _Square { struct _Shape base; int side; }Square; //基类的方法 Shape* ShapeCreate(char* name, int x, int y); void ShapeSet(Shape* self, int x, int y); //设置公有变量 void ShapeNameSet(Shape* self, char* name);//设置私有变量 name void ShapeMove(Shape* self, int dx, int dy); char* ShapeNameGet(Shape* self); //获取私有变量 void ShapeShow(Shape* self);//实现多态的函数 float ShapeArea(Shape* self);//实现多态的函数 //子类的方法 Rectangle* RectangleCreate(char* name, int x, int y, int width, int height); void RectangleShow(Shape* self);//子类的重载的函数 float RectangleArea(Shape* self);//子类的重载的函数 //子类的方法 Square* SquareCreate(char* name, int x, int y, int side); void SquareShow(Shape* self);//子类的重载的函数 float SquareArea(Shape* self);//子类的重载的函数 #endif
//Shape.c #include "Shape.h" //私有变量 typedef struct _PrivateVariable { char* name; }PVar; Shape* ShapeCreate(char* name, int x, int y) { printf("ShapeCreate......)))\n"); Shape* s = (Shape*)malloc(sizeof(Shape)); //配置属性 s->funcPtr.area = NULL; s->funcPtr.show = NULL; ShapeNameSet(s, name); s->x = x; s->y = y; return s; } void ShapeSet(Shape* self, int x, int y) { printf("ShapeSet.......+++\n"); self->x = x; self->y = y; } void ShapeNameSet(Shape* self, char* name) { //设置私有变量 name self->pVar = (PVar*)malloc(sizeof(PVar)); self->pVar->name = name; } void ShapeMove(Shape* self, int dx, int dy) { printf("ShapeMove....\n"); self->x += dx; self->y += dy; } char* ShapeNameGet(Shape* self) { //获取私有变量 return self->pVar->name; } //两个多态的基类的函数 void ShapeShow(Shape* self) { if (self->funcPtr.show != NULL) (self->funcPtr.show)(self); else { printf("ShapeShow.......\n"); printf("info > (%10s ,x = %3d, y = %3d)\n", ShapeNameGet(self), self->x, self->y); } } float ShapeArea(Shape* self) { if (self->funcPtr.area != NULL) return (self->funcPtr.area)(self);//每次调用ShapeArea时,让这个函数指针指向不同的函数表,就实现了多态 else{ printf("ShapeArea.......\n"); return (self->x * self->y); } } Rectangle* RectangleCreate(char* name, int x, int y, int width, int height) { printf("RectangleCreate.......)))\n"); Rectangle* r = (Rectangle*)malloc(sizeof(Rectangle)); //配置函数指针 r->base.funcPtr.area = RectangleArea; r->base.funcPtr.show = RectangleShow; //配置Rectangle属性 ShapeSet(r, x, y); ShapeNameSet(r, name); r->width = width; r->height = height; return r; } void RectangleShow(Shape* self) { printf("RectangleShow.......\n"); Rectangle* r = (Rectangle*)self; printf("info > (%10s ,x = %3d, y = %3d, width = %3d, height = %3d)\n", ShapeNameGet(r), r->base.x, r->base.y, r->width, r->height); } float RectangleArea(Shape* self) { printf("RectangleArea.......\n"); Rectangle* r = (Rectangle*)self; return (r->width * r->height); } Square* SquareCreate(char* name, int x, int y, int side) { printf("SquareCreate.......)))\n"); Square* s = (Square*)malloc(sizeof(Square)); //配置函数指针 s->base.funcPtr.area = SquareArea; s->base.funcPtr.show = SquareShow; //配置Square属性 ShapeSet(s, x, y); ShapeNameSet(s, name); s->side = side; return s; } void SquareShow(Shape* self) { printf("SquareShow.......\n"); Square* s = (Square*)self; printf("info > (%10s ,x = %3d, y = %3d, side = %3d)\n", ShapeNameGet(s), s->base.x, s->base.y, s->side); } float SquareArea(Shape* self) { printf("SquareArea.......\n"); Square* s = (Square*)self; return (s->side * s->side); }
main.c没更改,显示结果也一致。
为了验证是否实现了私有化和公有化变量共存的情况,可以在主函数内访问几个变量试试。
既然前面私有化变量,那么私有化函数也是同样的道理!
//Shape.h ... //实现封装 typedef struct _Shape { //私有函数 struct _PrivateFuncTable* pFuncPtr; //公有函数 struct _ShapeFuncTable funcPtr; //私有变量 struct _PrivateVariable* pVar; //公有变量 int x; int y; }Shape; ...
//Shape.c ... //私有化函数 typedef struct _PrivateFuncTable { void(*set)(struct _Shape* self); }PFuncT; //私有函数 void ShapeAddX(Shape* self) { printf("ShapeSet.......ooo\n"); self->x+=100; } //初始化私有函数 #define PRIVATE_FUNC_INIT(func) \ {\ s->pFuncPtr = (PFuncT*)malloc(sizeof(PFuncT));\ s->pFuncPtr->set = func;\ } Shape* ShapeCreate(char* name, int x, int y) { printf("ShapeCreate......)))\n"); Shape* s = (Shape*)malloc(sizeof(Shape)); //配置属性 PRIVATE_FUNC_INIT(ShapeAddX); s->funcPtr.area = NULL; s->funcPtr.show = NULL; ShapeNameSet(s, name); s->x = x; s->y = y; return s; } //提供给外面使用私有函数接口 void Shape_UsePrivateFunc(Shape* self) { (self->pFuncPtr->set)(self); } ...
仅仅是两个area,show这种固定的函数还是不行,为了之后的可拓展性,我需要定义参数可变的函数,并且扩大虚函数表,返回类型也需要多种多样!!!
为了不影响前面的代码,避免不小心的错误,之前的两个旧的函数指针就留着。
建立下面这样一张表后,随便实现几个函数看看!
//虚函数表
struct _ShapeFuncTable {
//旧表
float(*area)(struct _Shape* self);
void(*show)(struct _Shape* self);
//待扩展的表
int(*MyFuncPtr_INT)(struct _Shape* self, ...);
float(*MyFuncPtr_FLOAT)(struct _Shape* self, ...);
double(*MyFuncPtr_DOUBLE)(struct _Shape* self, ...);
void(*MyFuncPtr_VOID)(struct _Shape* self,...);
char*(*MyFuncPtr_STR)(struct _Shape* self, ...);
};
//Shape.h
#define FREE_OBJ(obj) free(obj);obj=NULL
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。