如何在C++中定义字符串常量?

21

可能是重复问题:
C++中静态常量字符串(类成员)
链接时给出重复符号错误的已初始化static const的C++类成员

由于我使用的 C++ 版本不支持 string 类,所以我要重新开始学习一些东西。

我正在为我的类定义头文件,并想为一个 URL 创建一个静态常量。我试图通过以下方式实现:

#include <string>
class MainController{
private:
    static const std::string SOME_URL;
}

const std::string MainController::SOME_URL = "www.google.com";

但这会在链接期间导致重复定义。

我该如何实现这一点?


dup http://stackoverflow.com/questions/2888805/static-const-c-class-member-initialized-gives-a-duplicate-symbol-error-when-linking - David Nehme
4个回答

17

移动

const std::string MainController::SOME_URL = "www.google.com";

将其放到cpp文件中。如果你将其放在头文件中,那么每个包含它的.cpp文件都将有一份副本,并且在链接期间会出现重复的符号错误。


2
我想我不太明白的是,我在我的头文件保护内部有这些内容。这解决了问题,但我不明白为什么... - Thom
4
@Thom,头文件保护并不能解决问题,因为每个翻译单元(cpp文件)都包含该头文件,因此每个翻译单元最终都会有一个同名的字符串“副本”,这导致每个翻译单元都能正确编译。然而,当链接多个翻译单元时,它们具有相同的符号(即该字符串),会导致符号链接错误。 - Javier Mr

12
你需要放置这行代码


const std::string MainController::SOME_URL = "www.google.com";

在cpp文件中定义静态成员,而不是头文件中,因为一个定义规则。你不能直接在类中初始化它的事实是因为std::string不是像int一样的整型类型。
或者,根据您的用例,您可以考虑不制作静态成员,而是使用匿名命名空间。请参见此帖子以获取正/反方面的意见

1
@Nawaz 在实践中,多个翻译单元中的多个定义是未定义行为,因此编译器可以使其工作。 (或者做任何其他事情,但“使其工作”是C中常见的实现方式。其中构造函数没有进入其中。) - James Kanze
1
@JamesKanze:你想说什么?这与静态成员的类型有关吗? - Nawaz
1
@Nawaz:我知道这不是OP正在做的事情。OP提到他对C++有点生疏,我只是添加了一些信息,告诉他如何初始化字符串(将其放在cpp中),如果它是int类型,则可以直接在类体中初始化,并且匿名命名空间在某些情况下可能会很有用。 - JRL
1
@Nawaz 这与类型无关。在单独的编译单元中有多个定义是未定义行为,编译器可以让它工作。传统上,C 编译器(出于历史原因)确实这么做了;而 C++ 编译器则没有这么做。可能是因为旧链接器很难在存在动态初始化时使其工作。实际上,在使用 C++ 编译器时,你会得到一个错误。 - James Kanze
2
@Nawaz 我并不是在说你错了;就今天的C++而言,你是正确的。我只是加入了一些额外的信息:历史和标准语言,但并没有改变你所写内容的影响。 - James Kanze
显示剩余8条评论

4

在头文件中定义类:

//file.h
class MainController{
private:
    static const std::string SOME_URL;
}

然后,在源文件中:

//file.cpp
 #include "file.h"

const std::string MainController::SOME_URL = "www.google.com";

2

你应该将 const std::string MainController::SOME_URL = "www.google.com"; 的定义放在单个源文件中,而不是头文件中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接