Вопрос по global-variables, c++, namespaces, extern, const – Как extern работает в пространствах имен?

5

Я запускаю простую программу, похожую на то, что я нашелВот, Он предназначен для уменьшения раздувания кода при включении констант в несколько файлов. Это достигается путем использования глобальных переменных const в пространстве имен с соответствующимиextern жду деклараций.

globals.h

#ifndef GLOBALS_H_
#define GLOBALS_H_

namespace Constants
{
    // forward declarations only
    extern const double pi;
    extern const double avogadro;
    extern const double my_gravity;
}

#endif

globals.cpp

namespace Constants
{
    // actual global variables
    extern const double pi(3.14159);
    extern const double avogadro(6.0221413e23);
    extern const double my_gravity(9.2); // m/s^2 -- gravity is light on this planet
}

source.cpp

#include <iostream>
#include <limits>

#include "globals.h"

int main()
{
    double value_of_pi = Constants::pi;

    std::cout << value_of_pi;

    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    std::cin.get();

    return 0;
}

Я предполагаю, что Constants :: pi получает значение pi, содержащееся в пространстве имен Constants globals.cpp, и может сделать это, поскольку имеет доступ к самому пространству имен из включенного globals.h. Я не понимаю, почемуconst global определения / инициализации в globals.cpp нуженextern ключевое слово? Я пытался удалитьextern ключевые слова в globals.cpp, думая, что это не нужно, но моя программа не будет работать без них. я думалextern был использован только для предварительных деклараций? Зачем они нужны дляconst global определения / инициализации? Это как-то связано с пространством имен, в котором они определены?

Ваш Ответ

1   ответ
10

в несколько файлов

Я бы посоветовал не сосредотачиваться на такого рода оптимизациях, если это не становится действительно необходимым, а скорее выбрать простейший дизайн: определить эти константы непосредственно в заголовочном файле и включить этот заголовочный файл из всех блоков перевода («.cpp файлы»), которые нуждаются чтобы получить доступ к этим константам. Поскольку эти объектыconstони будут иметь внутреннюю связь, и компоновщик не будет кричать на вас из-за нарушения правила единого определения.

Я попытался удалить ключевые слова extern в globals.cpp, думая, что это не нужно, но моя программа не будет работать без них

Это потому, что пространство именconst объекты со статической продолжительностью хранения (например, вашиpi переменная) естьвнутренняя связь если вы явно не определите их какextern.

Я думал, что extern использовался только для предварительных деклараций?

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

Это как-то связано с пространством имен, в котором они определены?

Нет, это правило для всех уровней пространства именconst объекты со статической продолжительностью хранения, и это указано в пункте [basic.link] / 3 стандарта C ++:

Имя, имеющее область имен (3.3.6), имеет внутреннюю связь, если это имя

(3.1) [...] - переменная, функция или шаблон функции, которые явно объявлены статическими; или же,

(3.2) -переменная энергонезависимого типа с константной квалификацией, который явно не объявлен как extern и не был ранее объявлен как имеющий внешнюю связь; или же

(3.3) - член данных анонимного объединения.

Это не так, но есть другие примеры на странице, с которой он взял код. Puppy
Я чувствую себя вынужденным понизить голос, потому что вы не указали, насколько он глуп, а вместо этого сосредоточены только на языковой адвокатуре, которая будет иметь ограниченную ценность для спрашивающего. Puppy
@Puppy: не стесняйтесь понижать голос. Ваша точка зрения действительна. Имейте в виду, однако, что это не «изменяемые переменные», как вы написали в комментарии к вопросу. Они естьconst объект. Но, честно говоря, я буду редактировать. Andy Prowl
Дамы, я, вероятно, буду использовать глобальные переменные только один или два раза в своей жизни. Я здесь только для того, чтобы понимать язык, поэтому, если я найду плохо написанный код, я пойму, что он означает. @AndyProwl Спасибо за ваше подробное объяснение. Теперь я понимаю большинство из них, за исключением двух вещей. С сайта, с которого я это снял, он говорит, что переменные внутриnamespace Constants являютсяфактические глобальные переменные, но я думал, что пространство имен имеет область видимости и, следовательно, что-нибудь внутри не может иметь глобальную область видимости? И делаетConstants::pi захватитьидентификатор из предварительной декларации пи вglobals.h? Wandering Fool
@WanderingFool: Они находятся на уровне пространства имен, и их обычно называют «глобальными», потому что они не находятся в области блока, но это также не совсем точно, так как они не являются частью глобального пространства имен. Они имеют статическую длительность хранения, создаются доmain() входит и уничтожается после того, как его оставили, но они живут вConstants Пространство имен и для доступа к их имени необходимо указатьConstants:: (или сделать это неявным образом с помощью директивы using или объявления using). Я думаю, что ответ на последний вопрос "да": имя видно благодаря заголовку Andy Prowl

Похожие вопросы