为什么要使用 extern 关键字在命名空间范围内声明变量?

Why should I use the extern keyword to declare variables in a namespace scope?

我是 C++ 的新手,目前正在学习 short-course。我在 Java.

有一些背景

我希望有一个名为 "Message" 的命名空间,它将用于存储 unchanging/constant 字符串,这些字符串将在我的程序中的各种不同 class 中使用。 (例如标题、关键字、名称等)。

如果所有这些字符串都在 class 中,它们将是常量和静态的,因此我觉得最好将它们放入命名空间而不是 class。我现在的 "Message.h" 看起来有点像这样:

#ifndef MESSAGE
#define MESSAGE

#include <string>

namespace Message {
    const std::string NAME = "Car";
    const std::string SEPARATE = " | ";
    const std::string COMMAND = "Please enter a 1, 2 or a 3: ";
};

#endif MESSAGE

直到老师建议我改成这样...

Message.h:

#ifndef MESSAGE
#define MESSAGE

#include <string>

namespace Message {
    extern const std::string NAME;
    extern const std::string SEPARATE;
    extern const std::string COMMAND;
};

#endif MESSAGE

Message.cpp:

#include "Message.h"

const std::string Message::NAME = "Car";
const std::string Message::SEPARATE = " | ";
const std::string Message::COMMAND = "Please enter a 1, 2 or a 3: ";

在 session 结束之前,我几乎没有时间从讲师那里得到澄清,而且在我有机会之前,它会相当 some-time。根据我的研究,它与 translation-units 有关,更具体地说,是尝试在不同的翻译单元中使用变量。

我理解这个的一般概念,但我不太明白在这种情况下使用 extern 的好处?

这里的 include 守卫是否足以使 Message:: 名称空间变量不会 declared/defined 不止一次?为什么在这种情况下推荐使用 extern 关键字,这纯粹是为了 compile-speed 的好处吗?

两者都可以正常工作(尽管 knee-jerk 对问题的评论)。区别有点微妙。

在第一个示例中,包含 header 的每个翻译单元(想想 .cpp 文件)都将获得这三个字符串中每一个的副本。这样做没关系,因为它们被标记为 const,所以它们不会从翻译单元中导出。如果它们不是 const,您将对同一个符号有多个定义。

在第二个例子中,三个字符串各有一份。这些副本位于 Message.cpp 中,并将链接到您的可执行文件中。任何包含 Message.h 的翻译单元都会知道这些名称,因为它们是在 header 中声明的,并且可以使用它们。

对于像常量 int 值这样的小事情,第一种方法是最常见的。对于更大的东西,例如字符串 objects(通常需要 non-trivial 初始化的东西),第二种方法是最常见的。