0

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

所以,我试了一下。将 .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 文件不同,头文件(如果未添加到项目中)不会更新,除非您手动保存它们。保存后,成功了。对不起,大家。

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

4

1 回答 1

0

宏定义在翻译单元中是本地的:编译源文件时,预处理器扩展各种预处理器指令(#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()后者每个文件都有一个计数器,而前者有一个全局计数器。

于 2012-10-06T17:45:19.473 回答