C++ 我应该包括<;标准h>;在我的头文件中,只是为了声明一个接受文件*的函数?

C++ 我应该包括<;标准h>;在我的头文件中,只是为了声明一个接受文件*的函数?,c++,c,coding-style,header-files,declaration,C++,C,Coding Style,Header Files,Declaration,例如在foo.h中: typedef struct foo_t foo_t; /* Lots of function declarations dealing with foo_t... */ int foo_print(const foo_t *foo); /* Print foo to stdout. */ int foo_fprint(FILE *f, const foo_t *foo); /* Print foo to file f. */ 我不想在foo.h中乱扔太多foo.h用

例如在
foo.h
中:

typedef struct foo_t foo_t;

/* Lots of function declarations dealing with foo_t... */

int foo_print(const foo_t *foo); /* Print foo to stdout. */
int foo_fprint(FILE *f, const foo_t *foo); /* Print foo to file f. */
我不想在
foo.h
中乱扔太多
foo.h
用户可能不想包含的其他头文件,但我确实需要声明采用
FILE*
等类型的函数。我怀疑我是第一个遇到这种困境的人,那么在这种情况下人们通常会怎么做呢?或者我想避免在头文件中包含
stdio.h
,这是被误导了吗

编辑:

人们似乎不理解我的问题。为了澄清,以下是一些潜在的解决方案:

  • 只需包含
    stdio.h
    ,而不必担心它会在我客户的代码中引起冲突(例如,如果他们碰巧有自己的函数,而该函数恰好被调用
    getchar
  • 使用
    #ifdef
    查找是否已包含
    stdio.h
    ,然后才声明与
    文件*
    相关的函数。这样做的缺点是,它会强制执行特定的排序,以便在我客户的代码中包含
  • 将所有与I/O相关的声明移动到单独的头文件中,例如
    foo_io.h

  • 什么问题是最好的做法?

    简短回答:您正在尝试解决一个不存在的问题

    如果使用<代码>文件< /> >,则在C++中包含<代码> STDIO .H< /COD>或<代码> CSTDIO < /COD>。就这么简单


    尝试“优化”
    #包括
    s,除了明显的未使用的情况外,不会给您带来任何好处并导致问题。

    您应该努力让头文件在空源模块中干净地编译。例如:

    #包括“myheader.h”

    就这样。如果将其放入C++源文件中,并且不使用其他代码编译,则不应该有编译器错误。 如果您确实遇到了错误,那么您需要证明存在错误的原因。我认为出现错误的唯一合理原因是,标题在库中是内部的,不应该由库的用户单独使用


    如果您的客户机应该使用头文件,请不要通过获取上面的测试源文件并向源文件添加头文件来“修复”问题。您可以通过在(在我的简单示例中)
    myheader.h

    中包含适当的标题来修复它,请参考更新后的问题:

    根据所包含文件的顺序有条件地启用或禁用代码块(或功能)简直是臭不可闻。这是通往地狱的直路

    如果要启用或禁用功能,使代码更加模块化,可以使用预处理器宏,可能需要用户显式选择编译模式

    #ifdef USE_STDIO
    #include <stdio.h>
    #endif
    
    lotsa lotsa code
    
    #ifdef USE_STDIO
    int foo_print(const foo_t *foo);
    int foo_fprint(FILE *f, const foo_t *foo);
    #endif
    
    #如果定义使用#
    #包括
    #恩迪夫
    lotsa lotsa代码
    #ifdef使用_STDIO
    int foo_print(const foo_t*foo);
    int foo_fprint(文件*f,常量foo_t*foo);
    #恩迪夫
    
    这种解决方案的缺点是:代码变得更难理解


    第二种选择是将这些方法提取到
    foo_io.h
    (可能还有
    foo_io.c
    )。此解决方案的缺点是您强制用户包含两个文件而不是一个。

    您已经回答了自己的问题。1)和3)都是有效的解决方案。如果在一个函数中使用
    FILE*
    ,则只有将函数与声明
    FILE
    的头结合使用才有意义。正如其他人所指出的,没有任何头可以向前声明
    文件
    ,因此您唯一的选择是包含
    stdio.h


    如果您的客户机包含头文件,则假定将使用所有函数。不要使用条件编译来删除include。如果我包括你的头文件,并且看到它包含一个使用
    file*
    的函数声明,我希望也包括
    stdio.h

    如果你使用的是标准库功能,只需要包括标准头的句号。不要试图过多地考虑某人可能拥有与标准库中的某个函数同名的函数:他们的代码已经很脆弱/代理,您不应该担心这种情况


    我无法确定你的代码是C++还是C(注意,即使C++可能有C语言的根,它们也是不同的语言)。如果是C++,你可以使用<代码> CSTDIO < /C> >代替<代码> STDIO .H/CODE >,并使用来自<代码> STD< /Calp>命名空间的特征,而不是全局命名空间。否则,如果您的代码是C,您必须使用
    stdio.h

    我不想在foo.h中添加太多其他头文件,而foo.h的用户可能不想包含这些头文件
    ,因此您想让您的客户承担
    #包含
    ,否则您的代码无法编译?您的代码应该在没有“用户干预”的情况下编译。问题是,没有允许您正确转发声明
    文件
    (因此可以使用
    文件*
    ,而不包括
    stdio.h
    ),就像其他I/O(
    iosfwd
    )一样。所以您必须使用include.Wrt。编辑后的问题:正确答案是1,或3。如果您担心引入大量额外的标题和名称。对于您的客户来说,无条件的
    #include
    永远不会是问题。这是C:没有名称空间。如果你选择了一个标准库中已经存在的名称,那是你的错。@Matt:对——如果它是
    静态的
    ,那么你的头的
    #include
    就不会影响它。@Matt:很抱歉,我之前的评论不完全正确。如果标准声明
    getchar()
    和静态声明
    getchar
    ,则可能是编译时错误。(没有链接时间冲突,因为
    static
    函数没有链接。)不过,我认为这不值得担心。如果您需要使用
    文件*
    ,请选择y