Я не очень понял, что такое единица перевода и как использовать безымянные пространства имен:
Если у меня есть файл .cpp:
namespace
{
void extFunction()
{
std::cout << "Called Unnamed Namespace's function.\n";
}
}
и основной файл .cpp:
#include <iostream>
#include "ext.cpp"
using namespace std;
int main()
{
extFunction();
return 0;
}
Почему я могу получить доступ к члену безымянного пространства имен из другого файла?
Обновлено:
Спасибо за ответы; но тогда как я могу использовать безымянные пространства имен и для какой цели?
#include означает «скопировать и вставить точное содержимое файла в это место». Таким образом, ваш main.cpp скомпилирован точно так же, как если бы вы сами поместили туда безымянное пространство имен.
Никогда не включайте файл .cpp. Если бы вы не включили файл cpp и вместо этого скомпилировали его как часть своего проекта, вы бы не смогли использовать extFunction() в main.





Единица перевода — это, по сути, кусок кода, который вы передаете компилятору для обработки. Компилятор обрабатывает его и создает объектный код для компоновщика. Компоновщик объединяет объектный код всех ваших единиц перевода в исполняемый файл. (Иногда вы увидите детали, отличающиеся от этого, например, отсутствие файла для объектного кода, когда у вас есть только одна единица перевода. Концепция по-прежнему действительна, даже если детали реализации могут различаться.)
Поэтому, как правило, между .o (или .obj) файлами, созданными при компиляции, и единицами перевода существует однозначное соответствие. Также обычно вы получаете один файл .o для каждого файла .cpp. Следовательно, обычно разумно рассматривать каждый файл .cpp как отдельную единицу перевода. Пока вы не сделаете что-то нестандартное.
Когда вы используете директиву #include, вы указываете компилятору заменить эту строку всем содержимым подключаемого файла. То есть фрагмент кода, переданный компилятору, включает код как из исходного файла, так и из включенного файла. Если вы включите один файл .cpp в другой, фрагмент кода, переданный компилятору, будет включать код из двух файлов .cpp, нарушая эквивалентность между файлами .cpp и единицами перевода. Обычно это считается плохой идеей.
Давайте посмотрим на пример. Предположим, у вас есть файл с именем ext.cpp, который содержит следующее:
namespace
{
void extFunction()
{
std::cout << "Called Unnamed Namespace's function.\n";
}
}
Также предположим, что у вас есть файл с именем main.cpp, который содержит следующее:
#include <iostream>
#include "ext.cpp"
int main()
{
extFunction();
return 0;
}
Если бы вам нужно было скомпилировать main.cpp, компилятор в первую очередь предобработал бы main.cpp. Это изменяет содержимое файла, изменяя то, что видит компилятор. После предварительной обработки фрагмент кода, который будет обрабатывать компилятор, будет выглядеть следующим образом.
[lots of code from the library header named "iostream"]
namespace
{
void extFunction()
{
std::cout << "Called Unnamed Namespace's function.\n";
}
}
int main()
{
extFunction();
return 0;
}
На данный момент нет проблем с вызовом extFunction, поскольку компилятор видит безымянное пространство имен в обрабатываемом фрагменте кода.
Еще один пример запрошенной информации об использовании безымянных пространств имен. Аналогичен предыдущему, но отличается. Предположим, у вас есть файл с именем ext.cpp, который содержит следующее:
#include <iostream>
namespace
{
void extFunction()
{
std::cout << "Called Unnamed Namespace's function in EXT.\n";
}
}
void extPublic()
{
extFunction();
}
Давайте также предоставим заголовок (ext.h), который объявит функцию, имеющую внешнюю связь.
void extPublic();
Теперь переходим к main.cpp:
#include <iostream>
#include "ext.h" // <-- Including the header, not the source.
namespace
{
void extFunction()
{
std::cout << "Called Unnamed Namespace's function in MAIN.\n";
}
}
int main()
{
extFunction();
extPublic();
return 0;
}
Посмотри на это! Есть два определения функции с именем extFunction! Компоновщик не запутается? Нисколько. Эти функции не видны за пределами их единиц перевода, поэтому конфликта нет. Если вы скомпилируете main.cpp, скомпилируете ext.cpp и свяжете main.o и ext.o в один исполняемый файл, вы получите следующий результат.
Called Unnamed Namespace's function in MAIN.
Called Unnamed Namespace's function in EXT.
Одним из преимуществ безымянного пространства имен является то, что вам не нужно беспокоиться о конфликте с именами в безымянном пространстве имен другого исходного файла. (Это становится гораздо большим преимуществом, когда ваш проект разрастается до сотен исходных файлов.)
Большое спасибо за помощь!
Потому что вы
#included это сделали, так что это одна и та же единица перевода. «Единица перевода» не является синонимом «файла».