c语言面向对象编程私有方法,C语言面向对象编程

OO Programing in C is not only

POSSIBLE, but also PRACTICAL.

--------------------------------------------------------------------------------

“class“是很多OO编程语言里的关键字,它来源于OO鼻祖Smalltalk。class(类),是对一群有相同特性的对象的抽象概括,对象称为类的实例。在class里面可以存放有状态(变量),行为(函数/方法)....有关OO概念、方法的文章太多了,不再啰嗦。在C里面,唯一可以实现自定义类型的是struct,struct是C的OO编程最重要的工具。

一个最常见的技巧,就是用struct来"仿真"class: 在struct里面放入变量,函数指针,嵌入其他struct等。

以下例子摘自我最近刚开发完成的一个USB Firmware项目:

C代码 a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

structusb_device;

structusb_ctl;

structusb_iobuf {

intlen;

unsignedcharbuf[USBEPFIFO_SIZE];

};

structusb_endpoint {inttype;

intqlen;

xQueueHandle lock;

xQueueHandle q;

intidx;

intepx;

intcfg;

intbank;

inttxCount;void(*ep_process) (structusb_device *dev,structusb_endpoint *ep, xISRStatus *pxMessage);

};

structusb_descriptor {

inttype;

intidx;

intsize;

void* data;

structlist_head list;

};

structusb_deviceOps {

int(*init)(structusb_device *dev);

int(*reset)(structusb_device *dev);

int(*switch_in)(structusb_device *dev);

int(*switch_out)(structusb_device *dev);

void(*class_interface_req)(structusb_device *dev, xUSB_REQUEST *pxRequest);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;

intconf;

eDRIVER_STATE state;

xCONTROL_MESSAGE tx;

xCONTROL_MESSAGE rx;

structubufm *bufmn;

intprio;

xTaskHandle task_handle;

structusb_ctlOps *ctlOps;

};

structusb_device {

charname[16];

structusb_deviceOps *ops;

structusb_ctl *ctl;

structlist_head desc_list;

structusb_endpoint *ep[MAX_ENDPOINTS];

intactive;

xQueueHandle ready;

void*private;

structlist_head list;

};

struct usb_device;

struct usb_ctl;

struct usb_iobuf {

int len;

unsigned char buf[USBEPFIFO_SIZE];

};

struct usb_endpoint { int type;

int qlen;

xQueueHandle lock;

xQueueHandle q;

int idx;

int epx;

int cfg;

int bank;

int txCount; void (*ep_process) (struct usb_device *dev, struct usb_endpoint *ep, xISRStatus *pxMessage);

};

struct usb_descriptor {

int type;

int idx;

int size;

void * data;

struct list_head list;

};

struct usb_deviceOps {

int (*init)(struct usb_device *dev);

int (*reset)(struct usb_device *dev);

int (*switch_in)(struct usb_device *dev);

int (*switch_out)(struct usb_device *dev);

void (*class_interface_req)(struct usb_device *dev, xUSB_REQUEST *pxRequest); int (*ctl_data_comp)(struct usb_device *dev, xCONTROL_MESSAGE *pxMessage);

};

struct usb_ctlOps {

void (*ctl_transmit_null)(struct usb_ctl *ctl);

void (*ctl_send_stall)(struct usb_ctl *ctl);

void (*ctl_reset_ep0)(struct usb_ctl *ctl);

void (*ctl_detach_usb)(struct usb_ctl *ctl);

void (*ctl_attach_usb)(struct usb_ctl *ctl);

void (*ctl_send_data)(struct usb_ctl *ctl, unsigned char *data,

int req_len,

int send_len,

int is_des);

};

struct usb_ctl {

int addr;

int conf;

eDRIVER_STATE state;

xCONTROL_MESSAGE tx;

xCONTROL_MESSAGE rx;

struct ubufm *bufmn;

int prio;

xTaskHandle task_handle;

struct usb_ctlOps *ctlOps;

};

struct usb_device {

char name[16];

struct usb_deviceOps *ops;

struct usb_ctl *ctl;

struct list_head desc_list;

struct usb_endpoint *ep[MAX_ENDPOINTS];

int active;

xQueueHandle ready;

void *private;

struct list_head list;

};

