Почему я должен использовать ключевое слово extern для объявления переменных в области имен? - PullRequest
0 голосов
/ 01 января 2019

Я довольно новичок в C ++ и в настоящее время изучаю его.У меня есть некоторый опыт работы с Java.

Я хотел бы иметь пространство имен, называемое «Сообщение», которое будет использоваться для хранения неизменяемых / константных строк, которые будут использоваться в различных классах всей моей программы.(Например, заголовки, ключевые слова, имена и т. Д.).

Если бы все эти строки были в классе, они были бы константными и статичными, поэтому я считаю, что лучше поместить их в пространство имен, а не в класс,Мой текущий «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: ";

У меня было мало времени для разъяснений от преподавателя до конца сеанса, и пройдет довольно много времени, прежде чем я получу возможность.Из того, что я исследовал, это связано с единицами перевода и, в частности, с попыткой использовать переменную в другой единице перевода.

Я понимаю общую концепцию этого, но не могу понятьВыгода в том, что преимущества использования extern в этом контексте?

Разве здесь недостаточно защитников включения, чтобы переменные пространства имен Message :: не были объявлены / определены более одного раза?Почему ключевое слово extern рекомендуется в этом контексте, и это исключительно для преимущества скорости компиляции?

1 Ответ

0 голосов
/ 01 января 2019

Оба будут работать очень хорошо (несмотря на коленные комментарии, которые получил вопрос).Разница немного неуловима.

В первом примере каждая единица перевода (например, файл .cpp), которая включает этот заголовок, получит копию каждой из этих трех строк.Это нормально, потому что они помечены const, поэтому они не экспортируются из модуля перевода.Если бы они не были const, у вас было бы несколько определений одного и того же символа.

Во втором примере ровно одна копия каждой из трех строк.Эти копии находятся в Message.cpp и будут связаны с вашим исполняемым файлом.Любой модуль перевода, который включает Message.h, будет знать об этих именах, потому что они объявлены в заголовке и могут их использовать.

Для небольших вещей, таких как постоянные значения int, первый подход наиболее распространен,Для более крупных вещей, таких как строковые объекты (вещи, которые обычно требуют нетривиальной инициализации), наиболее распространенным является второй подход.

...