Konvertierung auf Templateklasse
-
Schönen Guten Abend, allesamt!
Ich habe eine Klasse geschrieben, die einfach gesagt einen 2D-Vector für bool bereitstellt. Jetzt würde ich die Klasse gerne in eine template-Klasse für beliebige Datentypen umschreiben, was soweit auch geklappt hat.
Sobald ich die allerdings in mein Projekt einbinde und die entsprechenden Definitionen von "CMap2d myMap" auf "CMap2d<bool> myMap" umwandle, bekomme ich diese Fehlermeldung:
CGame.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: __thiscall CMap2d<bool>::CMap2d<bool>(void)" (??0?CMap2d@\_N@@QAE@XZ)" in Funktion ""public: __thiscall CGame::CGame(void)" (??0CGame@@QAE@XZ)". CGame.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: void \_\_thiscall CMap2d
::put(int,int,bool * const)" (?put@?CMap2d@_N@@QAEXHHQA_N@Z)" in Funktion ""public: void __thiscall CGame::init(void)" (?init@CGame@@QAEXXZ)".
CGame.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: bool __thiscall CMap2d<bool>::get(int,int)" (?get@?$CMap2d@_N@@QAE_NHH@Z)" in Funktion ""private: void __thiscall CGame::movePlayer(int,struct pos2d &)" (?movePlayer@CGame@@AAEXHAAUpos2d@@@Z)".Die Fehlermeldung habe ich bisher nur gesehen, wenn ich versucht habe, eine externe Bibliothek einzubinden, die eine falsche Version - und damit diverse Funktionen noch nicht implementiert - hatte.
Ich habe die Umwandlung nach dieser Url gemacht und sehe keinen Unterschied in der Herangehensweise zu meiner Klasse.
Any Hints?
Vielen Dank im Voraus,
IceBaer________________________________________________________________________
Hier ist meine Template-Klasse:
#include <stdio.h> #include <vector> template<class _type_> class CMap2d { public: CMap2d(); ~CMap2d() {}; _type_ get(int x, int y); void put(int x, int y, _type_ value); void put(int x, int y, _type_ pData[]); int iSizeX, iSizeY; private: std::vector<std::vector<_type_> > m_vData; void extendSize(int x, int y); void extendSizeBy(int x, int y); const std::vector<_type_> emptyVector; }; template<class _type_> CMap2d<_type_>::CMap2d() { iSizeX = 0; iSizeY = 0; } template<class _type_> _type_ CMap2d<_type_>::get(int x, int y) { return m_vData[x][y]; } template<class _type_> void CMap2d<_type_>::put(int x, int y, _type_ value) { extendSize(x, y); m_vData[x][y] = value; } /** * takes a 1D-array and fakes a 2d-array. */ template<class _type_> void CMap2d<_type_>::put(int x, int y, _type_ *pData) { extendSize(x, y); int i, j, k; int size = x*y; for (i=0; i<size; i++) { j = i/x; // row k = i%y; // col put(k, j, pData[i]); } } /** * extends by absolute size if necessary */ template<class _type_> void CMap2d<_type_>::extendSize(int x, int y) { int iResizeX = 0, iResizeY = 0; // do we need to resize at all? if (x > iSizeX-1) iResizeX = x-iSizeX; if (y > iSizeY-1) iResizeY = y-iSizeY; if (iResizeX!=0 || iResizeY!=0) extendSizeBy(iResizeX, iResizeY); } /** * extends by relative size if necessary */ template<class _type_> void CMap2d<_type_>::extendSizeBy(int x, int y) { int i; // do we need more entries in the first dimensions? if (x > 0) { iSizeX += x; m_vData.resize(iSizeX, emptyVector); } // if any sizechanges occur, resize the whole array, // since the new entries in the first dimensions have // the wrong size of 0. if (y > 0 || x > 0) { iSizeY += y; for (i=0; i<iSizeX; i++) m_vData[i].resize(iSizeY, 0); } }zum Vergleich hier die (funktionierende) bool-klasse:
#include <stdio.h> #include <vector> class CMap2d { public: CMap2d(); ~CMap2d() {}; bool get(int x, int y); void put(int x, int y, bool value); void put(int x, int y, bool data[]); bool load(char file[]); int iSizeX, iSizeY; private: std::vector<std::vector<bool> > m_vData; void extendSize(int x, int y); void extendSizeBy(int x, int y); const std::vector<bool> emptyVector; }; CMap2d::CMap2d() { iSizeX = 0; iSizeY = 0; } bool CMap2d::get(int x, int y) { return m_vData[x][y]; } void CMap2d::put(int x, int y, bool value) { extendSize(x, y); m_vData[x][y] = value; } /** * takes a 1D-array and fakes a 2d-array. */ void CMap2d::put(int x, int y, bool *pData) { extendSize(x, y); int i, j, k; int size = x*y; for (i=0; i<size; i++) { j = i/x; // row k = i%y; // col put(k, j, pData[i]); } } /** * extends by absolute size if necessary */ void CMap2d::extendSize(int x, int y) { int iResizeX = 0, iResizeY = 0; // do we need to resize at all? if (x > iSizeX-1) iResizeX = x-iSizeX; if (y > iSizeY-1) iResizeY = y-iSizeY; if (iResizeX!=0 || iResizeY!=0) extendSizeBy(iResizeX, iResizeY); } /** * extends by relative size if necessary */ void CMap2d::extendSizeBy(int x, int y) { int i; // do we need more entries in the first dimensions? if (x > 0) { iSizeX += x; m_vData.resize(iSizeX, emptyVector); } // if any sizechanges occur, resize the whole array, // since the new entries in the first dimensions have // the wrong size of 0. if (y > 0 || x > 0) { iSizeY += y; for (i=0; i<iSizeX; i++) m_vData[i].resize(iSizeY, 0); } }
-
Ist auch alles, also auch die Implementierung, brav in der Header-Datei?
-
Nein, wusste nicht, dass das nötig ist. Jetzt funktionierts.

Kannst Du kurz erklären, weshalb das so ist? Ich dachte der Compiler würde bei einem #include "..." die entsprechende Datei an den Anfang der .cpp-Datei kopieren und dann kompilieren, und die header-Dateien wären nur für vorkompilierte Bibliotheken wichtig...

-
Bei templates ist das anders. templates werden zur Compilezeit genaut und deshalb müssen alle Informationen (Implementierung) vorhanden sein. Insbesondere die Definition der Funktionen.