C语言类的封装?没错,就是C,而不是什么C++、C#的类的封装!
说到封装这个面向对象的基本特征,那么有必要一起谈一谈面向对象和封装这两个概念和关系。
1、面向对象(Object Oriented,OO)是软件开发方法。面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统、交互式界面、应用结构、应用平台、分布式系统、网络管理机构、CAD技术、人工智能等领域。面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。
简单的说,面向对象是一种思想,而编程语言是实现面向对象这种思想的工具和方法。
2、面向对象和封装的关系
面向对象的类是封装良好的模块,类定义将其说明(用户可见的外部接口)与实现(用户不可见的内部实现)显式地分开,其内部实现按其具体定义的作用域提供保护。
封装是保证软件部件具有优良的模块性的基础,对象是封装的最基本单位。封装防止了程序相互依赖而带来的变动影响。
使用枚举、结构体模拟类属性,模拟接口。
实际用例:
#ifndef __CPU_H__
#define __CPU_H__
#ifdef __cplusplus
extern "C"
{#endif
/***************************枚举*****************************/
typedef enum _choose_t{
SWITCH_CHO0SE_1 =1,
SWITCH_CHO0SE_2,
SWITCH_CHO0SE_3,
}abc_choose_t;
/**************************结构体*************************/
typedef struct{
uint8_t chSwitchMessage;
uint8_t chSwitchID;
}Switch_message_t;
#ifdef __cplusplus
}
#endif
#endif
看上去,貌似很简单......只是作为一个类,不能都是公有吧?什么时候都得留点自己的空间吧?若是都是公有,恐怕没啥秘密了...若是按照接口信息最小公开的潜规则,这样写估计的死翘翘了吧?
下面看一段经过先驱验证过的代码:
参考样例(实际中没这么搞过,直接复制了,样例来源于: [微知识]模块的封装(一):C语言类的封装)
(一)
封装代码(学名:掩码结构体(Masked Structure),是不是很形象?)
#define __EXTERN_CLASS_OBJ( __TYPE, __OBJ )
extern union {
CLASS(__TYPE) __##__OBJ;
__TYPE __OBJ;
};
#define EXTERN_CLASS_OBJ(__TYPE, __OBJ)
__EXTERN_CLASS_OBJ( __TYPE, __OBJ )
#define __EXTERN_CLASS(__NAME,...)
/*typedef union __NAME __NAME; */
union __NAME {
__VA_ARGS__
uint_fast8_t __NAME##__chMask[(sizeof(struct{
__VA_ARGS__
#define EXTERN_CLASS(__NAME, ...) __EXTERN_CLASS(__NAME, __VA_ARGS__)
#define END_EXTERN_CLASS(__NAME, ...)
}) + sizeof(uint_fast8_t) - 1) / sizeof(uint_fast8_t)];
};
#define DECLARE_CLASS(__NAME)
typedef union __NAME __NAME;
#define __DEF_CLASS(__NAME,...)
/*typedef union __NAME __NAME; */
typedef struct __##__NAME __##__NAME;
struct __##__NAME {
__VA_ARGS__
#define DEF_CLASS(__NAME, ...) __DEF_CLASS(__NAME, __VA_ARGS__)
#define __END_DEF_CLASS(__NAME, ...)
};
union __NAME {
__VA_ARGS__
uint_fast8_t __NAME##__chMask[(sizeof(__##__NAME) + sizeof(uint_fast8_t) - 1) / sizeof(uint_fast8_t)];
};
#define END_DEF_CLASS(__NAME, ...) __END_DEF_CLASS(__NAME, __VA_ARGS__)
#define __CLASS(__NAME) __##__NAME
#define CLASS(__NAME) __CLASS(__NAME)
queue.h
...
//! \name byte queue
//! @{
EXTERN_CLASS(queue_t)
uint8_t *pchBuffer; //!< queue buffer
uint16_t hwBufferSize; //!< buffer size
uint16_t hwHead; //!< head pointer
uint16_t hwTail; //!< tail pointer
uint16_t hwCounter; //!< byte counter
END_EXTERN_CLASS(queue_t)
//! @}
...
extern bool queue_init(queue_t *ptQueue, uint8_t *pchBuffer, uint16_t hwSize);
extern bool enqueue(queue_t *ptQueue, uint8_t chByte);
extern bool dequeue(queue_t *ptQueue, uint8_t *pchByte);
extern bool is_queue_empty(queue_t *ptQueue);
...
(二)
queue.c
...
//! \name byte queue
//! @{
DEF_CLASS(queue_t)
uint8_t *pchBuffer; //!< queue buffer
uint16_t hwBufferSize; //!< buffer size
uint16_t hwHead; //!< head pointer
uint16_t hwTail; //!< tail pointer
uint16_t hwCounter; //!< byte counter
END_DEF_CLASS(queue_t)
//! @}
...
...
bool is_queue_empty(queue_t *ptQueue)
{
CLASS(queue_t) *ptQ = (CLASS(queue_t) *)ptQueue;
if (NULL == ptQueue) {
return true;
}
return ((ptQ->hwHead == ptQ->hwTail) && (0 == ptQ->Counter));
}
...