[英]Separating the Interface and Implementation in C
在将接口与C中的实现分开时,哪里是包含头文件的正确位置?
在接口文件(.h文件)或实现文件(.c文件)中? 为什么?
我的示例代码:
console.h
#ifndef CONSOLE_H
#define CONSOLE_H
#include <windows.h>
void gotoxy (const WORD x, const WORD y);
void clearScreen();
#endif
console.c中
#include <stdlib.h>
#include "console.h"
COORD coord = {0,0};
void gotoxy (const WORD x, const WORD y){
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void clearScreen(){
system("cls");
}
以下是一些原则:
不必要的包含标头只会增加编译时间。
这可能听起来很容易被忽视,而且一般来说,但如果你养成了包含太多的习惯,它就会成为一个问题。
想象一下,您的项目有一个通用标题,包括所有其他项目标题以及它们可能需要的所有系统标题。 所以任何.c文件只需要包含这一个标题并完成它。 这很方便。 但是,除了延长每个.c文件的编译时,它还保证每次更改单个标头时都必须重新编译整个项目 。 这将显着减慢您的修改 - 编译 - 测试周期。
您必须避免创建循环包含依赖项。
如果你确实创建了一个循环包含,那你就麻烦了。 因此,最好避免包含任何不必要的内容:包含的内容越少,触发循环包含的标头越少。 有时您可能需要插入前向声明而不是包含。
.c文件必须包含其.h文件。
如果你没有这样做,.c文件中的函数签名将不会根据.h文件中的声明进行检查,并且会出现疯狂。
这个原则的问题是,如果.h文件没有定义实现所需的类型,那么你的.c文件可以在没有include的情况下正常编译。 然而,包含必须在那里以防止签名不匹配。
因此,除了第3点之外,谨慎的做法是仅包含绝对需要的标头,并且仅包含实际需要它的文件。 就个人而言, 在我收到编译器错误告诉我缺少某些内容后 ,我经常只包含一个标题。
Include指令应始终包含在需要它们的文件中,或者使您更容易阅读和理解代码。
在您的示例中,您在console.h中包含了windows.h. 对于这样一个常见的头文件,可以将它留在console.h中。 但是,如果您正在使用另一个您编写的库,并且尚未被广泛采用,那么将它包含在两个文件中是明智的,以防止将来的开发人员不得不搜索头文件来搜索提供功能的文件。在console.c中。
我的设置只有两个变化。 我会在头文件中包含所有头文件,除了包含头文件所必需的console.h
头文件。 第二,当你#define CONSOLE_H 1
,给它一个值1
就可以了。 我只是阻止了一个未初始化的标签。 看起来不错。
console.h
#ifndef CONSOLE_H
#define CONSOLE_H 1
#include <windows.h>
#include <stdlib.h>
void gotoxy (const WORD x, const WORD y);
void clearScreen();
#endif
console.c中
#include "console.h"
COORD coord = {0,0};
void gotoxy (const WORD x, const WORD y){
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void clearScreen(){
system("cls");
}
就像在评论和其他答案中已经提到的那样 - 包括应该在需要它们的文件中。
但是,对于复杂/大型项目,我建议设计接口,使它们只需要处理程序/引用实际数据而不是实际数据。 这允许在头文件中使用前向声明,在实现文件中使用实际包含。 其原因是避免紧耦合 。 紧耦合通常会导致非常有问题的行为,强制包含不直接需要的标头(甚至创建循环依赖,导致编译失败并需要进行大量更改!),增加编译时间并损害此类软件属性作为模块化,可维护性和可扩展性。
也就是说,在大多数情况下(例如stdio.h,windows.h等)都需要常见的标题(通常是你正在使用的环境的一部分) - 包括这些标题虽然汇编,但不会损害软件质量时间可能还会增加。 解决此问题的一种方法是使用预编译头 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.