我正在努力将一些源代码移植到linux系统,正如预期的那样,一些东西被打破了。有一件事现在给我一个错误,就是有人有.h和.cpp文件都使用fclose()
编译器抱怨fclose()在头文件中未声明。
这是头文件中的函数声明:
void closeFile() { if (fp) fclose(fp); }
现在,我认为这是一种糟糕的风格,但是 - 他们之前是如何做到这一点的呢?他们的编译器版本是否允许这种行为?
我应该通过在标题中包含stdio来修复此问题,还是将整个内容移动到cpp?
答案 0 :(得分:6)
风格不错,你可以将源代码放在头文件中,有时你会被迫使用,特别是:
定义模板类/函数时。
定义内联函数时。
无论如何,你不应该在头文件中放置一个自由的(在类范围外定义)非内联函数,因为只要源文件包含这样的头文件就会编译它(这会给你一个链接错误)
如果您收到的错误表明fclose
尚未声明,则可能是因为cstdio
(或stdio.h
)未在该段代码之前声明。将#include <cstdio>
放在头文件的开头。
答案 1 :(得分:3)
只是添加关于其他答案的两件事,记住内联不是一个顺序,更多的是猜测编译器应该做什么,除非你强制内联。大多数编译器可以决定何时内联函数,即使您没有将其声明为内联函数。它不是必须,它是应该。
有时你真的需要在标题中包含这样的函数/结构/类定义,有时它们不是微不足道的或那么简单。但是这些定义通常是您需要的一些辅助功能,您只是不想将它们包含在主文件中,只是为了更好地组织。
我见过的最好的例子(好的,我没有看到那些很多)关于这种做法是游戏源代码(这是我的主要兴趣:))。
顺便说一句,我通常不会对头文件(结构和枚举除外)进行任何声明,我将它们放在分隔的文件中,除非是:
希望它有所帮助。
答案 2 :(得分:2)
请记住,头文件不是自己编译的(通常)。它们是#include
到源文件中,解析头文件时可用的定义是在相关头文件上方的源文件中包含的内容。
无论头文件是否适合实施closeFile()
,您的头文件都应#include
在其顶部需要的所有内容。因此,请在标头文件的顶部添加#include <stdio.h>
。
(请注意,如果这是要编译到Linux内核本身的代码,则可能需要与stdio.h
不同的标头。通常,应用程序级标头不适合在内核源中使用。 )
答案 3 :(得分:2)
fclose()
,则 stdio.h
将被取消定义。这就是错误发生的原因。
我个人认为允许在头文件中使用的代码没有任何问题,但是,如果是,并且您使用的是C99,则应该声明它
inline void closeFile() { if (fp) fclose(fp); }
这意味着多个编译对象不会有closeFile()
个符号(因为inline
)和inline
提示编译器,这不应该保留为函数调用但是取代inline
,这可能是你想要的速度。
答案 4 :(得分:0)
标题包含在文本替换中(即标题的全部内容被替换为#include
声明)。因此,如果只有一个.cpp文件包含此特定标头,则这与在.cpp文件中定义的函数等效。我认为这就是它工作的原因(在链接时)。
C标准仅定义必须包含的标头以使功能可用,但不禁止系统标头彼此包含。所以有可能在某些系统上,stdio.h
标头被另一个标头隐含地包含在内(因此编译器没有报告错误)。
就个人而言,我会将此类代码移动到.cpp文件中,因为它不会那么脆弱(标头可以包含多个.cpp文件,标头不需要先前包含stdio.h
标头如果必须更改实现,则允许更快地重新编译(添加日志记录或正确的错误处理,因为关闭文件可能会失败)。