Единицы трансляции и компоновка
В программе C++ символ, например имя переменной или функции, можно объявить любое количество раз в область. Однако его можно определить только один раз. Это правило является правилом "Одно правило определения" (ODR). Объявление вводит (или повторно вводит) имя в программу вместе с достаточной информацией, чтобы позже связать имя с определением. Определение вводит имя и предоставляет все необходимые сведения для его создания. Если имя представляет переменную, определение явно создает хранилище и инициализирует его. Определение функции состоит из сигнатуры и тела функции. Определение класса состоит из имени класса, за которым следует блок, который перечисляет все члены класса. (Тела функций-членов могут быть определены отдельно в другом файле.)
В следующем примере показаны некоторые объявления:
int i;
int f(int x);
class C;
В следующем примере показаны некоторые определения:
int i{42};
int f(int x){ return x * i; }
class C {
public:
void DoSomething();
};
Программа состоит из одного или нескольких единиц перевода. Единица перевода состоит из файла реализации и всех заголовков, которые он включает прямо или косвенно. Файлы реализации обычно имеют расширение .cpp
файла или .cxx
. Файлы заголовков .h
обычно имеют расширение или .hpp
. Каждая единица перевода компилируется независимо компилятором. После завершения компиляции компоновщик объединяет скомпилированные единицы перевода в одну программу. Нарушения правила ODR обычно отображаются в виде ошибок компоновщика. Ошибки компоновщика возникают, когда одно и то же имя определено в нескольких единицах перевода.
Как правило, лучший способ сделать переменную видимой в нескольких файлах — объявить ее в файле заголовка. Затем добавьте директиву #include
в каждый .cpp
файл, требующий объявления. Добавляя охранники вокруг содержимого заголовка, вы гарантируете, что имена заголовка объявляются только один раз для каждого урока перевода. Определите имя только в одном файле реализации.
В C++20 модули представлены в качестве улучшенной альтернативы файлам заголовков .
В некоторых случаях может потребоваться объявить глобальную переменную или класс в .cpp
файле. В таких случаях требуется способ сообщить компилятору и компоновщику, какой тип компоновки имеет имя. Тип компоновки указывает, отображается ли имя объекта только в одном файле или во всех файлах. Концепция компоновки применяется только к глобальным именам. Концепция компоновки не применяется к именам, объявленным в область. Область указывается набором вложенных фигурных скобок, таких как в определениях функций или классов.
Внешняя и внутренняя компоновка
Бесплатная функция — это функция, определяемая в глобальном или пространстве имен область. Глобальные переменные, не являющиеся константными, и бесплатные функции по умолчанию имеют внешнюю связь; они видны из любой единицы перевода в программе. Ни один глобальный объект не может иметь это имя. Символ с внутренней компоновкой или связью не отображается только в единице перевода, в которой она объявлена. Если имя имеет внутреннюю компоновку, то же имя может существовать в другом модуле перевода. Переменные, объявленные в определениях классов или телах функций, не имеют связи.
Вы можете принудительно заставить глобальное имя иметь внутреннюю компоновку, явно объявив его как static
. Эта ключевое слово ограничивает видимость той же единицы перевода, в которой она объявлена. В этом контексте static
означает что-то другое, чем при применении к локальным переменным.
Следующие объекты имеют внутреннюю компоновку по умолчанию:
- Объекты
const
- Объекты
constexpr
- Объекты
typedef
static
объекты в пространстве имен область
Чтобы предоставить const
внешнюю компоновку объекта, объявите его как extern
и назначьте его значение:
extern const int value = 42;
Дополнительные сведения см. в разделе extern
.
См. также
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по