Страницы

Поиск по вопросам

понедельник, 4 февраля 2019 г.

C++: Undefined reference при линковке теста с либой

Вот исходник тесты #include #include using namespace RFw;
int main() { Array _a_;
_a_.resize(5);
_a_[2] = 'b'; _a_[3] = 'a';
printf("%c%c
", *(_a_.provideElement(2)), *(_a_.provideElement(3)));
return 0; } Так компилю: c++ test.cpp -o test -std=c++11 -Isrc-core/ -Lbin/ -lcore Вывод: /tmp/test-k6aFM8.o: In function `main': test.cpp.text+0x27): undefined reference to `RFw::Array::Array(unsigned int, int*)' test.cpp.text+0x3a): undefined reference to `RFw::Array::resize(unsigned int)' test.cpp:(.text+0x52): undefined reference to `RFw::Array::operator[](unsigned int)' test.cpp:(.text+0x76): undefined reference to `RFw::Array::operator[](unsigned int)' test.cpp:(.text+0x9a): undefined reference to `RFw::Array::provideElement(unsigned int)' test.cpp:(.text+0xbd): undefined reference to `RFw::Array::provideElement(unsigned int)' test.cpp:(.text+0x101): undefined reference to `RFw::Array::~Array()' test.cpp:(.text+0x11b): undefined reference to `RFw::Array::~Array()' clang: error: linker command failed with exit code 1 (use -v to see invocation) PS Array взят из Array.hpp который инклюдится в common.hpp Array.hpp: /** * src-core/Array.hpp */ #ifndef _ARRAY_HPP_ #define _ARRAY_HPP_
#include "util.hpp" #include "Object.hpp" #include "arrayExceptions.hpp"
namespace RFw { template class Array : public Object { public: Array(intnum _length = 0, TValue* _array = nullptr); virtual ~Array();
void addToTop(const TValue _element) throw(ArrayOverflowException); void addToEnd(const TValue _element) throw(ArrayOverflowException); void clone(const intnum _length, const TValue* _array);
TValue* provideElement(const intnum _index) throw(IndexOutOfRangeException); const TValue* provideElement(const intnum _index) const throw(IndexOutOfRangeException);
TValue& operator[](const intnum _index) throw(IndexOutOfRangeException); const TValue& operator[](const intnum _index) const throw(IndexOutOfRangeException);
void resize(const intnum _newLentgh);
const Array getClone() const; const intnum getLength() const; const TValue* getArray() const; private: intnum length__; TValue* array__; }; }
#endif // _ARRAY_HPP_


Ответ

С шаблонами вы должны помещать реализацию методов в header.
В вашем случае пишите так:
template class Array : public Object { public: Array(intnum _length = 0, TValue* _array = nullptr) : length__(_length), array__(new TValue[_length]) { // остаток имплементации } virtual ~Array() { delete[] array__; } // и так далее };
Если вы вынесете реализацию методов в .cpp-файл, компилятор не будет знать, какие инстанциации шаблона ему нужно компилировать. Это ограничение модели компиляции языка C++. Sorry for this.

Небольшое объяснение. В C++ шаблон не есть класс, это лишь «описание», по которому при подстановке шаблонных аргументов генерируется реальный класс. Никакого объектного кода шаблон сам по себе не производит.
Когда компилятор компилирует C++-файл с кодом, использующим шаблон, он видит, с каким шаблонным аргументом используется этот шаблон. Но когда он компилирует C++-файл с реализацией шаблонных методов, он не знает, с какими аргументами инстанциировался шаблон в других файлах, ведь каждый C++-файл компилируется по отдельности!
Поэтому решением является положить реализацию внутрь шаблонного класса. При этом компилятор в той точке, где он видит инстанциацию шаблона, видит весь его код, и может скомпилировать все методы класса.
(Существует ещё уродливый костыль с указанием в C++-файле точного списка инстанциаций шаблона, который настолько ужасен, что я не хочу о нём и говорить. Аналогом этому было бы около каждой функции указывать заранее список всех аргументов, с которым функция будет вызвана в программе.)

Комментариев нет:

Отправить комментарий