Подобно этому вопросу, я могу скомпилировать эту программу без необходимости включать hello.h в hello.cpp.
Но если я использую extern "C", то во время связывания я получаю неопределенную ссылку на hello в main.cpp. Почему это?
привет.hpp:
extern "C" void hello();
привет.cpp:
//#include "hello.h"
#include <stdio.h>
void hello() {
std::cout << "Hello!" << std::endl;
}
основной.cpp:
#include "hello.h"
int main() {
hello();
return 0;
}
g++ -c main.cpp hello.cpp
g++ main.o hello.o
main.cpp: undefined reference to 'hello'





extern "C" удаляет украшение имени, которое большинство компиляторов применяют к именам функций C++. Если вы пытаетесь назвать неукрашенное имя, но у вас получилось только украшенное, они не найдут друг друга.
В обычных компоновщиках каждая функция (не локальная для объектного файла/библиотеки) должна иметь уникальное имя. В C все функции имеют уникальное имя (без перегрузки, без членства в классе и т. д.), поэтому оформление имени не требуется (и компилятор может использовать либо отсутствие оформления, либо фиксированную схему оформления, например, добавление _). C++ имеет перегрузку функций (две функции с одинаковыми именами и разными типами аргументов), и необходимо оформление, чтобы компоновщик видел каждую перегрузку как имеющую уникальное имя. extern "C" также может изменить механизм передачи аргументов и возврата значений.
Итак, в моем случае, если бы я включил заголовочный файл в hello.cpp, спецификация компоновки применялась бы к объявлению функции (я забыл, что мне также не нужно использовать extern "C" в определении функции). Таким образом, неукрашенное имя, вызываемое в main и определенное в hello.cpp, совпадает, и связывание выполняется успешно.
Я не решаюсь сказать, что это точный дубликат, поскольку он, похоже, не дает прямого ответа на ваш конкретный вопрос, но может иметь для вас полезную информацию.