从模块的外部上下文中正确隐藏函数
Properly hiding functions from the external context of the module
我正在尝试以面向对象的方式在 C 中实现信息隐藏。由于 C 显然不提供访问修饰符,例如 public、private 和 protected,我想出的解决方案是在 * 中定义一个抽象数据类型(哪些属性在外部不可见) .c 文件,并在相应的头文件中放入一个仅引用此新数据类型的typedef。
头文件还包含我的 public 函数的原型,因此用作此数据类型的 public 接口。
还有另一个头文件,其中列出了我不希望在正常情况下可见的受保护函数。
*.c 文件随后包含每个函数的实现,包括两个头文件中均未列出的函数。这些是我的私人功能。
LinkedList.h
#ifndef LINKEDLIST_H_
#define LINKEDLIST_H_
typedef struct LinkedList LinkedList;
LinkedList* newLinkedList();
#endif
LinkedList_protected.h
#ifndef LINKEDLIST_PROTECTED_H_
#define LINKEDLIST_PROTECTED_H_
#include "Node.h"
#include "LinkedList.h"
Node* getFirstNode(LinkedList* self);
Node* getLastNode(LinkedList* self);
#endif
LinkedList.c
#include "LinkedList.h"
#include "LinkedList_protected.h"
#include "Node.h"
// PRIVATE
struct LinkedList {
Node* first;
Node* last;
unsigned int nodesNo;
};
void privateTest() {
printf("Test");
}
// PROTECTED
Node* getFirstNode(LinkedList* self) {
return self->first;
}
Node* getLastNode(LinkedList* self) {
return self->last;
}
// PUBLIC
LinkedList* newLinkedList() {
LinkedList* self = malloc(sizeof(LinkedList));
self->first = NULL;
self->last = NULL;
self->nodesNo = 0;
return self;
}
这似乎可行:尝试访问另一个模块中 LinkedList 的属性时出现错误 ("dereferencing pointer to incomplete type"),这正是我想要的。但是,引用私有甚至受保护的函数只会给我一个 "implicit declaration" 警告。这是为什么?我应该担心吗?另外,这个解决方案安全吗,是否可以改进?
C 是一门非常古老的语言。发明计算机时,速度很慢且内存很少,cpu 电源甚至磁盘 space。 CPU 时间也是要花钱的。必须包含 headers、解析它们并记住所有声明的函数,这会消耗实际成本。
因此,为了简化事情,编译器假设如果您调用一个函数,该函数将存在并采用您在调用时使用的参数类型,并且它将 return int。那是 "implicit declaration"。只需调用该函数即可隐式声明它。此功能至今存在。
所以编译器并不是以某种方式看到了那些 protected/private 函数,而是简单地盲目地假设它们存在,并且令人惊讶的是,当你稍后 link 将 object 文件放在一起时他们有。
查看您的编译器文档,了解如何将此警告变为错误。虽然完全合法,但它是一个非常危险的特性(隐式声明本质上会跳过任何类型检查,并且对于任何非 returning 的东西都会失败),现在你真的不应该使用这个特性。当有人试图使用它时编译失败似乎是你想要的。
我正在尝试以面向对象的方式在 C 中实现信息隐藏。由于 C 显然不提供访问修饰符,例如 public、private 和 protected,我想出的解决方案是在 * 中定义一个抽象数据类型(哪些属性在外部不可见) .c 文件,并在相应的头文件中放入一个仅引用此新数据类型的typedef。
头文件还包含我的 public 函数的原型,因此用作此数据类型的 public 接口。 还有另一个头文件,其中列出了我不希望在正常情况下可见的受保护函数。 *.c 文件随后包含每个函数的实现,包括两个头文件中均未列出的函数。这些是我的私人功能。
LinkedList.h
#ifndef LINKEDLIST_H_
#define LINKEDLIST_H_
typedef struct LinkedList LinkedList;
LinkedList* newLinkedList();
#endif
LinkedList_protected.h
#ifndef LINKEDLIST_PROTECTED_H_
#define LINKEDLIST_PROTECTED_H_
#include "Node.h"
#include "LinkedList.h"
Node* getFirstNode(LinkedList* self);
Node* getLastNode(LinkedList* self);
#endif
LinkedList.c
#include "LinkedList.h"
#include "LinkedList_protected.h"
#include "Node.h"
// PRIVATE
struct LinkedList {
Node* first;
Node* last;
unsigned int nodesNo;
};
void privateTest() {
printf("Test");
}
// PROTECTED
Node* getFirstNode(LinkedList* self) {
return self->first;
}
Node* getLastNode(LinkedList* self) {
return self->last;
}
// PUBLIC
LinkedList* newLinkedList() {
LinkedList* self = malloc(sizeof(LinkedList));
self->first = NULL;
self->last = NULL;
self->nodesNo = 0;
return self;
}
这似乎可行:尝试访问另一个模块中 LinkedList 的属性时出现错误 ("dereferencing pointer to incomplete type"),这正是我想要的。但是,引用私有甚至受保护的函数只会给我一个 "implicit declaration" 警告。这是为什么?我应该担心吗?另外,这个解决方案安全吗,是否可以改进?
C 是一门非常古老的语言。发明计算机时,速度很慢且内存很少,cpu 电源甚至磁盘 space。 CPU 时间也是要花钱的。必须包含 headers、解析它们并记住所有声明的函数,这会消耗实际成本。
因此,为了简化事情,编译器假设如果您调用一个函数,该函数将存在并采用您在调用时使用的参数类型,并且它将 return int。那是 "implicit declaration"。只需调用该函数即可隐式声明它。此功能至今存在。
所以编译器并不是以某种方式看到了那些 protected/private 函数,而是简单地盲目地假设它们存在,并且令人惊讶的是,当你稍后 link 将 object 文件放在一起时他们有。
查看您的编译器文档,了解如何将此警告变为错误。虽然完全合法,但它是一个非常危险的特性(隐式声明本质上会跳过任何类型检查,并且对于任何非 returning 的东西都会失败),现在你真的不应该使用这个特性。当有人试图使用它时编译失败似乎是你想要的。