Файлы проекта таковы:
source
parser
parser.cpp
parser.hpp
brain
brain.cpp
brain.hpp
Я сначала запустил эти две команды (PWD source/brain/
):
g++ -c brain.cpp -o brain.o
ar rvs brain.a brain.o
Я скопировал оба brain.a
а также brain.hpp
в source/parser/
, Затем я запустил эту команду (PWD source/parser
):
g++ parser.cpp brain.a -o parser
И я получил эту ошибку:
/tmp/cceGRLZn.o: In function `main':
parser.cpp:(.text+0x1cc): undefined reference to `std::brain<long long>::brain()'
parser.cpp:(.text+0x205): undefined reference to `std::brain<long long>::init(int)'
parser.cpp:(.text+0x26b): undefined reference to `std::brain<long long>::work()'
parser.cpp:(.text+0x2a4): undefined reference to `std::brain<long long>::clear()'
parser.cpp:(.text+0x2ec): undefined reference to `std::brain<long long>::~brain()'
parser.cpp:(.text+0x322): undefined reference to `std::brain<long long>::~brain()'
/tmp/cceGRLZn.o: In function `int parser_extract_args<long long>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, int, short&, std::brain<long long>&)':
parser.cpp:(.text._Z19parser_extract_argsIxEiRSsiRsRSt5brainIT_E[int parser_extract_args<long long>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, int, short&, std::brain<long long>&)]+0x17b): undefined reference to `std::brain<long long>::push_back(long long)'
parser.cpp:(.text._Z19parser_extract_argsIxEiRSsiRsRSt5brainIT_E[int parser_extract_args<long long>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, int, short&, std::brain<long long>&)]+0x37a): undefined reference to `std::brain<long long>::push_back(long long)'
collect2: ld returned 1 exit status
Исходные файлы:
brain.cpp [http://ideone.com/GNUxmH][1]
brain.hpp [http://ideone.com/M2IFAI][2]
parser.cpp [http://ideone.com/fJRzhD][3]
parser.hpp [http://ideone.com/mj6dST][4]
Что я должен делать?
Бьюсь об заклад, вы реализовали функции-члены шаблона вашего класса brain
в .cpp
файл. Вам нужно предоставить определения шаблонов в заголовочном файле, чтобы компилятор мог генерировать соответствующий код, когда он видит создание шаблона. Так что переместите содержимое brain.cpp
вплоть до brain.h
,
В качестве примера рассмотрим эти три файла:
test.h
template <typename T>
struct test
{
void foo(T);
};
test.cpp
#include "test.h"
template <typename T>
void test<T>::foo(T x)
{
// do something with x
}
main.cpp
#include "test.h"
int main()
{
test<int> t;
t.foo(5);
}
каждый .cpp
компилируется отдельно, а затем связывается вместе. Представьте, что вы компилятор, и вы пытаетесь скомпилировать main.cpp
, Вы видите, что код хочет использовать test
шаблон создан с T
как int
, Так что теперь вам нужно сгенерировать соответствующий код для test<int>::foo
, но для этого вам нужно увидеть определение функции. К сожалению, вы этого не видели, поэтому не можете скомпилировать эту программу.
Вместо этого определение foo
должен быть перемещен в заголовочный файл, чтобы в результате появилась эта двух файловая программа:
test.h
template <typename T>
struct test
{
void foo(T);
};
// Alternatively, you can define this up in the class definition
void test<T>::foo(T x)
{
// do something with x
}
main.cpp
#include "test.h"
int main()
{
test<int> t;
t.foo(5);
}
Обратите внимание, что вы не должны добавлять свои собственные объявления в std
Пространство имен:
Поведение программы на C ++ не определено, если она добавляет объявления или определения в пространство имен std или в пространство имен в пространстве имен
std
если не указано иное.
Первым делом: не добавляйте ни одного объекта в std
Пространство имен. Это дает вашу программу Неопределенное поведение.
Из вашего сообщения похоже, что вы добавили класс с именем brain
к std
Пространство имен. Удалить brain
от std
пространство имен и поместите его в какое-то ваше пространство имен. Единственное, что вы можете добавить к std
пространство имен специализаций шаблонов, которые принадлежат std
Пространство имен.
Во-вторых, если вы не предоставите явные экземпляры шаблонов классов, которые вы используете в своей программе, Вы должны поместить определения функций-членов шаблона класса в тот же заголовочный файл, который содержит их объявление, чтобы убедиться, что они видны с точки инстанцирования.
Отнесение их в отдельный .cpp
file делает невозможным для компилятора генерировать код для функций-членов, которые вы вызываете из других модулей перевода, кроме того, который содержит их определения. Это Q&А на StackOverflow может также помочь вам
Вам нужно объявить экземпляр класса шаблона мозга с нужным вам типом, поэтому в файле brain.cpp в конце файла вы должны указать:
template class brain <long long> ;
Когда вы компилируете brain.cpp, если у вас там нет спецификаторов шаблонов, он не создаст никакого связанного кода, потому что не может создать экземпляр класса шаблона без объявления типа. Тем не менее, при использовании шаблонных классов их лучше хранить в виде чистых заголовочных файлов.