#cpp #шаблоны_с++ #компоновщик #clang
Вот исходник тесты #include#include using namespace RFw; int main() { Array _a_; _a_.resize(5); _a_[2] = 'b'; _a_[3] = 'a'; printf("%c%c\n", *(_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_
Ответы
Ответ 1
С шаблонами вы должны помещать реализацию методов в header. В вашем случае пишите так: templateclass 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++-файле точного списка инстанциаций шаблона, который настолько ужасен, что я не хочу о нём и говорить. Аналогом этому было бы около каждой функции указывать заранее список всех аргументов, с которым функция будет вызвана в программе.)
Комментариев нет:
Отправить комментарий