【发布时间】:2019-05-28 12:51:03
【问题描述】:
我对 C++ 还是很陌生,目前正在学习它的短期课程。我有一些Java背景。
我希望有一个名为“Message”的命名空间,它将用于存储不变/恒定的字符串,这些字符串将在我的程序中的各种不同类中使用。 (例如标题、关键字、名称等)。
如果所有这些字符串都在一个类中,它们将是 const 和静态的,因此我觉得最好将它们放入命名空间而不是类。我当前的“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
直到教练建议我把它改成这样……
消息.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: ";
在课程结束之前,我几乎没有时间从导师那里得到澄清,而且我还需要一段时间才能有机会澄清。根据我的研究,它与翻译单元有关,更具体地说,是尝试在不同的翻译单元中使用变量。
我了解这个的一般概念,但我不太明白在这种情况下使用 extern 的好处?
这里的包含守卫是否足以让 Message:: 命名空间变量不会被多次声明/定义?为什么在这种情况下推荐使用 extern 关键字,这纯粹是为了提高编译速度?
【问题讨论】:
-
“好处”是当使用多个翻译单元时,最终结果是有效的 C++,而不是链接失败、未定义的行为和/或违反 One Definition Rule。
extern关键字不是“推荐的”。这是必需的。 -
老实说,您可以自己轻松尝试。当您将
Message.h包含在多个文件中、构建并将它们链接在一起时会发生什么? -
我建议您详细了解声明和定义之间的区别。您可以拥有任意数量的符号声明(当然,如果它们都相同的话),但只有一个定义。
-
@SamVarshavchik So... 在第一种使用头文件的情况下,它声明并定义了每次包含 Message.h 的变量,从而打破了单一定义规则。唯一允许它编译的是包含守卫?该程序在两种情况下都成功编译并按预期运行(VS 2017)。
-
@Jaymaican -- 看起来人们忽略了每个字符串对象上的
const。这些对象具有内部链接(即,它们在包含该标题的任何翻译单元之外不可见),因此不存在 ODR 违规。
标签: c++ namespaces constants definition extern