C++链接器抱怨char*有多个定义,但没有std::string

C++ Linker complains multiple definition of char* but not std::string

本文关键字:定义 string std 链接 char C++      更新时间:2023-10-16

在一个大项目中,我有一个.h文件,它在一个命名空间中定义了很多常量。引入const-char*常量会导致链接器出现错误,抱怨有多个定义。

例如h

#include <string>
namespace Dv
{
    const int MAX = 10;
    const std::string NAME = "bobo";
    const char* NAME2 = "fred";  // <-- ERROR: multiple definition of `Dv::NAME2'
}

exA.cpp

#include "ex.h"
void aFunction() { printf("this is aFunctionn"); }

exB.cpp

#include "ex.h"    
void aFunction(void);
int main(int argc, char **argv)
{
    aFunction();
    return 0;
}

编译和链接

g++ -c exA.cpp
g++ -c exB.cpp
g++ exA.o exB.o -o ex
exB.o:(.data+0x0): multiple definition of `Dv::NAME2'
exA.o:(.data+0x0): first defined here
collect2: ld returned 1 exit status

如果在.h文件中包含NAME2,则会发生链接器错误。为什么?

如果MAX也是POD(如char[]?),为什么链接器不抱怨多个int MAX定义?(或者多个std::string NAME定义?)

我不明白在这种情况下char[]有什么特别之处。

感谢

根据C++标准(3.5程序和链接)

3具有命名空间作用域(3.3.6)的名称具有内部链接,如果它是的名称

--显式声明为const或constexpr且既没有显式声明extern也没有先前声明的非易失性变量声明具有外部链接;或

4未命名的命名空间或直接或间接声明的命名空间在未命名的命名空间中具有内部链接所有其他名称空间具有外部链接具有命名空间作用域的名称未被赋予内部链接。以上链接与封闭命名空间(如果它是变量的名称);或

在这个名称空间定义中

namespace Dv
{
    const int MAX = 10;
    const std::string NAME = "bobo";
    const char* NAME2 = "fred";  // <-- ERROR: multiple definition of `Dv::NAME2'
}

(唯一的)变量NAME2不是常数,因此具有外部链接。

您可以将其设置为具有内部链接来定义它,例如使用关键字static。例如

namespace Dv
{
    const int MAX = 10;
    const std::string NAME = "bobo";
    static const char* NAME2 = "fred";
}

或者可以将其定义为恒定

namespace Dv
{
    const int MAX = 10;
    const std::string NAME = "bobo";
    const char * const NAME2 = "fred";
}