0

我有一个代码,其中我#include<linux/videodev2.h>. 共有三个文件:

  1. 一个头文件 - 包括:stdint.hstdlib.h. 定义了几个函数,一个结构,比如 abc,和一些 #define 宏。功能之一是

    int func(int, uint32_t, size_t, abc*);
    
  2. 一个包含很多方法的 cpp 文件,包括 .h 文件中的函数定义。

  3. 一个 main.cpp,它具有 main(),它对 .h 文件中的方法有一个函数调用(下面的完整文件)。此文件仅用于测试目的。

    #include "head.h"
    int main() {
        func(5, (uint32_t)5, (size_t)5, 0);
        return 0;
    }
    

看到的是一个奇怪的案例:

  1. 如果我linux/videodev2.h仅包含在 .h 文件中,uint32_t并且 .cpp 文件无法访问此标头中定义的其他内容。(我得到的错误是:uint32_t was not declared in this scope,和uint32_t does not name a type,等等)。即使 .h 文件的第一行是#include<linux/videodev2.h>
  2. 如果我在两个 cpp 文件中都包含 videodev2 标头,则当我在 .h 文件之前导入它 (videodev2) 时它才有效。
  3. 如果我func(5, (uint32_t)5, (size_t)5, (abc*)0);在 main.cpp 文件中使用,我会得到 abc 未在此范围内声明的错误。

我正在使用以下命令进行编译:g++ main.cpp head.cpp

我无法弄清楚为什么会这样。我想在 .h 文件中包含 videodev2 标头,因为几乎可以肯定使用 .h 文件的代码将依赖于它。但似乎将其包含在 .h 文件中根本没有效果。

我必须在这里说实话。这是我必须转换为 C++ 的 C 代码。我知道我不符合最佳实践和标准。但为什么会出现这种行为?

4

2 回答 2

3

请记住,该#include指令向预处理器指示指定文件的内容应被视为直接出现在源文件中代替指令(从MSDN转述)。

考虑到这一点,您似乎遇到了不正确的#includes 顺序并且还缺少#includes。我的猜测是您没有在 .cpp 文件中包含自己的头文件。这将解释案例一和案例三。考虑以下文件:

// header.h
// #include <linux/videodev2.h>  <-- Option 1
class A {
    void func(uint32_t var);
};

// header.cpp
void A::func(uint32_t var) {
    // implementation
}

// main.cpp
// #include <linux/videodev2.h>  <-- Option 2
#include "header.h"
// #include <linux/videodev2.h>  <-- Option 3

int main() {
    // implementation; something creates an instance of A and calls func
}

现在,选项 1并不完全可取;避免#include在头文件中使用 s 是一种很好的做法,因为它们会增加构建时间并创建不需要的依赖项。但是,它将确保header.h需要的类型可供它使用。关键是的内容linux/videodev2.h必须出现在 的内容之前header.h,在header.hd#include的任何地方。

这使我想到了选项 2。选项 2 也将正确编译,因为linux/videodev2.h它包含在您的标头之前,并且您的标头依赖于其中定义的类型。同样重要的是两者main.cppheader.cppmust #include "header.h",因为它们引用其中声明的符号。

如果您使用选项 3,您将收到类型uint32_t未定义的编译错误,并且编译器将指向您的头文件。这是因为头文件的内容出现在 的内容之前,所以编译器在遇到它时linux/videodev2.h还不明白是什么类型。uint32_t

因此,考虑到所有这些,您可以选择:在每次包含您自己的头文件之前包含 `linux/videodev2.h',或者直接将其包含在您的头文件中。我之前提到后者不是好的做法,但对于您的特定情况,它可能是两者中更好的选择,以防您的头文件需要包含在许多 .cpp 中。

我认为这将是深入研究预编译标头的好机会,但我对它们并不精通,所以我会把它留给有更多经验的人来解释它们。

希望这可以帮助 :)

于 2012-10-30T03:22:35.207 回答
0

找到了答案。目录中有.h.gch 文件。我不知道预编译的头文件。感谢 ktodisco 的洞察力。我仍然不知道为什么该文件首先存在。

于 2012-10-30T04:02:07.180 回答