C语言程序的模块化——封装(1)

C语言类的封装?没错,就是C,而不是什么C++、C#的类的封装!

说到封装这个面向对象的基本特征,那么有必要一起谈一谈面向对象和封装这两个概念和关系。

1、面向对象(Object Oriented,OO)是软件开发方法。面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统、交互式界面、应用结构、应用平台、分布式系统、网络管理机构、CAD技术、人工智能等领域。面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。

简单的说,面向对象是一种思想,而编程语言是实现面向对象这种思想的工具和方法

2、面向对象和封装的关系

面向对象的类是封装良好的模块,类定义将其说明(用户可见的外部接口)与实现(用户不可见的内部实现)显式地分开,其内部实现按其具体定义的作用域提供保护。

封装是保证软件部件具有优良的模块性的基础对象是封装的最基本单位。封装防止了程序相互依赖而带来的变动影响。

使用枚举、结构体模拟类属性,模拟接口。

实际用例:

#ifndef __CPU_H__

#define __CPU_H__

扫描二维码关注公众号,回复: 5801271 查看本文章

#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));

}

...

猜你喜欢

转载自blog.csdn.net/qq_33712422/article/details/82977504
今日推荐