C语言下的封装 继承 与多态.docx

上传人:b****4 文档编号:4877595 上传时间:2022-12-11 格式:DOCX 页数:11 大小:23.54KB
下载 相关 举报
C语言下的封装 继承 与多态.docx_第1页
第1页 / 共11页
C语言下的封装 继承 与多态.docx_第2页
第2页 / 共11页
C语言下的封装 继承 与多态.docx_第3页
第3页 / 共11页
C语言下的封装 继承 与多态.docx_第4页
第4页 / 共11页
C语言下的封装 继承 与多态.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

C语言下的封装 继承 与多态.docx

《C语言下的封装 继承 与多态.docx》由会员分享,可在线阅读,更多相关《C语言下的封装 继承 与多态.docx(11页珍藏版)》请在冰豆网上搜索。

C语言下的封装 继承 与多态.docx

C语言下的封装继承与多态

C语言下的封装、继承与多态

上次课,钱SIR提到,Liux下面也有很多用C实现的面向对象的结构。

比较感觉兴趣,就在网上查了一些资料,原来C语言模拟实现面向对象语言所具有的特性:

多态,继承,封装,也是一件很简单的事儿。

并且现在很多开源软件都了用C语言实现了这几个特性,包括大型开源数据库系统postgreSQL,可移植的C语言面向对象框架GObject。

在自己机器上实践了下,感叹C语言的灵活与强大!

总结一下,以便交流:

一、基础知识

(1)结构体

结构体可以嵌套,因而可以把一个结构体当成另一个结构体的成员,如:

[cpp]viewplaincopyprint?

1.structPoint{

2.intx;

3.inty;

4.};

[cpp]viewplaincopyprint?

1.structCircle{

2.structPointpoint_;

3.intradius;

4.};

该结构体与以下定义完全一样(包括内存布置都一样

[cpp]viewplaincopyprint?

1.structCircle{

2.intx;

3.inty;

4.intradius;

5.};

(2)void*

指针是整个C语言的精髓所在。

而你也一直敬畏着指针,又爱又恨地使用着它。

许多教材都告诉你,int*叫做指向整型的指针,而char*是指向字符型的指针,等等等等不一而足。

然而这里有一个另类的指针家族成员——void*。

不要按照通常的命名方式叫它做指向void类型的指针,它的正式的名字叫做:

可以指向任意类型的指针。

(3)C中的参数个数可变函数

可变参数函数的原型声明:

[cpp]viewplaincopyprint?

1.typeVAFunction(typearg1,typearg2,…);

参数可以分为两部分:

个数确定的固定参数和个数可变的可选参数。

函数至少需要一个固定参数,固定参数的声明和普通函数一样;可选参数由于个数不确定,声明时用"..."表示。

固定参数和可选参数公同构成一个函数的参数列表。

标准C/C++包含头文件stdarg.h,该头文件中定义了操作不定变量的相关宏:

[cpp]viewplaincopyprint?

1.voidva_start(va_listarg_ptr,prev_param);/*ANSIversion*/

2.typeva_arg(va_listarg_ptr,type);

3.voidva_end(va_listarg_ptr);

在这些宏中,va就是variableargument(可变参数)的意思;

arg_ptr是指向可变参数表的指针;

prev_param指可变参数表的前一个固定参数;

type为可变参数的类型。

va_list也是一个宏,其定义为typedefchar*va_list,实质上是一char型指针。

具体用法可以参考:

二、封装

封装的主要含义是隐藏内部的行为和信息,使用者只用看到对外提供的接口和公开的信息。

在C语言中的实现方法:

把私有数据信息放在一个不透明的priv变量或者结构体中,只有类的实现代码才知道priv或者结构体的真正定义。

例如:

头文件:

[cpp]viewplaincopyprint?

1.//========头文件:

Point.h文件========

2.#ifndefPOINT_H

3.#definePOINT_H

4.typedefstructPointpoint;

5.typedefstructpointPrivatepointPrivate;

6.structPoint

7.

8.{

9.structpointPrivate*pp;};

10.intget_x(point*point_);

11.intget_y(point*point_);

12.point*new_point(intx,inty);

13.}

14.#endif

源文件

[cpp]viewplaincopyprint?

1.//=======C文件:

Point.c文件========

2.#include"Point.h"

3.#include

4.structpointPrivate;

5.intx;

6.inty;

7.};

8.

9.intget_x(point*point_){

10.returnpoint_->pp->x;

11.}

12.

13.intget_y(point*point_){

14.returnpoint_->pp->y;

15.}

16.

17.point*new_point(intx,inty){

18.point*p=(point*)malloc(sizeof(point));

19.p->pp=(pointPrivate*)malloc(sizeof(pointPrivate));

20.p->pp->x=x;

21.p->pp->y=y;

22.returnp;

23.}

测试文件:

[cpp]viewplaincopyprint?

1.intmain()

