TKlasse<int>



  • Hey,

    ich arbeite derzeit an einem eigenen dynamischen mehrdimensionalen Array, möchte das aber natürlich mit verschiedensten Typen machen. Derzeit sieht mein Header so aus:

    class IntMatrix2D {
    	private:
    		std::vector<int> Data_;
    		unsigned int Rows_;
    		unsigned int Cols_;
    	public:
    		IntMatrix2D();
    		IntMatrix2D(unsigned int rows, unsigned int columns);
    
    		void resize(unsigned int rows, unsigned int columns);
    
    		int& operator()(unsigned int row, unsigned int column);
    };
    

    Wie ihr seht sieht mein Name derzeit so aus: "IntMatrix2D". Mir wäre es aber natürlich lieber, wenn ich einfach TMatrix2D<char> bzw TMatrix2D<int> schreiben könnte. Kann man das realisieren? Geändert werden müsste dann zB der Rückgabewert von "operator()" auf den angegebenen.

    Danke!



  • Das kann man mit Templates realisieren.



  • Hey,

    danke schonmal, ich scheitere aber an der Umsetzung:

    matrix.h

    //---------------------------------------------------------------------------
    
    #ifndef matrixH
    #define matrixH
    #include <vector>
    //---------------------------------------------------------------------------
    template <class T>
    class TMatrix2D {
    	private:
    		std::vector<T> Data_;
    		unsigned int Rows_;
    		unsigned int Cols_;
    	public:
    		TMatrix2D();
    		TMatrix2D(unsigned int rows, unsigned int columns);
    
    		void resize(unsigned int rows, unsigned int columns);
    
    		T& operator() (unsigned int row, unsigned int column);
    		TMatrix2D& operator=(const TMatrix2D &matrix);
    };
    //---------------------------------------------------------------------------
    #endif
    

    matrix.cpp

    //---------------------------------------------------------------------------
    
    #pragma hdrstop
    
    #include "matrix.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    //---------------------------------------------------------------------------
    template <class T>
    TMatrix2D<T>::TMatrix2D() {
    	resize(0,0);
    }
    //---------------------------------------------------------------------------
    template <class T>
    TMatrix2D<T>::TMatrix2D(unsigned int r, unsigned int c) {
    	resize(r,c);
    }
    //---------------------------------------------------------------------------
    template <class T>
    void TMatrix2D<T>::resize(unsigned int r, unsigned int c) {
    	Data_.resize(r * c);
    	Rows_ = r;
    	Cols_ = c;
    }
    //---------------------------------------------------------------------------
    template <class T>
    T& TMatrix2D<T>::operator() (unsigned int r, unsigned int c) {
    	return Data_[r * Cols_ + c];
    }
    //---------------------------------------------------------------------------
    template <class T>
    TMatrix2D<T>& TMatrix2D<T>::operator= (TMatrix2D<T> const& m) {
    	if (*this != m) {
    		for (int i = 0; i < Cols_ * Rows_; i++) {
    			this->Data_[i] = m.Data_[i];
    		}
    	}
    }
    

    [ilink32 Fehler] Error: Nicht auflösbares externes 'TMatrix2D<int>::TMatrix2D<int>(unsigned int, unsigned int)' referenziert von C:\USERS\T**\DOCUMENTS\RAD STUDIO\PROJEKTE\C++\TEST\WIN32\DEBUG\TEST.OBJ



  • Schau mal hier unter Punkt 5



  • Ich blicks nicht sry 😞



  • Das Problem ist, dass die Klassendefinitionen in der Header-Datei und die Methodendefinitionen in der cpp-Datei liegen.

    Die einfachste Moeglichkeit liegt darin, alles in eine Header-Datei zu schreiben:

    Header File:

    #ifndef matrixH
    #define matrixH
    
    #include <vector>
    
    template <class T>
    class TMatrix2D {
        private:
            std::vector<T> Data_;
            unsigned int Rows_;
            unsigned int Cols_;
        public:
            TMatrix2D();
            TMatrix2D(unsigned int rows, unsigned int columns);
    
            void resize(unsigned int rows, unsigned int columns);
    
            T& operator() (unsigned int row, unsigned int column);
            TMatrix2D& operator=(const TMatrix2D &matrix);
    };
    
    template <class T>
    TMatrix2D<T>::TMatrix2D() {
        resize(0,0);
    }
    
    template <class T>
    TMatrix2D<T>::TMatrix2D(unsigned int r, unsigned int c) {
        resize(r,c);
    }
    
    template <class T>
    void TMatrix2D<T>::resize(unsigned int r, unsigned int c) {
        Data_.resize(r * c);
        Rows_ = r;
        Cols_ = c;
    }
    
    template <class T>
    T& TMatrix2D<T>::operator() (unsigned int r, unsigned int c) {
        return Data_[r * Cols_ + c];
    }
    
    template <class T>
    TMatrix2D<T>& TMatrix2D<T>::operator= (TMatrix2D<T> const& m) {
        if (*this != m) {
            for (int i = 0; i < Cols_ * Rows_; i++) {
                this->Data_[i] = m.Data_[i];
            }
        }
    }	
    
    #endif
    


  • Das ist ja blöd 😞 Kann man das nicht auch mit der Header und CPP Datei machen?



  • Es gibt gewisse Compiler, die ein Keyword 'extern' anbieten, mit dem man das Problem loesen kann. Es wird allerdings von vielen Compilern nicht unterstuezt und ich kenne es nicht wirklich. Google mal danach.

    Eine andere Moglichkeit ist die Klassendefinition weiterhin in ein Header-File zu schreiben und die Methodendefinition in ein .impl File. Dann kannst du das .impl File im Header File inkludieren. Angewendet auf dein Beispiel ergibt das:

    Header File:

    #ifndef matrixH
    #define matrixH
    
    #include <vector>
    
    template <class T>
    class TMatrix2D {
        private:
            std::vector<T> Data_;
            unsigned int Rows_;
            unsigned int Cols_;
        public:
            TMatrix2D();
            TMatrix2D(unsigned int rows, unsigned int columns);
    
            void resize(unsigned int rows, unsigned int columns);
    
            T& operator() (unsigned int row, unsigned int column);
            TMatrix2D& operator=(const TMatrix2D &matrix);
    };
    
    #include "Matrix.impl"
    
    #endif
    

    Matrix.impl File:

    template <class T>
    TMatrix2D<T>::TMatrix2D() {
        resize(0,0);
    }
    
    template <class T>
    TMatrix2D<T>::TMatrix2D(unsigned int r, unsigned int c) {
        resize(r,c);
    }
    
    template <class T>
    void TMatrix2D<T>::resize(unsigned int r, unsigned int c) {
        Data_.resize(r * c);
        Rows_ = r;
        Cols_ = c;
    }
    
    template <class T>
    T& TMatrix2D<T>::operator() (unsigned int r, unsigned int c) {
        return Data_[r * Cols_ + c];
    }
    
    template <class T>
    TMatrix2D<T>& TMatrix2D<T>::operator= (TMatrix2D<T> const& m) {
        if (*this != m) {
            for (int i = 0; i < Cols_ * Rows_; i++) {
                this->Data_[i] = m.Data_[i];
            }
        }
    }
    


  • icarus2 schrieb:

    Es gibt gewisse Compiler, die ein Keyword 'extern' anbieten

    extern kennen alle, du meinst export 🙂



  • Bashar schrieb:

    icarus2 schrieb:

    Es gibt gewisse Compiler, die ein Keyword 'extern' anbieten

    extern kennen alle, du meinst export 🙂

    Ja, ich meine natuerlich export. Danke 🙂

    *Edit
    Ich hatte noch ein merkwuerdiges Gefuehl als ich 'extern' schrieb, dachte mir aber nichts boeses dabei 😃



  • @Icarus2:
    Warum so kompliziert? Warum erst die Methodendeklaration und dann die Implementation, wo doch sowieso alles in der Header Datei stehen muss?
    Man kann doch statt

    template<typename T>
    class XYZ
    {
    public:
       XZY();
    };
    
    template<typename T>
    XZY::XYZ()
    {
    }
    

    besser

    template<typename T>
    class XYZ
    {
    public:
       XZY() 
       {
       }
    };
    

    schreiben.

    @Frolo:
    Den Kopierkonstruktor brauchst du nicht mehr, das erledigt der Compiler für dich.



  • DocShoe schrieb:

    @Icarus2:
    Warum so kompliziert? Warum erst die Methodendeklaration und dann die Implementation, wo doch sowieso alles in der Header Datei stehen muss?
    Man kann doch statt [...]

    Klar kann man das machen. Ich bevorzuge allerdings eine Trennung zwischen Klassendefinition und Methodendefinition wegen der Uebersichtlichkeit. Ich finde der Code wird dadurch auch nicht komplizierter.

    Ist wahrscheinlich Geschmackssache.


Log in to reply