Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用命名空间生成全局函数,但获取多个定义的符号时出错_C++_Linker Errors_Precompiled Headers - Fatal编程技术网

C++ 使用命名空间生成全局函数,但获取多个定义的符号时出错

C++ 使用命名空间生成全局函数,但获取多个定义的符号时出错,c++,linker-errors,precompiled-headers,C++,Linker Errors,Precompiled Headers,这些函数是我的大多数程序对象都会使用的实用类型的东西。我希望将它们放在名称空间中,并使它们成为全局的。此命名空间在头中定义,然后添加到我的预编译头中。但是到目前为止,我已经在两个不同的对象中使用了这个名称空间中的函数,并且编译器在这两个对象上抛出了multiply-defined-symbols错误 名称空间文件 #ifndef UTILS_H #define UTILS_H #include <random> #include <cmath> namespace

这些函数是我的大多数程序对象都会使用的实用类型的东西。我希望将它们放在名称空间中,并使它们成为全局的。此命名空间在头中定义,然后添加到我的预编译头中。但是到目前为止,我已经在两个不同的对象中使用了这个名称空间中的函数,并且编译器在这两个对象上抛出了multiply-defined-symbols错误

名称空间文件

#ifndef UTILS_H
#define UTILS_H

#include <random>
#include <cmath>


namespace Utils
{
    extern int GetRandomBetween(int low, int high)
    {
        if (low < 0 || low >= high)
            return 0;
        int seed = high - low;

        return (rand() % seed) + low;
    }
};

#endif
\ifndef UTILS\u H
#定义UTILS\u H
#包括
#包括
命名空间Utils
{
外部int GetRandomBetween(int低,int高)
{
如果(低<0 | |低>=高)
返回0;
int seed=高-低;
返回值(rand()%seed)+低;
}
};
#恩迪夫
和我的预编译头

// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#pragma once

#include "targetver.h"

//#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>

// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <random>


#define SAFE_DELETE( p )       { if( p ) { delete ( p );     ( p ) = NULL; } }
#define SAFE_DELETE_ARRAY( p ) { if( p ) { delete[] ( p );   ( p ) = NULL; } }
#define SAFE_RELEASE( p )      { if( p ) { ( p )->Release(); ( p ) = NULL; } }
// TODO: reference additional headers your program requires here

#include "Utils.h"
#include "Manager.h" // this object uses utils
#include "Bot.h"    // this object uses utils
#include "LinkedList.h"
#include "Village.h"  // this object will use utils in the future
//stdafx.h:标准系统包含文件的包含文件,
//或特定于项目的包含经常使用的文件,但
//变化不大
//
#布拉格语一次
#包括“targetver.h”
//#定义WIN32_LEAN_和_MEAN//从Windows标题中排除很少使用的内容
//Windows头文件:
#包括
//C运行时头文件
#包括
#包括
#包括
#包括
#包括
#定义SAFE_DELETE(p){if(p){DELETE(p);(p)=NULL;}}
#定义安全删除数组(p){if(p){DELETE[](p);(p)=NULL;}
#定义安全释放(p){if(p){(p)->RELEASE();(p)=NULL;}}
//TODO:在此处引用程序所需的其他标题
#包括“Utils.h”
#包括“Manager.h”//此对象使用UTIL
#包括“Bot.h”//此对象使用UTIL
#包括“LinkedList.h”
#包括“Village.h”//此对象将来将使用UTIL
链接器错误消息:

Manager.obj:错误LNK2005:“int u cdecl Utils::GetRandomBetween(int,int)”(?GetRandomBetween@Utils@@YAHHH@Z)已在Bot.obj中定义
stdafx.obj:错误LNK2005:“int\uu cdecl Utils::GetRandomBetween(int,int)”(?GetRandomBetween@Utils@@YAHHH@Z)已在Bot.obj中定义
c:\users\lee\documents\visualstudio 2010\Projects\AI\Debug\AI.exe:致命错误LNK1169:找到一个或多个多重定义符号


也许值得注意的是,在我的Manager类标题中,我转发了声明的Bot。与村级标题相同。

Manager.cpp
Bot.cpp
都包括
Util.h

因此,在编译它们时,两个对象文件都会导出符号“GetRandomBetween”。当链接器将这些对象文件合并到一个可执行文件中时,它会找到该函数的两个实例。链接器无法确定使用哪一个(并且它不理解它们是相同的)

如果要使对象文件不导出符号(以便不存在链接器冲突),请删除extern关键字。

函数定义(即:源代码)不应位于标题中。获取多个定义的原因是
extern
无法将函数定义(源代码)转换为函数声明(即:仅原型)。因此,您需要这样做:

Util.h:

namespace Utils
{
    int GetRandomBetween(int low, int high);
};
SomeSourceFile.cpp(可能是Util.cpp):


尽管您应该只在小功能中使用它。

没有它就无法工作。我首先写的时候没有使用extern关键字,这就是我得到错误并添加exern的时候。但我还是继续尝试了一次,没有使用extern,但仍然不能产生相同的错误。@J的分析是正确的,但他的建议是错误的。您有两种选择:要么仅在标题中声明函数,并将定义移动到CPP文件,要么将
extern
替换为
inline
。好的,有三种选择——您可以用
静态
替换
外部
,但不能<代码>内联
将比
静态
更少浪费。完美!谢谢你们,你们俩的代表。啊,你们救了我一天<代码>内联
工作起来很有魅力!但是@Rob,既然我们在做,为什么
内联
静态
浪费更少呢?为什么这些选项中的任何一个都是浪费的?@SexyBeast static和inline将创建fn的两个副本,但它们将仅对它们在(a.obj,b.obj)中定义的翻译单元进行访问-这就是此解决方案解决错误的原因。两者之间的区别在于内联将在调用它的地方嵌入代码,而静态将添加跳转汇编指令并生成堆栈帧。帧和跳转在运行时代价很高,但会创建一个更压缩的二进制文件。内联方法将增加二进制但优化的运行时成本。现代的编译器会忽略这两者,并用它认为最好的方法优化代码。
namespace Utils
{
    int GetRandomBetween(int low, int high);
    {
        if (low < 0 || low >= high)
            return 0;
        int seed = high - low;

        return (rand() % seed) + low;
    }
};
namespace Utils
{
    inline int GetRandomBetween(int low, int high)
    {
        if (low < 0 || low >= high)
            return 0;
        int seed = high - low;

        return (rand() % seed) + low;
    }
};