c - 从模块的外部上下文中正确隐藏函数

标签 c oop header-files information-hiding

我正在尝试以面向对象的方式在 C 中实现信息隐藏。由于 C 显然不提供访问修饰符,例如 public、private 和 protected,所以我能想到的解决方案是在 *.c 文件中定义一个抽象数据类型(其属性不应该在外部可见),并在相应的头文件中放入一个仅引用此新数据类型的typedef。

头文件还包含我的公共(public)函数的原型(prototype),因此可以用作此数据类型的公共(public)接口(interface)。 还有另一个头文件列出了我不希望在正常情况下可见的 protected 函数。 然后,*.c 文件包含每个函数的实现,包括一些头文件中都没有列出的函数。这些是我的私有(private)功能。

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 的属性会给我一个错误(“取消引用指向不完整类型的指针”),这正是我想要的。然而,引用私有(private)函数甚至 protected 函数只会给我一个“隐式声明”警告。这是为什么?我应该担心吗?另外,这个解决方案安全吗?可以改进吗?

最佳答案

C 是一门非常古老的语言。当计算机被发明时,速度很慢,内存、CPU 功率甚至磁盘空间都很少。 CPU 时间也花费了真金白银。必须包含 header 、解析它们并记住其中声明的所有函数,这会消耗实际成本。

因此,为了简化事情,编译器假设如果您调用一个函数,该函数将存在并采用您在调用时使用的参数类型,并且它将返回 int。这就是“隐含声明”。只需隐式调用该函数即可声明它。此功能至今仍然存在。

因此,编译器并不是以某种方式看到这些 protected /私有(private)函数,而是简单地盲目地假设它们存在,令人惊讶的是,当您稍后将目标文件链接在一起时,它们确实存在。

检查编译器文档,了解如何将此警告转换为错误。虽然完全合法,但这是一个非常危险的功能(隐式声明本质上会跳过任何类型检查,并且对于任何不返回的内容都会失败),现在您确实不应该使用此功能。当有人尝试使用它时编译失败似乎是您想要的。

关于c - 从模块的外部上下文中正确隐藏函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60092687/

相关文章:

c - 如何正确使用 SIGALRM?

c - 访问 char 和 int 参数

Scala 类的多重继承

c++ - 为什么一定要Forward声明一个类,在一个头文件中包含对应的头文件

c - 在头函数声明中传递常量

c++ - 如何在 Visual Studio 2017 中使用 VC++ 包含目录的子文件夹

c - 指针地址相乘

c++ - 类构造函数不保存变量

c++ - 派生类是否可以具有不在 C++ 中的基类中的构造函数?

转换指针并获得警告