在这个例子,我用struct分别描述了USB设备,USB控制通道,USB端点,USB描述符和USB缓冲区对象。USB设备对象包含了若干个USB端点,一个USB控制通道指针,一个USB描述符表的表头(指向若干个USB描述符),和一个USB缓冲区管理对象。而且,USB设备对象还包含了name属性,一个由USB

Framework调用的回调函数集,还有一个用于连接其他USB设备的链表节点。

值得一提的是,USB设备对象中有一个void *private

成员,可以指向任何数据。实际上在我的程序里,我实现了usb-serial和usb-mass-storage两个USB设备,对于usb-serial对象,private我弃之不用,而在usb-mass-storage对象中,private指向一个Mass

storage对象,usb-mass-storage正是通过这个Mass

storage对象访问外部大容量存储的(在我的程序里,Mass storage对象和一个MMC

Card对象绑定,外部存储是SD/MMC卡)。由于对于每一种设备的具体实现来说,它知道private指向的是何种类型的设备,因此不会引起混乱。而外部程序根据需要在初始化USB设备对象前赋予private有意义的值——运行时动态绑定。

这一系列struct基本上如实地反映了USB DEVICE硬件逻辑和规范要求:

"一个USB设备包含若干个端点,其中有一个固定的控制端点(端点0)。在枚举阶段USB设备要根据HOST的请求应答相应的描述符..."

现在回到OO的话题,这个例子中体现了"组合类":USB设备对象包含了USB端点对象,USB描述符对象...。还有动态绑定

(private成员)。从严格的OO意义上来看,好像有点"怪",不过我认为这恰恰是C的特点——简洁,直接。不信你用C++表达试试?也许会更漂亮,很OO,但是不一定会如此清爽!

P.S. : 熟悉USB Firmware开发的人可能对struct

usb_endpoint中的epx,cfg,bank和txCount四个成员有异议,因为这些成员是和特定的硬件相关,并不是所有的USB硬件都支持ping-pong

mode,所以bank和txCount不一定用得上,epx,

cfg也可能因硬件的不同而不同。没错!更理想的设计是把与硬件相关的部分分离出来,用void

*private指向各自的与硬件相关的配置——就像struct usb_device所采用方法,所以更好的版本应该是:

Java代码 a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

struct usb_endpoint {

inttype;

intqlen;

xQueueHandle lock;

xQueueHandle q;

intidx;

void(*ep_process)(struct usb_device *dev, struct usb_endpoint *ep, xISRStatus *pxMessage);

void*private;

};

struct usb_endpoint {

int type;

int qlen;

xQueueHandle lock;

xQueueHandle q;

int idx;

void (*ep_process)(struct usb_device *dev, struct usb_endpoint *ep, xISRStatus *pxMessage);

void *private;

};

tips: 用C表达的一个关键处就是要很好地应用struct来描述模型。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
面向对象的基本特征包括封装、继承和多态。在C语言中,这些特征可以通过一些技术来实现。 封装是将数据和对这些数据进行操作的代码封装成一个单元,只暴露必要的接口供外部使用。在C语言中,可以通过定义结构体来封装数据,并使用函数操作这些数据。结构体中可以包含私有成员,对外部不可见,从而实现数据的保护性。封装的优点是可以隐藏并保护数据,提高安全性和可维护性,但缺点是实现相对复杂,需要手动管理内存。 继承是指一个类从另一个类继承属性和方法C语言中通过结构体和指针实现类似继承的机制。可以定义一个结构体,其中包含自身需要继承的成员,然后使用指针指向结构体的子结构体。继承的优点是代码重用性高,减少了重复编写的工作量,但缺点是较为繁琐,需要手动管理指针的内存释放。 多态是指同一类型的对象,在不同的情境下可以表现出不同的行为。在C语言中,可以通过函数指针来实现多态。定义一个可以指向不同函数的函数指针,根据不同的情境来赋予不同的函数,从而达到多态的效果。多态的优点是提高了代码的灵活性和可扩展性,但缺点是对函数的设计要求较高,并且实现稍显复杂。 总的来说,C语言可以通过结构体、指针和函数指针等技术来实现面向对象的基本特征。封装可以通过结构体和函数的组合来实现数据和操作的封装;继承可以通过结构体和指针实现类似继承的机制;多态可以通过函数指针来实现。但相比于专门面向对象的编程语言,C语言的实现相对繁琐,并且需要手动管理内存和指针,容易出错。因此,在使用C语言实现面向对象的特性时,需要额外注意代码的可读性和正确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值