2.{

3.point*p=new_point(1,2);

4.//printf("x:

%d,y:

%d\n",p->pp->x,p->pp->y);

5.printf("x:

%d,y:

%d\n",get_x(p),get_y(p));

6.}

在测试代码中,注释掉的一部分是编译不过的,因为我们已经把pointPrivate结构体的定义隐藏了。

而且必须使用new_point来创建point结构对象,否则无法初始化point结构体中的pp成员变量。

有意思的是:

这段代码生成的exe文件可能会被360误认为病毒。

三、继承

在C语言中,可以利用“结构在内存中的布局与结构的声明具有一致的顺序”这一事实实现继承。

比如我们要设计一个作图工具,其中可能涉及到的对象有Point(点),Circle(圆),由于圆是由点组成的,所有可以看成Circle继承自Point。

另外,Point和Circle都需要空间申请,空间释放等操作,所有他们有共同的基类Base。

[cpp]viewplaincopyprint?

1.//基类Base的内部头文件Base.r,对外隐藏

2.#ifndefBASE_R

3.#defineBASE_R

4.#include

5.structBase{

6.size_tsize;

7.void*(*ctor)(void*self,va_list*app);//构造函数

8.void*(*dtor)(void*self);//析构函数

9.void(*draw)(constvoid*self);//作图函数

10.};

11.#endif

12.

13.//Point的内部头文件Point.r,对外隐藏

14.#ifndefPOINT_R

15.#definePOINT_R

16.structPoint{

17.constvoid*base;//继承Base类,基类指针,放在第一个位置,const是防止修改

18.intx,y;//坐标

19.};

20.#definex(p)(((conststructPoint*)(p))->x)

21.#definey(p)(((conststructPoint*)(p))->y)

22.#endif

23.

24.//Point的头文件Point.h(对外提供接口)

25.#ifndefPOINT_H

26.#definePOINT_H

27.externconstvoid*Point;/*new(Point,x,y);*/

28.voidmove(void*point,intdx,intdy);

29.#endif

30.

31.//Point的源文件Point.c

32.#include

33.#include"Point.h"

34.#include"Point.r"

35.#include"new.h"

36.#include"Base.r"

37./**********Point类自己的构造函数***********/

38.staticvoid*Point_ctor(void*_self,va_list*app){

39.structPoint*self=_self;

40.self->x=va_arg(*app,int);

41.self->y=va_arg(*app,int);

42.returnself;

43.}

44./**********Point类自己的绘图函数***********/

45.staticvoidPoint_draw(constvoid*_self){

46.conststructPoint*self=_self;

47.printf("Pointat%d,%d\n",self->x,self->y);

48.}

49.staticconststructBase_Point={

50.sizeof(structPoint),Point_ctor,0,Point_draw

51.};

52.constvoid*Point=&_Point;

53.voidmove(void*_self,intdx,intdy){

54.structPoint*self=_self;

55.self->x+=dx,self->y+=dy;

56.}

57.

58.//Circle内部头文件Circle.r,对外隐藏

59.#ifndefCIRCLE_R

60.#defineCIRCLE_R

61.#include"Point.r"

62.structCircle{

63.conststructPoint_;//继承Point类,需放在第一位

64.intrad;

65.};

66.#endif

67.

68.//Circle的头文件Circle.h(对外提供接口)

69.#ifndefCIRCLE_H

70.#defineCIRCLE_H

71.#include"Point.h"

72.externconstvoid*Circle;/*new(Circle,x,y,rad)*/

73.#endif

74.

75.//Circle的源文件Circle.c

76.#include

77.#include"Circle.h"

78.#include"Circle.r"

79.#include"new.h"

80.#include"Base.r"

81./**********Circle类自己的构造函数***********/

82.staticvoid*Circle_ctor(void*_self,va_list*app){

83.structCircle*self=((conststructBase*)Point)->ctor(_self,app);

84.self->rad=va_arg(*app,int);

85.returnself;

86.}

87./**********Circle类自己的绘图函数***********/

88.staticvoidCircle_draw(constvoid*_self){

89.conststructCircle*self=_self;

90.printf("circleat%d,%drad%d\n",x(self),y(self),self->rad);

91.}

92.staticconststructBase_Circle={

93.sizeof(structCircle),Circle_ctor,0,Circle_draw

94.};

95.constvoid*Circle=&_Circle;

96.

97.//内存管理类头文件new.h(对外提供接口)

98.#ifndefNEW_H

99.#defineNEW_H

100.void*new(constvoid*base,...);

101.voiddelete(void*item);

102.voiddraw(constvoid*self);

103.#endif

104.

105.//内存管理类的源文件:

new.c

106.#include

107.#include

108.#include

109.#include"Base.r"

110.void*new(constvoid*_class,...){

111.conststructBase*base=_class;

112.void*p=calloc(1,base->size);

113.assert(p);

114.*(conststructBase**)p=base;

115.if(base->ctor){

116.va_listap;

117.va_start(ap,_class);

118.p=base->ctor(p,&ap);

119.va_end(ap);

120.}

121.returnp;

122.}

123.voiddelete(void*self){

124.conststructBase**cp=self;

125.if(self&&*cp&&(*cp)->dtor)

126.self=(*cp)->dtor(self);

127.free(self);

128.}

129.voiddraw(constvoid*self){

130.conststructBase*const*cp=self;

131.assert(self&&*cp&&(*cp)->draw);

132.(*cp)->draw(self);

133.}

四、多态可以是用C语言中的万能指针void*实现多态,接上面的例子:

[cpp]viewplaincopyprint?

1.#include"Circle.h"

2.#include"new.h"

3.intmain(intargc,char**argv)

4.{

5.void*p;

6.inti;

7.for(i=0;i<2;i++)

8.{

9.if(i==0)

10.p=new(Circle,1,2,3);

11.else

12.p=new(Point,1,2);

13.draw(p);

14.move(p,10,20);

15.draw(p);

16.delete(p);

17.}

18.return0;

19.}

输出结果:

circleat1,2rad3

circleat11,22rad3

Pointat1,2

Pointat11,22

五、总结

面向对象是一种程序设计思想,而C语言则是一种编程语言。

也许它并不是专门为了面向对象编程而设计,但是这绝不意味着它不能实现面向对象的程序设计。

当然以上所展示的这几个操作,如果是用别的编程语言,可能只要寥寥几行就可以完成,但是C语言想告诉我们的是:

也许我不擅长,但是并不意味着我做不到。

注:

有些头文件名被csdn误认为内部命令,而变很很诡异,请以所下载的代码为准。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1