С++ доступ к переменным из файлов .CPP

Я немного не понимаю, как работает переменный доступ между файлами .cpp. Например:

main.cpp

int main()
{
    int a = i;
    return 0;
}

main2.cpp

int i;

Это генерирует ошибку компилятора в main.cpp, сообщая мне, что in i не существует. Какая тогда разница, делает ли ключевое слово «static» в этом контексте? (Я пробовал использовать Google для этого, но большинство информационных страниц «статического ключевого слова» говорят о классах и функциях)

main2.cpp

static int i;

Это то же самое? Предотвращает ли это использование extern int i для доступа к i в другом месте? Чем отличается использование анонимных пространств имен в том, как обрабатываются переменные?

main2.cpp

namespace
{
    int i;
}

Подводить итоги:

  • Можно ли получить доступ к переменным между файлами .cpp? (кроме ключевого слова extern)
  • Как ключевое слово static в глобальной переменной влияет на вещи?
  • Как анонимные пространства имен по-разному влияют на вещи?

person bfops    schedule 07.09.2010    source источник
comment
Я не думаю, что было бы справедливо так сильно менять вопрос, если никто не запросил разъяснений.   -  person Potatoswatter    schedule 07.09.2010
comment
Чтобы ответить на новый вопрос: это не так. Это избавляет вас от необходимости писать namespace { }.   -  person Potatoswatter    schedule 07.09.2010


Ответы (3)


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

Во втором примере main2.cpp определяет переменную области файла i. Переменные области файла отличаются от глобальных переменных, даже если они имеют одно и то же имя. Если бы у вас было внешнее объявление i в main.cpp во втором примере, оба файла были бы успешно скомпилированы, но тогда вы получили бы ошибку ссылки, потому что нет глобальной переменной i был определен.

Если вы переименуете main2.cpp из второго примера в main3.cpp, добавите внешнее объявление i в main.cpp, скомпилируете все три и соедините их все вместе, это будет успешным; main.cpp и main2.cpp будут использовать одну переменную с именем i, а main3.cpp будет иметь собственную совершенно отдельную переменную с именем i.

Этот материал называется linkage. Пространства имен почти полностью не связаны с компоновкой. Однако анонимное пространство имен является особенным. Определение переменной в анонимном пространстве имен для всех практических целей аналогично ее определению с помощью static — оно делает ее переменной области действия файла. (Если я правильно помню, разница есть, но она имеет значение только в том случае, если вы делаете сложные вещи с экспортированными шаблонами, а поскольку экспортированные шаблоны используются настолько мало, что говорят об удалении функции из стандарта C++, вы не не стоит об этом беспокоиться.)

Ценность анонимного пространства имен заключается в том, что вы можете поместить в него определение класса, что делает все методы класса локальными для файла. (Только блок class { ... } должен быть внутри блока namespace { ... }, чтобы получить этот эффект.) Вы не можете сделать это другим способом.

person zwol    schedule 07.09.2010

Все глобальные переменные имеют некоторую связь. extern связь требуется для обозначения одной и той же переменной в разных контекстах между разными файлами.

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

extern int i; // i exists somewhere in some .cpp file.
int i; // ah! this is the file it exists in. 
       // (Although nothing special about that.)

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

Исключением из правила static, означающего локальный файл, являются классы и inline функции. Членов класса static правильнее называть extern, поскольку семантика идентична. Это уродливо и запутанно, но я думаю, что Бьерн просто хотел убрать extern из ключевого слова.

Встроенные функции могут иметь одно и то же определение в нескольких файлах .cpp, поэтому при создании переменной static определение переменной также используется совместно.

person Potatoswatter    schedule 07.09.2010
comment
Я предполагаю, что технически верно, что в C++ вам действительно нужно создать переменную только один раз, но каждый компилятор, который я когда-либо использовал, прекрасно справлялся со слиянием int i без extern; в двух и более файлах. (Думаю, осталось от C, где это предварительные определения, а слияние обязательно.) - person zwol; 08.09.2010
comment
@Zack: Каждый компилятор, который я использовал, был полностью анальным по этому поводу. Основная практическая проблема заключается в том, что они могут быть инициализированы разными значениями. - person Potatoswatter; 08.09.2010
comment
IME они получают анальный только в том случае, если более чем одно объявление без внешних элементов имеет инициализатор. - person zwol; 08.09.2010

  • да, например, вы можете использовать статические переменные класса
  • он делает переменную локальной и постоянной для единицы компиляции
  • анонимное пространство имен предотвращает конфликты между символами. это как если бы вы вручную создавали пространство имен с уникальным именем
person Anycorn    schedule 07.09.2010