如果您想在 c 中使用私有变量,有许多技术可以近似私有变量,但 C 语言实际上没有延伸到私有、公共、受保护的“保护”概念(就像 C++ 那样)。
C 将显示任何变量的名称(这是 C 中的要求),因此您必须通过隐藏变量类型的信息来处理它(使取消引用变得非常困难)。
一个技巧是将变量定义为一个仅在一个模块void*
中知道实际变量类型的变量。.c
/* somefile.h */
extern void* counter;
/* somefile.c */
#include "somefile.h"
int actualCounter = 0;
void* counter = &actualCounter;
/* otherfile.c */
#include "somefile.h"
// we can see "counter", but we cannot "use" it here; because we don't have access
// to the real "hidden" type of "int".
更好的方法是使用struct
关键字扩展这个想法,并制作伪方法,就像这样
/* person.h */
struct s_person;
typedef Person struct s_person;
Person* new_Person(char* name);
void delete_Person(Person* person);
void Person_setName(Person* person, char* name);
char* Person_getName(Person* person);
/* person.c */
struct s_person {
char* name;
};
Person* new_Person(char* name) {
Person* object = (Person*)malloc(sizeof(struct s_person));
// duplicate the string for more security, otherwise constructor
// could manipulate the "private" string after construction.
object->name = strdup(name);
return object;
}
void delete_Person(Person* person) {
// some implementations pass a Person** to set the reference to 0
// this implementation requires that the caller sets his own references to 0
free(person->name);
free(person);
}
void Person_setName(Person* person, char* name) {
// free the old
free(person->name);
// duplicate the new to provide "out of simulated class" modification by malicious
// name setter.
person->name = strdup(name);
}
char* Person_getName(Person* person) {
// must return a copy, otherwise one can manipulate name
// from reference provided by Person_getName(...);
return strdup(person->name);
}
/* otherfile.c */
#include "Person.h"
/* Now we can hold Person "simulated objects", but we cannot */
/* manipulate their "state" without using the C simulated object */
/* methods */
int main(int argc, char** argv) {
Person* bob = new_Person("bob");
printf("%s\n", Person_getName(bob));
delete_Person(bob);
// critical or we hold a pointer to freed memory.
bob = 0;
return 0;
}
像这样的技术有几种变体,一种是有一个“公共结构”和一个指向“私有结构”的 void* 指针。一种是将“方法”作为函数指针包含在“公共结构”中(支持多态性的一步),一种是实际编写一个完整且适当的 C++ 类型系统,该系统试图完全按照 C++ 的方式解决问题(类层次结构,多态性、后期绑定、信息隐藏等)。
基本上,您无需太多工作就可以获得一些“面向对象”,但是随着您添加更多的 -ornamentation 功能,您将添加更多胶水代码(直到实际使用面向对象的编程语言变得更加简单) .