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... 😕


  • Mod

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


Anmelden zum Antworten