Argumente einer Vorlagen-Klasse



  • Hallo miteinander,

    wenn ich eine Vorlagen-Klasse habe, die relativ umfangreich ist, und eine Memberfunktion einen zusätzlichen Parameter benötigt, muss ich dann der ganzen Vorlagen-Klasse zwei geben?

    Z.B.

    template<class T, class DTO>
    class class_name
    {
        T m_data;
        // ...
    
    public:
        class_name(T data);
        // ...
        void function(DTO dto);
    };
    

    Es gibt in der ganzen Klasse nur eine Funktion die den Parameter DTO benötig. Wenn ich aber folgendes schreibe

    template<class T>
    class class_name
    {
        T m_data;
        // ...
    
    public:
        class_name(T data);
        // ...
        template<class DTO>void function(DTO dto);
    };
    

    Setzt der Compiler T für DTO ein und ich bekomme eine Fehlermeldung.

    Wie löst man so etwas, bzw. was mache ich falsch?
    Bin um jede Hilfe dankbar.

    Viele Grüße
    Knecht



  • Der Codeabschnitt ist korrekt.

    Ich könnte den Post hier eigentlich beenden ;), dennoch:
    - Wie lautet die Fehlermeldung?
    - Wie ist die Implementierung von void function<>?

    EDIT:
    - Wie versuchst Du void function<> aufzurufen?



  • evtl. benutzt du auch einen schlechten compiler, der member templates nicht ausserhalb der klasse definieren kann bsp: VC6.
    zumindest sieht es so aus das deine definitionen ausserhalb wären.



  • Hallo miteinander,

    der gegebene Code war nur ein vereinfachtes Beispiel. Im Original sieht es so aus.

    namespace Tree
    {
    	typedef unsigned int qtLocCode;
    
    	template<class T>
    	class qtCell
    	{
    	public:
    		// constructors
    		qtCell(T *Data, qtLocCode xCode = 0, qtLocCode yCode = 0, 
    			   qtLocCode Level = QT_ROOT_LEVEL, qtCell<T> *Parent = 0);
    		~qtCell(void);
    
    		// ...
    
    		template<class DTO>
    		void qtBranch(DTO *dto);   // branch this Node
    		void qtUnbranch(void);	// remove all sons from here
    
    		class qtBranchError {};	// class for exception handling
    		class qtTreeSizeError {};
    
    	private:
    		int			key;		// HACK this initializer can be removed if the comparison of addresses in the neighbour searching dialog works.
    		qtLocCode	xLocCode;	// X locational code
    		qtLocCode	yLocCode;	// Y locational code
    		qtLocCode	level;		// Cell level in hierarchy (smallest cell has level 0)
    		qtCell		*parent;	// Pointer to parent cell
    		qtCell		**children;	// Pointer to first of 4 contiguous child cells
    		T			*data;		// Application specific cell data
    
    		//-------------------------------------------------------------------------------
    		// Maximum quadtree depth and related constants
    		//-------------------------------------------------------------------------------
    		static qtLocCode QT_N_LEVELS;		// Number of possible levels in the quadtree (def. = 16)
    		static qtLocCode QT_ROOT_LEVEL;		// Level of root cell (def. = QT_N_LEVELS - 1)
    		// For converting positions to locational codes (QT_MAX_VAL = 2^QT_ROOT_LEVEL)
    		static double QT_MAX_VAL;			// 32768.0 
    
    		static unsigned int counter;		
    	};
    
        // Declaration of helper functions
        // ...
    }
    
    template<class T, class DTO>
    void Tree::qtCell<T>::qtBranch(DTO *dto)
    /*
    	The qtBranch() function checks first if the cell is already branched and 
    	if so it throws an exception. Second it checks if the level of the current
    	cell is zero. This mean that the tree has reached its max height and 
    	qtBranch() throws an exception.
    	Then it calls the function T.Branch() to get the data for the new cells. 
    	Further it determis the childs location codes and creates them.
    */
    {
    	if (children) throw qtBranchError();
    	if (!level) throw qtTreeSizeError();
    
    	T **Data = data->Branch(dto);
    	qtLocCode Level = level - 1;
    	qtLocCode branch = 1 << Level;
    
    	children = new qtCell *[4];
    	children[0] = new qtCell(Data[0], xLocCode, yLocCode, Level, this);
    	children[1] = new qtCell(Data[1], xLocCode | branch, yLocCode, Level, this);
    	children[2] = new qtCell(Data[2], xLocCode, yLocCode | branch, Level, this);
    	children[3] = new qtCell(Data[3], xLocCode | branch, yLocCode | branch, Level, this);
    
    	// delete only the pointer to the data not the data themselfe.
    	delete[] Data;
    	Data = 0;
    }
    

    und die zugehörige Fehlermeldung ist die folgende.

    c:\MitsubishiQuadTree.h(364) : error C2244: 'qtBranch': Keine Übereinstimmung für Funktionsdefinition mit vorhandener Deklaration gefunden
            Definition
            'void Tree::qtCell<T>::qtBranch(T2 *)'
            Vorhandene Deklarationen
            'void Tree::qtCell<T>::qtBranch(DTO *)'
    

    Als Compiler verwende ich MS VS2003.net und die Definitionen stehen im gleichen File wie die Deklaration.

    Herzlichen Dank für die Hilfe
    Viele Grüße

    EDIT: Ich rufe die funktion folgendermaßen auf

    (*temp)->qtBranch(ppd);
    

    wobei temp ein iterator auf ein qtCell<T> object ist, da ich die leaves in einer Liste verwalte...
    ppd ist eine Struktur die die nötigen parameter zusammen fasst.



  • auf den ersten blick würde ich sagen so

    template<
        class T>
    template<
        class DTO>
    void Tree::qtCell<T>::qtBranch(DTO *dto)
    {
    // ...
    


  • Es gibt ja auch keine Funktion qtBranch in der Klasse qtCell<T, DTO> sondern nur eine Funktion qtBranch<DTO> in der Klasse qtCell<T> ;). Die korrekte Definition müsste wie folgt lauten:

    template<class T> // "äusseres" Template
    template<class DTO> // "inneres" Template
    Tree::qtCell<T>::qtBranch(DTO* dto)
    {
    //...
    }
    

    Damit weiss der Compiler, dass es sich um das Template qtBranch<DTO>(DTO*) innerhalb des Templates qtCell<T> handelt.



  • Hallo miteinander,
    genau das war's.

    Herzlichen Dank für die schnelle Hilfe.

    Viele Grüße
    Knecht


Anmelden zum Antworten