为什么要使用 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 初始化的东西),第二种方法是最常见的。
我是 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 初始化的东西),第二种方法是最常见的。