【问题标题】:C++: File conflicting with itselfC++:文件与自身冲突
【发布时间】:2012-04-08 22:38:27
【问题描述】:

我已经创建了自定义随机数生成器,并将它们的全局函数放在一个名为 SamRandom.h 的文件中。该文件如下所示:

#ifndef _SAM_RANDOM_H
#define _SAM_RANDOM_H

#include <cstdlib>
#include <ctime>

void InitialiseRandomSeed()
{
    //...
}

//...

#endif

我在一个非常复杂的面向对象程序中工作,该程序有许多不同的组件。每次我添加一个无论如何都与该文件相关的文件时,我都会收到以下冲突消息:

LaserBase.obj:-1: error: LNK2005: "void __cdecl InitialiseRandomSeed(void)" (?InitialiseRandomSeed@@YAXXZ) already defined in main.obj
error: LNK1169: one or more multiply defined symbols found

在 MSVC 和 MinGW 上我得到:

In function `Z20InitialiseRandomSeedv':
SamRandom.h:8: multiple definition of `InitialiseRandomSeed()'
error: first defined here
:-1: error: collect2: ld returned 1 exit status

为什么会这样?我认为预处理器指令应该可以防止这个问题的发生......这真的让我发疯了!!!

P.S.:问题与函数名无关。

感谢您的努力

【问题讨论】:

  • 预处理器可以防止在同一个翻译单元中声明两次,但您在每个翻译单元中都有该函数一次。将函数定义移动到 cpp,并将函数声明留在标题中。
  • 请注意,下划线大写的名称是全局保留的。
  • 非常感谢。它奏效了。但我更喜欢使用头文件而不是 cpp 文件的灵活性。
  • 如果它们是全局保留的呢?这很糟糕吗?

标签: c++ file header include conflict


【解决方案1】:

当您将文件包含在 .cpp 文件中时,预处理器会直接将其复制到该文件中。因此,当您编译该 .cpp 文件时,目标文件(即使您不认识,编译器也会执行此步骤)将包含该函数。如果将它包含在多个 .cpp 文件中,则每个目标文件都将包含该函数。当链接器尝试将所有目标文件链接到可执行文件时,它会找到函数 x 次并给出该错误。 “找到一个或多个多重定义的符号”表示它多次找到您的函数(或变量)之一并且不知道如何处理它。

为了避免这种情况,您应该只输入您的功能签名,例如

//whatever.h
#ifndef _SAM_RANDOM_H
#define _SAM_RANDOM_H

void InitialiseRandomSeed();

#endif

在头文件中并将实现放入单独的 .cpp 文件中:

//whatever.cpp
#include "whatever.h"
#include <cstdlib>
#include <ctime>

void InitialiseRandomSeed()
{
    //...
}

【讨论】:

    【解决方案2】:

    标头保护确保函数不会在单个编译单元(.cpp 文件)中多次定义。但是,它们不会阻止函数在多个编译单元中被定义一次。这是因为 header 包含函数的定义,所以每个包含 header 的 .cpp 都有自己的函数定义。

    您可以将定义移至 SamRandom.cpp,然后在标头中声明函数,如下所示:

    void InitialiseRandomSeed();
    

    或者,您可以指定该函数是内联的,这样可以接受多个定义:

    inline void InitialiseRandomSeed()
    {
        //...
    }
    

    假设该函数不是性能关键的并且不会被频繁调用,我会采用前一种方法。这使标头更具可读性,并且(通常)减少了编译时间。

    【讨论】:

      【解决方案3】:

      您可以将定义分离到一个 .cpp 文件中,然后在头文件中声明函数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-24
        • 2016-01-12
        • 2012-12-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多