【问题标题】:Multiple definition of function error/header files/inlining [closed]函数错误/头文件/内联的多重定义[关闭]
【发布时间】:2012-10-06 17:34:53
【问题描述】:

对不起,如果这是重复的,但我找到的那些......好吧,我以为我尝试了相同的解决方案,但无济于事。无论如何,我最近尝试将我常用的随机函数的实现移动到一个头文件中:我知道这些函数是如何工作的,我怀疑我会很快改变它们,所以我想,文件越少越好(以及功能很短)。

所以,我试了一下。将 .cpp 文件的内容粘贴到一个新文件中,并添加保护。然后只需包含它,瞧,它就可以了。不幸的是,我将它包含了两次,然后发现,我将相同函数的副本分发到每个文件,因此出现了错误。 (仍然会有点困惑,为什么这是标题保护,因为无论如何你最终都会得到一份副本,但我想确实如此)。无论如何,我用谷歌搜索(和 SO'ed),发现如果你将它们声明为内联 - 这在这种情况下是有道理的 - 那么预处理器(或者这也是链接器?)会做对。现在我想到了......作为一个小问题,DEFINES 是文件本地的,还是全局范围的? (即,如果我在两个文件中包含一个标题,并且标题保护定义......两个文件是否都包含它,因为定义发生在不同的文件中,还是只包含一次?如果它确实被包含两次,你会得到多个声明(但未定义)相同的函数/类/结构,我认为它会引发错误,但我猜它不会在不同的文件中?否则,它可能不会被包含在内,并且它不知道它是什么。所以,到再问,DEFINES 是文件本地的吗?)

这是我在文件中的函数被重复的内容(认为只包含一个函数)

#ifndef RANDOM_H
#define RANDOM_H

//needed for getting system time and for random generation functions rand and srand
#include <time.h>
#include <stdlib.h>

//this function returns a random number between an inclusive range
inline int randomRange(const int & min, const int & max)
{
    if (max >= min)
        return ((rand() % (max+1-min))+min);
    else
        return ((rand() %  (min+1-max))+max);
}

#endif

然后我只在这个文件(即“random.h”)上的两个文件中有#includes

我错过了什么?

编辑:错误消息是:

`randomRange(int const&, int const&)'的多重定义|

在稍作休息的同时,我关闭了 IDE。重新打开后,一切都已修复。显然,添加内联 DID 可以修复它,但是,与运行时的 cpp 文件不同,头文件(如果未添加到项目中)不会更新,除非您手动保存它们。保存后,成功了。对不起,各位。

每日一课:修复此类错误时,请确保您的文件已更新...

【问题讨论】:

  • 如果您不打算自己更改整数,最好按值而不是引用传递整数。
  • 嗯,是的,该函数最终可能会出现在#include此标头的所有源文件中。但它被标记为inline,所以没关系。您收到错误消息吗?

标签: c++ header inline multiple-definition-error


【解决方案1】:

宏定义在翻译单元中是本地的:编译源文件时,预处理器扩展各种预处理器指令(#define#include 等)并将结果传递给实际编译器。这对每个文件执行一次,而不仅仅是一次。使用包含守卫的原因是同一个标题很可能会在同一个翻译单元中包含两次。例如,如果你有一个类型,比如 Point,它被 RectangleTriangle 类使用,并且你同时包含了 RectangleTriangle 的标题,你最终会得到一个翻译单元,包括Point 的标头两次。

当你在头文件中定义一个函数时,你需要向编译器表明它不应该使它成为一个全局可见的定义。正常的方法是为此使用inline,这也向编译器表明它应该尽量不调用该函数,如果这是有意义的。使用inline 的替代方法是创建函数static,但在这种情况下,您实际上最终会在最终可执行文件中得到该函数的多个副本:即使编译器可能使用inline 版本每个翻译单元中的功能,在链接时从任何地方选择和使用一个(希望所有其他副本都被丢弃)。可以看到差异,例如,当您的函数中有一个本地 static 变量时:

inline int f() {
    static int rc(0);
    return ++rc;
}
static int g() {
    static int rc(0);
    return ++rc;
}

当您从不同的翻译单元调用这些函数 f()g() 时,后者每个文件都有一个计数器,而前者有一个全局计数器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多