LINUX.ORG.RU

Не могу подключить код из отдельного файла C++

 


0

1

Приветствую. Имею следующие файлы с исходным кодом:

index.cpp.

#include <iostream>
#include "text.h"

using namespace std;

int main()
{
	cout << getText();

	return 0;
}

text.h

#include <string>

using namespace std;

string getText();

text.cpp

string getText()
{
	return string("Клара у Карла украла кораллы. А Карл у Клары украл кларнет.");
}

При попытке скомпилировать выводится такая ошибка:

razip@elementaryOS:~/Документы/Проекты/Test$ g++ -o index index.cpp/tmp/cc4dT5qB.o: In function `main':
index.cpp:(.text+0x11): undefined reference to `getText()'
collect2: выполнение ld завершилось с кодом возврата 1

В чем проблема? Ногами не пинать, делаю первые шаги в C++.

★★
#include <string>

std::string getText()
{
    return "Клара у Карла украла кораллы. А Карл у Клары украл кларнет.";
}
#include <iostream>

extern std::string getText();

int main()
{
    std::cout << getText() << std::endl;
}
$ g++ -c text.cpp
$ g++ -c index.cpp
$ g++ -o main text.o index.o
$ ./main
Клара у Карла украла кораллы. А Карл у Клары украл кларнет.
mix_mix ★★★★★
()

у меня для тебя плохие новости. тебя обманули, это не с++. :)

если твой «проект» состоит более, чем из одного файла, надо параллельно освоить какую-нибудь систему сборки. Например, GNU Make.

aol ★★★★★
()

text.cpp Пушкин компилировать будет?

Gvidon ★★★★
()

g++ не понял, откуда взять функцию getText(). Нигде не говорится, в каком файле должна быть эта функция, а искать по всем файлам — это неправильный подход. Все необходимые файлы должны указываться при компиляции явно.

Компиляция состоит из двух шагов (я не силен в точной терминологии, пусть знающие лучше меня меня поправят): трансляция и сборка. На первом шаге из всех указанных в командной строке файлов (если в них нет синтаксических ошибок) переводятся в объектные файлы с расширением ".o". На этот момент в них могут находиться «неразрешенные символы» (unresolved externals), т. е. например имена функций из других .cpp, участвующих в сборке. На втором шаге происходит сборка полученных .o в один исполняемый файл, и в частности связывание таких символов. На этом шаге g++ и обнаружил, что есть вызов некой функции getText(), которую мы хз где взять. А text.cpp не был скомпилирован, потому что он не указан в командной строке запуска g++.

Кстати, в text.cpp нужно тоже включить text.h, либо [incline]#include <string>. Первый подход более распространен, так как не нужно при изменении списка заголовочных файлов в .h исправлять еще и .cpp

Kiborg ★★★
()

Такие команды

g++ -o index index.cpp text.cpp
или
g++ -с index.cpp
g++ -с text.cpp
g++ -o index index.o text.o
скомпилируют этот код нормально.

А у тебя сейчас что-то вроде:

g++ -с index.cpp
g++ -o index index.o
Чуешь в чем суть?

PS: в text.cpp также нужно включать <string> или «text.h»

kravich ★★★★
()
Ответ на: комментарий от aol

Спасибо за совет, буду осваивать.

Razip ★★
() автор топика
Ответ на: комментарий от Razip

extern для функций использовать не обязательно, для них по умолчанию внешняя линковка, поэтому все обходятся как раз залоговочными файлами (в моём примере их нет).

mix_mix ★★★★★
()
Ответ на: комментарий от Kiborg

трансляция и сборка

По-моему, сборку таки лучше называть линковкой, ибо термин «сборка» расплывчив сам по себе.

devsdc ★★
()
Ответ на: комментарий от devsdc

Да и трансляция тоже как-то.

Там на самом деле сложно всё, gcc и g++ не компиляторы, а лишь программки, которые парсят опции командной строки и вызывают последовательно необходимые утилиты. Компиляторы C и C++, это: cc1 и cc1plus. Они берут ваш *.с или *.cpp (*.cxx, *.C) файл и порождают из него ассемблерный листинг (*.S). Потом ассемблерный листинг ассемблируется в машинный код (объектный файл *.o или *.obj) утилитой as. И только потом все объектники собираются линковщиком ld в исполнительный файл.

EXL ★★★★★
()
Ответ на: комментарий от aol

тебя обманули, это не с++. :)

Никакого обмано! Это с++. Только «студенческий».

mos ★★☆☆☆
()
Ответ на: комментарий от aol

у меня для тебя плохие новости. тебя обманули, это не с++. :)

Вроде мода прошла на этот бред. Ан нет, кто то вылез и снова сказал бредятину.

andreyu ★★★★★
()
Ответ на: комментарий от EXL

Я не про конкретные утилиты вроде gcc и g++, а про идеологическое деление компиляции на этапы.

Сначала происходит преобразование отдельных файлов в target-код, что логично назвать трансляцией, а потом полученные странслированные юниты склеиваются между собой в процессе линковки.

На самом деле это только самое примитивное деление, в зависимости от исходного языка оно меняется: добавляется препроцессинг и что-нибудь ещё. Но это тоже уже частности, а я про общий принцип.

А вообще, я имел в виду, что сборкой часто называют весь процесс компиляции, поэтому использовать его для описания конкретного этапа как-то грустно. Термин «линковка» же более узкий и, на мой взгляд, подходит лучше в данном случае. Термин «трансляция» мне тоже хотелось чем-нибудь заменить, но я подумал, что здесь он вполне уместен (см. второй абзац этого комментария).

devsdc ★★
()
Последнее исправление: devsdc (всего исправлений: 1)
Ответ на: комментарий от andreyu

я за модой в этих ваших интернетах не слежу, а так же стараюсь называть вещи своими именами. ;)

aol ★★★★★
()
Ответ на: комментарий от aol

я за модой в этих ваших интернетах не слежу,

Плевать мне на вашу моду и ваш интернет.

а так же стараюсь называть вещи своими именами. ;)

Ну тогда поясните, где вы там не увидели c++?

andreyu ★★★★★
()

Не надо делать using namespace std; в заголовочном файле, потому что в итоге это будет действовать на все файлы, из которых ты этот заголовочный файл будешь инклюдить.

hlebushek ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.