C语言面向对象编程.docx
- 文档编号:28134574
- 上传时间:2023-07-08
- 格式:DOCX
- 页数:20
- 大小:28.32KB
C语言面向对象编程.docx
《C语言面向对象编程.docx》由会员分享,可在线阅读,更多相关《C语言面向对象编程.docx(20页珍藏版)》请在冰豆网上搜索。
C语言面向对象编程
C语言面向对象编程
原创作者:
rubynroll 阅读:
5643次 评论:
0条 更新时间:
2008-12-15
经常看到关于OO编程的讨论,C++,Java,C#...还有最近很流行的动态语言Python,Ruby等,但很少看到有C的份。
在我看来,OO编程的核心是OO的思想,用什么语言倒是其次。
但是,不可否认,那些专门为OO编程设计的语言可以比较方便和自然地表达OO思想,有些语言甚至强制使用OO特性。
C,作为最贴近底层的高级语言,拥有简洁的语法和直接内存操作能力(指针),大量运用于系统级编程,如操作系统内核,驱动程序等。
而在嵌入式系统中,由于资源有限等因素,更倾向于用C编程。
C虽然在语言特性上并没有体现OO特性,但是依然可以通过各种编程技巧来体现OO的思想。
由于C的高度自由的特点,在OO编程方面还能体现有别于其他语言的特殊韵味。
目录[-]
1.C的面向对象概念
2.用struct来仿真class
3.实现OO的继承机制
C的面向对象概念
OOPrograminginCisnotonlyPOSSIBLEbutalsoPRACTICAL.
--------------------------------------------------------------------------------
OO思想在Unix世界中很早就有:
UNIX把设备抽象成文件,这样就可以用一套相同的方法(open,read,write,close,...)去访问不同的设备和文件——尽管设备之间的差异很大。
用OO的观点来看,这些“设备”对象都实现了"文件操作接口",可以想象有一个叫"文件"的基类,定义了"文件操作接口",“设备”对象继承了“文件”对象....。
在实现角度看,在内核里面,设备驱动提供了自己的read,write等实现,并用它们去填充文件操作结构体里面的函数指针....这和C++里面的虚函数运行时绑定的道理是一样的。
(C++虚函数是其实是运行时静态绑定,而文件操作接口可以运行时动态绑定:
-)
Linux内核中则处处体现了OO的思想。
2.6内核的DeviceDriverModal是一套层次分明又错综复杂的机制,其中体现了许多OO设计理念。
虽然可能设备驱动程序开发者觉察不到,但所有的设备驱动对象内部都隐藏了一个叫KObject的对象。
内核把这些KObjects互相联系在一起,并通过KObject的相互关系构造了/sys文件系统。
/sys就是内核中各种设备对象的映射图,如果把/sys全部展开,我们可以清楚地看到各种对象的关系。
实践证明,C也可以很好地用于OO编程,而且可以用于构造很复杂的系统,而且C在表达OO思想的时候并不会显得蹩脚,而是可以很简单,很自然。
用struct来仿真class
OOPrograminginCisnotonlyPOSSIBLE,butalsoPRACTICAL.
--------------------------------------------------------------------------------
“class“是很多OO编程语言里的关键字,它来源于OO鼻祖Smalltalk。
class(类),是对一群有相同特性的对象的抽象概括,对象称为类的实例。
在class里面可以存放有状态(变量),行为(函数/方法)....有关OO概念、方法的文章太多了,不再啰嗦。
在C里面,唯一可以实现自定义类型的是struct,struct是C的OO编程最重要的工具。
一个最常见的技巧,就是用struct来"仿真"class:
在struct里面放入变量,函数指针,嵌入其他struct等。
以下例子摘自我最近刚开发完成的一个USBFirmware项目:
C代码
1.struct usb_device;
2.struct usb_ctl;
3.
4.struct usb_iobuf {
5. int len; /* data length in the buffer */
6. unsigned char buf[USBEPFIFO_SIZE]; /* data buffer itself */
7.};
8.
9.struct usb_endpoint { int type; /* endpoint type:
BULKIN, BULKOUT, CTL, ISO ... */
10. int qlen; /* queue length */
11.
12. xQueueHandle lock; /* semaphore lock */
13. xQueueHandle q; /* data queue (pointer of bulk_buf) */
14.
15. int idx; /* endpoint index */
16. int epx; /* endpoint mark bit */
17. int cfg; /* endpoint configure */
18. int bank; /* current operation bank (for ping-pong mode) */
19. int txCount; /* used for ping-pong mode */ /* endpoint data process function */ void (*ep_process) (struct usb_device *dev, struct usb_endpoint *ep, xISRStatus *pxMessage);
20.};
21.
22.struct usb_descriptor {
23. int type; /* descriptor type:
device, conf, string or endpoint */
24. int idx; /* descriptor index (for string descriptor) */
25. int size; /* descriptor size */
26. void * data; /* descriptor data */
27. struct list_head list; /* link list of descriptors */
28.};
29.
30.struct usb_deviceOps {
31. int (*init)(struct usb_device *dev); /* called when framework init usb device, add device descriptors, init private data ... etc. */
32. int (*reset)(struct usb_device *dev); /* called when reseted by host */
33. int (*switch_in)(struct usb_device *dev); /* called when switch in */
34. int (*switch_out)(struct usb_device *dev); /* called when swithc out */ /* called when HOST request class interface data */
35. void (*class_interface_req)(struct usb_device *dev, xUSB_REQUEST *pxRequest); /* called when HOST complete the data sending stage */ int (*ctl_data_comp)(struct usb_device *dev, xCONTROL_MESSAGE *pxMessage);
36.};
37.
38.struct usb_ctlOps {
39. void (*ctl_transmit_null)(struct usb_ctl *ctl);
40. void (*ctl_send_stall)(struct usb_ctl *ctl);
41. void (*ctl_reset_ep0)(struct usb_ctl *ctl);
42. void (*ctl_detach_usb)(struct usb_ctl *ctl);
43. void (*ctl_attach_usb)(struct usb_ctl *ctl);
44. void (*ctl_send_data)(struct usb_ctl *ctl, unsigned char *data,
45. int req_len,
46. int send_len,
47. int is_des);
48.};
49.
50.
51.struct usb_ctl {
52. int addr; /* address alloced by host */
53. int conf; /* configuration set by host */
54. eDRIVER_STATE state; /* current status */
55. xCONTROL_MESSAGE tx; /* control transmit message */
56. xCONTROL_MESSAGE rx; /* control receive message */
57. struct ubufm *bufmn; /* 'usb_iobuf' buffer manager, shared by all usb devices */
58. int prio; /* the main task priority */
59. xTaskHandle task_handle; /* the main task handler */
60. struct usb_ctlOps *ctlOps; /* control endpoint operations */
61.};
62.
63.struct usb_device {
64. char name[16]; /* device name, e.g. "usbser" */
65. struct usb_deviceOps *ops; /* usb device callback functions */
66.
67. struct usb_ctl *ctl; /* usb control enpoint, provided by framework */
68. struct list_head desc_list; /* usb descriptors */
69. struct usb_endpoint *ep[MAX_ENDPOINTS]; /* endpoints */
70. int active; /* whether the device is active */
71. xQueueHandle ready; /* notify this queue when usb device ready */
72. void *private; /* device private data */
73. struct list_head list; /* link list of usb device */
74.};
structusb_device;
structusb_ctl;
structusb_iobuf{
intlen;/*datalengthinthebuffer*/
unsignedcharbuf[USBEPFIFO_SIZE];/*databufferitself*/
};
structusb_endpoint{inttype;/*endpointtype:
BULKIN,BULKOUT,CTL,ISO...*/
intqlen;/*queuelength*/
xQueueHandlelock;/*semaphorelock*/
xQueueHandleq;/*dataqueue(pointerofbulk_buf)*/
intidx;/*endpointindex*/
intepx;/*endpointmarkbit*/
intcfg;/*endpointconfigure*/
intbank;/*currentoperationbank(forping-pongmode)*/
inttxCount;/*usedforping-pongmode*//*endpointdataprocessfunction*/void(*ep_process)(structusb_device*dev,structusb_endpoint*ep,xISRStatus*pxMessage);
};
structusb_descriptor{
inttype;/*descriptortype:
device,conf,stringorendpoint*/
intidx;/*descriptorindex(forstringdescriptor)*/
intsize;/*descriptorsize*/
void*data;/*descriptordata*/
structlist_headlist;/*linklistofdescriptors*/
};
structusb_deviceOps{
int(*init)(structusb_device*dev);/*calledwhenframeworkinitusbdevice,adddevicedescriptors,initprivatedata...etc.*/
int(*reset)(structusb_device*dev);/*calledwhenresetedbyhost*/
int(*switch_in)(structusb_device*dev);/*calledwhenswitchin*/
int(*switch_out)(structusb_device*dev);/*calledwhenswithcout*//*calledwhenHOSTrequestclassinterfacedata*/
void(*class_interface_req)(structusb_device*dev,xUSB_REQUEST*pxRequest);/*calledwhenHOSTcompletethedatasendingstage*/int(*ctl_data_comp)(structusb_device*dev,xCONTROL_MESSAGE*pxMessage);
};
structusb_ctlOps{
void(*ctl_transmit_null)(structusb_ctl*ctl);
void(*ctl_send_stall)(structusb_ctl*ctl);
void(*ctl_reset_ep0)(structusb_ctl*ctl);
void(*ctl_detach_usb)(structusb_ctl*ctl);
void(*ctl_attach_usb)(structusb_ctl*ctl);
void(*ctl_send_data)(structusb_ctl*ctl,unsignedchar*data,
intreq_len,
intsend_len,
intis_des);
};
structusb_ctl{
intaddr;/*addressallocedbyhost*/
intconf;/*configurationsetbyhost*/
eDRIVER_STATEstate;/*currentstatus*/
xCONTROL_MESSAGEtx;/*controltransmitmessage*/
xCONTROL_MESSAGErx;/*controlreceivemessage*/
structubufm*bufmn;/*'usb_iobuf'buffermanager,sharedbyallusbdevices*/
intprio;/*themaintaskpriority*/
xTaskHandletask_handle;/*themaintaskhandler*/
structusb_ctlOps*ctlOps;/*controlendpointoperations*/
};
structusb_device{
charname[16];/*devicename,e.g."usbser"*/
structusb_deviceOps*ops;/*usbdevicecallbackfunctions*/
structusb_ctl*ctl;/*usbcontrolenpoint,providedbyframework*/
structlist_headdesc_list;/*usbdescriptors*/
structusb_endpoint*ep[MAX_ENDPOINTS];/*endpoints*/
intactive;/*whetherthedeviceisactive*/
xQueueHandleready;/*notifythisqueuewhenusbdeviceready*/
void*private;/*deviceprivatedata*/
structlist_headlist;/*linklistofusbdevice*/
};
在这个例子,我用struct分别描述了USB设备,USB控制通道,USB端点,USB描述符和USB缓冲区对象。
USB设备对象包含了若干个USB端点,一个USB控制通道指针,一个USB描述符表的表头(指向若干个USB描述符),和一个USB缓冲区管理对象。
而且,USB设备对象还包含了name属性,一个由USBFramework调用的回调函数集,还有一个用于连接其他USB设备的链表节点。
值得一提的是,USB设备对象中有一个void*private成员,可以指向任何数据。
实际上在我的程序里,我实现了usb-serial和usb-mass-storage两个USB设备,对于usb-serial对象,private我弃之不用,而在usb-mass-storage对象中,private指向一个Massstorage对象,usb-mass-storage正是通过这个Massstorage对象访问外部大容量存储的(在我的程序里,Massstorage对象和一个MMCCard对象绑定,外部存储是SD/MMC卡)。
由于对于每一种设备的具体实现来说,它知道private指向的是何种类型的设备,因此不会引起混乱。
而外部程序根据需要在初始化USB设备对象前赋予private有意义的值——运行时动态绑定。
这一系列struct基本上如实地反映了USBDEVICE硬件逻辑和规范要求:
"一个USB设备包含若干个端点,其中有一个固定的控制端点(端点0)。
在枚举阶段USB设备要根据HOST的请求应答相应的描述符..."
现在回到OO的话题,这个例子中体现了"组合类":
USB设备对象包含了USB端点对象,USB描述符对象...。
还有动态绑定(private成员)。
从严格的OO意义上来看,好像有点"怪",不过我认为这恰恰是C的特点——简洁,直接。
不信你用C++表达试试?
也许会更漂亮,很OO,但是不一定会如此清爽!
P.S.:
熟悉USBFirmware开发的人可能对structusb_endpoint中的epx,cfg,bank和txCount四个成员有异议,因为这些成员是和特定的硬件相关,并不是所有的USB硬件都支持ping-pongmode,所以bank和txCount不一定用得上,epx,cfg也可能因硬件的不同而不同。
没错!
更理想的设计是把与硬件相关的部分分离出来,用void*private指向各自的与硬件相关的配置——就像structusb_device所采用方法,所以更好的版本应该是:
Java代码
1.struct usb_endpoint {
2. int type; /* endpoint type:
BULKIN, BULKOUT, CTL, ISO ... */
3. int q
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 面向 对象 编程