7

我正在使用 C 语言处理一个大型项目,我想使用接口 (.h) 和实现 (.c) 文件来组织它,类似于许多面向对象的语言,例如 Objective-C 或 Java。我熟悉在 C 中创建静态库,但我认为为我的项目这样做是不必要的复杂。如何在 ANSI C 中实现接口/实现范例?我主要使用 GCC 进行编译,但我的目标是严格遵守 ANSI C 和交叉编译器兼容性。谢谢!

4

3 回答 3

8

听起来您已经在做正确的事情:好的 C 代码还可以在 .h 文件中组织接口,在 .c 文件中组织实现。

示例 ah 文件:

void f(int a);

示例 ac 文件:

#include "a.h"
static void helper(void) {...}
void f(int a) {... use helper()...}

示例 main.c 文件:

#include "a.h"
int main(void) { f(123); return 0; }

你得到了模块化,因为辅助函数没有在头文件中声明,所以其他模块不知道它们(.c如果你愿意,你可以在文件顶部声明它们)。具有这种模块化减少了所需的重新编译次数并减少必须重新编译的数量。(尽管每次都必须进行链接)。请注意,如果您没有在标头中声明辅助函数,那么您已经非常安全了,但是static在它们前面放置也会在链接过程中将它们从其他模块中隐藏起来,因此如果多个模块使用相同的辅助函数就不会发生冲突-名字。

如果您只使用原始类型,那么这就是您需要知道的全部内容,您可以在此处停止阅读。但是,如果您的模块需要使用结构,那么它会变得更复杂一些。

有问题的示例标题 bh:

typedef struct Obj {
    int data;
}*Obj;
Obj make(void);
void work(Obj o);

您的模块想要传入和传出对象。这里的问题是,内部结构被泄露给依赖这个头文件的其他模块。如果表示更改为,float data则所有使用模块都必须重新编译。解决此问题的一种方法是仅使用void*. 这就是有多少程序可以做到的。但是这很麻烦,因为每个获取void*as 参数的函数都必须将其强制转换为Obj. 另一种方法是这样做:

标题通道:

typedef struct Obj*Obj;
Obj make(void);
void work(Obj);

实施抄送:

#include "c.h"
typedef struct Obj {
    int data;
}*Obj;

这样做的原因是, Obj 是一个指针(而不是按值/复制的结构)。依赖这个模块的其他模块只需要知道一个指针被传入和传出,而不是它指向什么。

于 2014-10-05T18:25:13.233 回答
0

您必须阅读有关非 OOL 的 OOP 的内容,例如http://www.cs.rit.edu/~ats/books/ooc.pdf。但是,这样做你永远不会有强大的 OOP 类型。

于 2014-10-05T17:50:59.250 回答
0

请帮自己一个忙,阅读C 接口和实现:创建可重用软件的技术

这是我的一个存储库,其中包含一些使用本书中描述的接口和实现模式用 C 编写的库。

于 2016-11-18T00:13:50.777 回答