除非您能够在结构的“用户”读取它的位置和数据所在的位置之间注入代码,否则它不是封装。这样的垫片允许您在不改变结构的外部使用的情况下更改结构的内部结构。
虽然您的解决方案是对通常在 C 中完成的方式的改进,但为了封装它,您需要能够将字段从单个值更改为构造值,而无需更改任何“外部”代码来证明它是真的封装了。
在 C 中,这通常是通过将数据隐藏在 void 指针后面,或者在封装代码的外部使用声明的(但未定义的)结构来执行的。
废话
struct myStruct_t;
typedef struct myStruct_t myStruct;
extern myStruct * const ptrConstMyStruct;
// if you want a constructor, you need to declare the
// method here, because only blah.c will know the struct
// size with this solution.
myStruct * new_myStruct();
// methods
myStruct_setData(myStruct* obj, char c);
char myStruct_getData(myStruct* obj);
废话.c
#include "blah.h"
struct myStruct_t {
unsigned char data;
unsigned int intdata;
};
static myStruct thisIsMyModulesData;
// no need to make the struct const, just the pointer
// otherwise, we would have to break the const just to change
// data, which now will only be done within this file.
myStruct * const ptrConstMyStruct = &thisIsMyModulesData;
另一个文件.c
#include "blah.h"
// anotherFile "knows" of a struct called myStruct, but
// it doesn't know what it contains, or even it's size.
// this is no longer possible
// now "data" is encapsulated, and can be changed
// by reimplementing `myStruct_getData(...)`
// (as long as we don't change the method signature).
variable = ptrConstMyStruct->data;
// this is the "new" way
variable = myStruct_getData(ptrConstmyStruct);
// with the old, compiler error because of
// assigning a value to a const value.
ptrConstMyStruct->data = variable; //compile error!
^
(error occurs here)
// with the new, compiler error because of
// dereferencing a pointer to a unknown / incomplete type.
ptrConstMyStruct->data = variable; // compile error!
^
(error occurs here)
如您所见,错误的位置决定了封装与否。ptrConstMyStruct->data
如果您在分配而不是取消引用时检查错误,则无法更改指针和数据之间的关系。