简体   繁体   中英

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

I am quite new to C++ and am currently taking a short-course on it. I have some background in Java.

I wish to have a namespace called "Message", that will be used to store unchanging/constant strings that will be used in a variety of different classes throughout my program. (Eg titles, keywords, names, etc).

If all of these strings were in a class, they would be const and static, thus I feel it is best to put them into a namespace rather than a class. My current "Message.h" looked a bit like this:

#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

Until an instructor suggested that I change it to this...

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: ";

I had little time for clarification from the instructor before the end of a session and it will be quite some-time before I get the opportunity to. From what I've researched, it has to do with translation-units and more specifically trying to use a variable in a different translation unit.

I understand the general concept of this, but what I can't quite catch is the benefits of using extern in this context?

Won't the include guards be enough here that the Message:: namespace variables won't be declared/defined more than once? Why is the extern keyword recommended in this context and is this purely for the benefits of compile-speed?

Both will work just fine (despite the knee-jerk comments the question has gotten). The difference is a bit subtle.

In the first example, every translation unit (think .cpp file) that includes that header will get a copy of each of those three strings. It's okay to do that, because they're marked const , so they are not exported from the translation unit. If they were not const you'd have multiple definitions of the same symbol.

In the second example, there is exactly one copy of each of the three strings. Those copies live in Message.cpp, and will get linked into your executable. Any translation unit that includes Message.h will know about those names, because they're declared in the header, and can use them.

For small things like constant int values, the first approach is most common. For larger things such as string objects (things that typically require non-trivial initialization), the second approach is most common.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM