【问题标题】:Why does the order of my #includes matter? (C++)为什么我的#includes 的顺序很重要? (C++)
【发布时间】:2009-05-14 21:10:17
【问题描述】:

我创建了一个名为“list_dec.h”的头文件,将它放在文件夹“C:\Headers”中,并将我的编译器设置为包含来自“C:\Headers”的文件,所以现在我可以做一些事情了喜欢

#include<list_dec.h>
int main(){return(0);}

但是当我尝试做类似的事情时

#include<iostream>
#include<list_dec.h>
int main(){return(0);}

我得到一个错误(不是任何具体的,只是“list_dec.h”中的一个巨大的语法错误列表,我知道这不是真的,因为我已经能够将它编译为 main.cpp 文件和.h 文件在一个单独的项目中)。但是,当我更改订单时,“list_dec.h”位于顶部:

#include<list_dec.h>
#include<iostream>
int main(){return(0);}

所有错误都消失了。那么为什么错误的顺序很重要呢?

注意:据我所知,当我将“list_dec.h”与所有头文件一起使用时会发生这种情况,但我绝对肯定它出现在的文件是:

#include<iostream>
#include<vector>
#include<time.h>
#include<stdlib.h>

编辑:当“list_dec.h”位于任何其他标题下方时,我会遇到以下错误:

c:\headers\list_dec.h(14) : error C2143: syntax error : missing ')' before 'constant'
        c:\headers\list_dec.h(51) : see reference to class template instantiation 'list<T,limit>' being compiled
c:\headers\list_dec.h(14) : error C2143: syntax error : missing ';' before 'constant'
c:\headers\list_dec.h(14) : error C2059: syntax error : ')'
c:\headers\list_dec.h(14) : error C2238: unexpected token(s) preceding ';'
c:\headers\list_dec.h(69) : warning C4346: 'list<T,limit>::{ctor}' : dependent name is not a type
        prefix with 'typename' to indicate a type
c:\headers\list_dec.h(69) : error C2143: syntax error : missing ')' before 'constant'
c:\headers\list_dec.h(69) : error C2143: syntax error : missing ';' before 'constant'
c:\headers\list_dec.h(69) : error C2988: unrecognizable template declaration/definition
c:\headers\list_dec.h(69) : error C2059: syntax error : 'constant'
c:\headers\list_dec.h(69) : error C2059: syntax error : ')'
c:\headers\list_dec.h(78) : error C2065: 'T' : undeclared identifier
c:\headers\list_dec.h(78) : error C2065: 'limit' : undeclared identifier
c:\headers\list_dec.h(78) : error C2065: 'T' : undeclared identifier
c:\headers\list_dec.h(78) : error C2065: 'limit' : undeclared identifier
c:\headers\list_dec.h(79) : error C2143: syntax error : missing ';' before '{'
c:\headers\list_dec.h(79) : error C2447: '{' : missing function header (old-style formal list?)

如果有帮助,这些是错误中提到的行(14、69、78 和 79):

第 14 行:list(const T&amp; NULL); (A constructor for "list" class)

第 69 行:inline list&lt;T, limit&gt;::list(const T&amp; NULL): (Definition for the constructor, also, the colon at the end is intentional, It part of the definion ie: void x(int n): VAR(n).)

第 78 行:inline list&lt;T, limit&gt;::list(const list&lt;T, limit&gt;&amp; lst) (def for the copy constructor)

第 79 行:{ (the begining of the list-copy contructor)

而且很多人都希望看到“list_dec.h”的开头:

template<class T, size_t limit>
class list

注意:这些不是第一行,但它们是我认为问题所在,它们之前的行只是一个名为“err”的枚举。

编辑:请注意,“list_dec.h”不包含包含、定义、ifdef 或任何以“#”开头的内容。除枚举外,仅包含“list”类声明和“list”类成员函数定义。

【问题讨论】:

  • 你能贴出list_dec.h的开头吗?
  • 您能否至少发布您遇到的前几个错误,这可能会有所启发。
  • 类名是“list”,枚举名是“err”,其他都是list的数据成员或成员函数,我尝试的几乎所有其他头文件都会出现错误.另外,正如我所说,它仅在我将 #include 放在另一个 #include 之后发生,而不是在我之前放置它时发生。
  • 让我们扭转局面:为什么不呢?

标签: c++ header include


【解决方案1】:

一般来说不应该,但是可能存在冲突的符号定义或预处理器宏,最终使编译器感到困惑。尝试通过从冲突的标题中删除部分和包含来缩小问题的规模,直到您可以看到导致它的原因。

为了响应您发布的错误消息,符号NULL 通常实现为数字 0 的预处理器宏。这样您就可以轻松地将其用作空指针。因此:

list(const T& NULL);

可以被预处理器转换成这个语法错误:

list(const T& 0);

将参数名称更改为 NULL 以外的名称。

【讨论】:

    【解决方案2】:

    注意这里:

    Line 14: list(const T&amp; NULL); (A constructor for "list" class)

    NULL 是标准宏的名称 - 当在 list_dec.h 之前包含标准头文件时,很可能会导致定义 NULL,这反过来会导致您的代码在编译器中看起来像这样:

    list(const T&amp; 0);

    上面的常量 0 使 C++ 行格式错误。您可以通过指示编译器生成预处理输出文件来获得更多信息。

    【讨论】:

    • 我之前尝试过使用 NULL 来达到这个目的,但是编译器告诉我 NULL 是未定义的,所以我在这里使用它。另外,当我编译“list_dec.h”本身时,这不会出现在编译器错误中吗?因为“list_dec.h”本身没有错误,所以只有当我把它放在另一个#include下面时才会出现错误。
    • 如果您不包含标准标题,NULL 是未定义的。如果包含标准标头,则 NULL 将被定义为 0。这就是最好将 0 用于空指针常量的原因(null_ptr 将是即将到来的标准 IIRC 中的保留字)
    • NULL 不是由编译器定义的,而是由 标准头定义的。不要使用标准宏的名称作为您自己的标识符。
    【解决方案3】:

    大概 list_dec.h 正在运行一个宏,该宏定义在其他头文件(或它们依次包含的某些头文件)中——如果没有看到第一条错误消息和 list_dec.h 的相关部分,很难说出哪个宏!

    【讨论】:

      【解决方案4】:

      实际的错误会提供更具体的线索,这意味着您的包含文件中有一些东西正在搞砸下一个的扫描。最常见的是某种 unclude #-directive,例如 #if 缺少其 #endif

      【讨论】:

        【解决方案5】:

        如果错误本质上是随机的,则可能是缺少分号。编译器通常会停止,但有时你会“幸运”。

        否则,名称或定义冲突。例如,您有任何名为 std 的东西吗?

        【讨论】:

          猜你喜欢
          • 2013-05-18
          • 1970-01-01
          • 2018-02-01
          • 2017-06-27
          • 1970-01-01
          • 1970-01-01
          • 2021-03-26
          • 2013-11-18
          • 1970-01-01
          相关资源
          最近更新 更多