Функция компилятора состоит в том, чтобы скомпилировать код, который вы написали, и преобразовать его в объектные файлы.Поэтому, если вы пропустили ;
или использовали неопределенную переменную, компилятор будет жаловаться, потому что это синтаксические ошибки.
Если компиляция продолжается без помех, создаются объектные файлы ,Объектные файлы имеют сложную структуру, но в основном содержат пять вещей:
- Заголовки - информация о файле
- Код объекта - Код на машинном языке (Этот код не может выполняться сам по себе в большинствеслучаи)
- Информация о перемещении - какие части кода должны иметь адреса, измененные при фактическом выполнении
- Таблица символов - Символы, на которые ссылается код.Они могут быть определены в этом коде, импортированы из других модулей или определены компоновщиком
- Отладочная информация - используется отладчиками
Компилятор компилирует код и заполняеттаблица символов с каждым знакомым символом.Символы относятся как к переменным, так и к функциям.Ответ на Этот вопрос объясняет таблицу символов.
Содержит коллекцию исполняемого кода и данных, которые компоновщик может обработать в работающее приложение или общую библиотеку.В объектном файле есть структура данных, называемая таблицей символов, которая отображает различные элементы в объектном файле на имена, понятные компоновщику.
Замечание
Если вы вызываете функцию из своего кода, компилятор не помещает окончательный адрес подпрограммы в объектный файл.Вместо этого он помещает в код значение заполнителя и добавляет примечание, в котором указывается, что компоновщик ищет ссылку в различных таблицах символов во всех объектных файлах, которые он обрабатывает, и указывает там окончательное местоположение.
Сгенерированные объектные файлы обрабатываются компоновщиком, который заполнит пробелы в таблицах символов, свяжет один модуль с другим и, наконец, даст исполняемый код, который может быть загружен загрузчиком.
Так в вашем конкретномcase -
- DefinedIncorrectFunction () - Компилятор получает определение функции и начинает его компилировать, чтобы создать объектный код и вставить соответствующую ссылку в таблицу символов.Сбой компиляции из-за синтаксической ошибки, поэтому компилятор прерывается с ошибкой.
- NonDefinedFunction () - Компилятор получает объявление, но не определяет, поэтому он добавляет запись в таблицу символов и отмечает компоновщик для добавления соответствующих значений (так каккомпоновщик будет обрабатывать кучу объектных файлов, возможно, это определение присутствует в каком-либо другом объектном файле).В вашем случае вы не указываете какой-либо другой файл, поэтому компоновщик прерывается с ошибкой
undefined reference to NonDefinedFunction
, поскольку он не может найти ссылку на соответствующую запись таблицы символов.
Чтобы понять это далее, допустим, что ваш код структурирован следующим образом
File-try.h
#include<string>
#include<iostream>
class Test {
private:
int i;
public:
Test(int val) {i=val ;}
void DefinedCorrectFunction(int val);
void DefinedIncorrectFunction(int val);
void NonDefinedFunction(int val);
template <class paramType>
void FunctionTemplate (paramType val) { i = val; }
};
Файл try.cpp
#include "try.h"
void Test::DefinedCorrectFunction(int val)
{
i = val;
}
void Test::DefinedIncorrectFunction(int val)
{
i = val;
}
int main()
{
Test testObject(1);
testObject.NonDefinedFunction(2);
//testObject.FunctionTemplate<int>(2);
return 0;
}
Давайте сначала толькоСкопируйте и соберите код, но не связывайте его
$g++ -c try.cpp -o try.o
$
Этот шаг выполняется без проблем.Итак, у вас есть объектный код в try.o.Давайте попробуем скомпоновать это
$g++ try.o
try.o: In function `main':
try.cpp:(.text+0x52): undefined reference to `Test::NonDefinedFunction(int)'
collect2: ld returned 1 exit status
Вы забыли определить Test :: NonDefinedFunction.Давайте определим это в отдельном файле.
File-try1.cpp
#include "try.h"
void Test::NonDefinedFunction(int val)
{
i = val;
}
Давайте скомпилируем его в объектный код
$ g++ -c try1.cpp -o try1.o
$
Снова это успешно.Давайте попробуем связать только этот файл
$ g++ try1.o
/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
Нет основной ссылки, поэтому ссылка не будет !!
Теперь у вас есть два отдельных объектных кода со всеми необходимыми компонентами.Просто передайте ОБА из них компоновщику, и пусть он сделает все остальное
$ g++ try.o try1.o
$
Без ошибок !!Это связано с тем, что компоновщик находит определения всех функций (даже если он разбросан по разным объектным файлам) и заполняет пробелы в объектных кодах соответствующими значениями