Это код темы:
externfile.cpp
int i = 10;
mainfile.cpp
#include <iostream>
using namespace std;
extern int i;
int main(int param)
{
cout << i << '\n';
int i = 0;
cout << i << '\n';
cout << ::i << '\n';
}
При компиляции этой программы (с использованием Visual Studio 2008) она работает нормально, и результат будет:
10
0
10
что неудивительно для меня, это вопрос сфер.
Но что меня смущает, так это то, как mainfile.cpp
файл получить значение i
От другого .cpp
файл (externfile.cpp
в нашем случае)? только потому, что они находятся в одном каталоге? или такое же решение?
И лучше: как «объединяются» исходные файлы при компиляции проекта (с VS2008, если я должен указать)? в каком «порядке» они размещены? и как они ограничены?
«Нормальный» проект VC ++1 поручить VC ++ скомпилировать каждый исходный файл отдельно в «объектный файл» (или объектный модуль), где компилятор оставляет «заполнители» для символов, которые еще не разрешены (например, external
переменные или функции, которые объявлены, но не определены).
Затем все объектные файлы связываются вместе с помощью компоновщика, который связывает их вместе для создания окончательного исполняемого файла. Во время этого отрывка «заполнители» заменяются фактическим адресом кода / данных, на которые они ссылаются, которые определены в различных объектных файлах. Если какое-то необходимое определение не найдено, вы получите неопределенную ссылочную ошибку, если какой-либо символ будет найден более одного раза, вы получите ошибку множественного определения2.
Для получения дополнительной информации о классической модели связывания, посмотрите на Эта статья Раймонд Чен (и, если вам интересно, вся серия).
inline
функции и template
конкретизации; в этих случаях компоновщик просто берет все, что он предпочитает (что не должно быть проблемой, поскольку множественные определения таких объектов должен быть таким же)Ваша IDE VS2008 передает исходные файлы компилятору. Компилятор строит ваши исходные файлы в объектные файлы, а затем передает эти файлы компоновщику, компоновщик связывает эти файлы, а также ваши включения.
Затем компоновщик выдаст двоичное представление всех этих файлов, будь то dll, lib или exe.
Это очень простое резюме того, что происходит, есть еще процессы, которые продолжаются.
Если бы вы делали это вручную, было бы 4 шага для запуска программы на C или C ++.
1 — препроцесс, в основном имеет дело с макросами C, #define и т. Д.
2 — компилировать, файлы конвертируются в объектный код с таблицей внешних символов, чтобы их можно было решить позже
3 — ссылка, разрешить внешние ссылки, сообщить о любых ошибках, если не может их найти
4 — запустить код.
Все это автоматизировано IDE, VS2008. Эти шаги выполняются по мере необходимости, если файл не изменился, он не перекомпилируется, если ссылка не нужна, это не делается. В .Net есть больше шагов, необходимых для сборки и т. Д.