代码之家  ›  专栏  ›  技术社区  ›  Steve

收割台护罩和LNK4006

  •  10
  • Steve  · 技术社区  · 15 年前

    //header.h
    const char* temp[] = {"JeffSter"};
    

    标题if#定义为受保护,顶部有一个#pragma。如果这个头包含在多个地方,我会得到一个已经在blahblah.obj中定义的LNK4006-char const**temp。我有几个问题要问

    1. 为什么此标头中的大量枚举不同时给出LNK4006警告?
    2. 是否有更好的方法来避免错误,但让我在头中声明数组。我真的很不愿意只为数组定义使用cpp文件。
    5 回复  |  直到 15 年前
        1
  •  14
  •   Alok Singhal    15 年前

    包含防护装置确保标题仅包含一次 一个文件 (翻译股)。对于包含标头的多个文件,您希望在每个文件中包含标头。

    通过 决定性的 ,而不是 宣布 具有外部链接的变量(全局变量)在头文件中,只能在源文件中包含头。如果将头包含在多个源文件中,将有多个变量定义,这在C++中是不允许的。

    因此,正如您所发现的,正是由于上述原因,在头文件中定义变量是一个坏主意。

    为什么此标头中的大量枚举不同时给出LNK4006警告?

    因为,它们不定义“全局变量”,它们只是关于类型等的声明。它们不保留任何存储。

    如果在签名之前添加static,则不会得到警告。这样做意味着什么。

    static ,它有 静态范围 . 对象在定义它的转换单元(文件)之外不可见。因此,简单地说,如果您有:

    static int i;
    

    在头文件中,包含头文件的每个源文件都将获得一个 分离 int i 内部连接 .

    是否有更好的方法来避免错误,但让我在头中声明数组。我真的很不愿意只为数组定义使用cpp文件。

    如果希望数组是从所有C++文件中可见的对象,则应:

    extern int array[SIZE];
    

    array .cpp )文件,您需要定义 :

    int array[SIZE];
    

    您还应该在上面的源文件中包含头文件,以便捕获由于头文件和源文件不同而导致的错误。

    extern 告诉编译器“ 是在某处定义的,并且具有 int ,以及尺寸 SIZE 定义 排列

        2
  •  5
  •   AnT stands with Russia    11 年前
    1. 整个程序 . 头保护的目的是防止将同一头文件多次包含到 同一翻译单位 (.cpp文件)。换句话说,它们的存在是为了防止出现多个定义 相同的源文件 . 在你的情况下,它们确实起到了预期的作用。

    2. 在C++中管理多个定义问题的规则称为一个定义规则(ODR)。ODR对于不同类型的实体有不同的定义。例如 类型 允许在程序中有多个相同的定义。他们可以(而且总是如此) 在使用它们的每个翻译单元中定义。这就是为什么枚举定义不会导致错误。

      这是一个完全不同的故事。它们必须在一个且仅在一个翻译单元中定义。这就是为什么你对 temp

    3. 加入 static 你给你的目标 内部连接 . 这将使错误消失,因为现在从ODR的角度来看它是完全正常的。但这将定义一个独立的 临时雇员 对象,该对象位于包含头文件的每个翻译单元中。为了达到同样的效果,你也可以这样做

      const char* const temp[] = { "JeffSter" }; 
      

      const

    4. 这取决于您是否需要具有外部链接的对象(即,整个程序需要一个链接)或具有内部链接的对象(每个翻译单元唯一)。如果您需要后者,请使用 和/或额外费用 常数 (如果对您有效)如上所示。

      如果需要前者(外部链接),则应将非定义声明放入头文件中

      extern const char* temp[];
      

      并将定义移到一个且仅一个.cpp文件中

      char* const temp[] = { "JeffSter" }; 
      

      临时雇员

      extern const char* temp[1];
      

      并记住在声明和定义之间保持同步。

        3
  •  4
  •   Georg Fritzsche    15 年前

    Include guards可防止重复将相同的头文件包含到相同的文件中,但不会将其包含在不同的文件中。
    temp 在多个对象文件中-您可以通过 临时雇员

    static const char* temp1[] = {"JeffSter"};
    // or
    namespace {
        const char* temp2[] = {"JeffSter"};
    }
    

    或者,您可以使用一个源文件来定义 临时雇员 只需在标题中将其声明为extern:

    // temp.cpp:
    const char* temp[] = {"JeffSter"};
    
    // header.h:
    extern const char* temp[];
    
        4
  •  0
  •   David A. Gray    8 年前

    我尊重地不同意反对在标题中定义变量的建议,因为我认为“从不”太宽泛了。然而,这一事件让我想到了这一点,为那些敢于这样做的人提供了一个警示故事。

    在对LNK4006警告的原因进行调查后,我登上了这一页,调用了一个长期建立的数组,我刚刚将该数组从定义DLLMain例程的翻译单元移动到包含在构成该库的大多数翻译单元中的私有标头中。在过去的11年里,我已经编译了数百次这个库,我以前从未见过这个警告。

    在阅读本页后不久,我发现了错误的原因,这是因为该定义位于保护块之外,保护模块中定义的所有其他内容,该模块也定义了DLLMain,我通常在该模块中收集所有需要外部链接的内存块。正如预期的那样,将表移动到防护块内消除了警告,只剩下两个与全新外部链接表相关的警告有待解决。

        5
  •  -2
  •   t0mm13b    3 年前

    坚持您正在混淆您的声明…您确实说了'char const**temp',但在头文件中有'const char*temp[]={“JeffSter”};'。

    见本手册第6.1节 C FAQ

    6.1:    I had the definition char a[6] in one source file, and in
        another I declared extern char *a.  Why didn't it work?
    
    A:  In one source file you defined an array of characters and in the
        other you declared a pointer to characters.  The declaration
        extern char *a simply does not match the actual definition.
        The type pointer-to-type-T is not the same as array-of-type-T.
        Use extern char a[].
    
        References: ISO Sec. 6.5.4.2; CT&P Sec. 3.3 pp. 33-4, Sec. 4.5
        pp. 64-5.
    

    这就是问题的根源。匹配您的声明和定义。抱歉,如果这听起来很直白,但我忍不住注意到链接器告诉你的。。。

    推荐文章