Template Klasse

HolgerX

Mitglied
Hallo,
ich will in VS C++ 6.0 nen Template anlegen!

Leider gibt es nirgendwo die Funktion Neues Template :(

Jetzt habe ich einfach eine neue Klasse angelegt und folgendes am Anfang der Headerdatei stehen:
Code:
template <class T> class CBildMatrix  
{

Ausserdem werden dort die Variablen und Funktionen deklariert.
Die Implementierung habe ich dann wie gewohnt in die .cpp Datei geschrieben.
Beim Versuch den ganzen Kram zu kompilieren bekam ich folgende Fehlermeldung:
Code:
Fuer die Verwendung einer Vorlagenklasse ist eine Vorlagen-Argumentliste erforderlich

In einem anderen Forum habe ich gelesen, dass auch die gesamte Implementierung in die .h Datei geschrieben werden muss.

Das habe ich dann auch getan und die .cpp gelöscht.

Aber wie kann ich nun in einer anderen Klasse mein Template nutzen?

Den Code habe ich aus einem Buch übernommen, dort stand dann folgender Aufruf:
Code:
 CBildMatrix<int> m1 (256,256);
Leider stand nirgendswo, wie ich das ausserhalb einer Main-Methode, z.B. in meiner Headerdatei der anderen Klasse als Membervariable aufrufen kann.

Jedenfalls schmeisst mir mein Kompiler immer Fehlermeldungen raus. :(
 
also wenn du das Template in anderen Klassen nutzen willst dürfte
eine

PHP:
#include <template.h>

class Irgendwas{
      Template<int> member;
};

genügen um das Template als Membervariable zu nutzen.

2.) Wie hast du deine Methoden im Template definiert?

Eine Beispiel Methode sollte folgendes sein:

PHP:
template<typename T> class Template{
   ...
  T& funktion(T& a, T& b){...}
   ...
}

Wenn du das alles befolgst sollte es eigentlich keine Probleme geben..

Gruß Redwing

p.S. Vielleicht kannst du auch Posten wie dein Template implementiert ist?
 
Das habe ich dann auch getan und die .cpp gelöscht.
Hm, Templates existieren in der Tat eigentlich nur in Headerdateien. Sie sind ja auch keine Klassen oder Funktionen, sondern nur Vorlagen für Klassen oder Funktionen.

Was soll deine Templateklasse denn tun oder sein? Kannst du mal -- wie bereits angesprochen -- vorhandenen Code posten? Dann kann ich dir gerne helfen, das Ganze in die richtige Form zu bringen.

PS: Ich liebe Templates! :-)
 
So, hier habe ich mal den ollen Quelltext rüberkopiert, den ich aus dem Buch habe:
Code:
// BildMatrix.h: Schnittstelle für die Klasse CBildMatrix.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_BILDMATRIX_H__5E39E9A8_FDCC_4AAD_A55F_2E6EB09209C2__INCLUDED_)
#define AFX_BILDMATRIX_H__5E39E9A8_FDCC_4AAD_A55F_2E6EB09209C2__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

template <class T> class CBildMatrix  
{
	unsigned int m_iXsize, m_iYsize; // Größe der Matrix
	T ** m_Matrix;
public:
	CBildMatrix();
	CBildMatrix(const CBildMatrix&);
	CBildMatrix(int, int);
	virtual ~CBildMatrix();
	T* operator[] (int);			 // access to Vector
	void operator =	(const CBildMatrix&); //assign Matrix
	void operator = (const T& v);	 // assign v to each element
	const T* operator[] (int) const; // read only access
	operator T**() {return CBildMatrix); } //efficient access
	int GetSizeX() const {return m_iXsize; } 
	int GetSizeY() const {return m_iYsize; } 

};

#endif // !defined(AFX_BILDMATRIX_H__5E39E9A8_FDCC_4AAD_A55F_2E6EB09209C2__INCLUDED_)

template <class T> CBildMatrix<T>::CBildMatrix(int x, int y)
{
	m_iXsize = x;
	m_iYsize = y;
	T* array = new T[x*y];
	m_Matrix = new T*[y];
	for (int i = 0; i<y, ++i)
		m_Matrix[i] = & (array[i*x]); // fill in vector pointers
}

template <class T> T* CBildMatrix<T>::operator [](int i)
{
	return matrix [i];
}

template <class T> const T* CBildMatrix<T>::operator [] (int i) const
{
	return matrix[i];
}

Also 100%ig habe ich den Quelltext nicht übernommen, lediglich einige Bezeichnungen von Namen sind anders.
Außerdem sind noch die #if #endif Teile von VS drin.

Der Aufruf sollte dann folgendermaßen sein:
Code:
CBildMatrix<int> m1(256,256);
Wieso muss ich beim Nutzen von Templates eigentlich das #include mit in die Headerdatei der anderen Klasse (wo ich das Template nutzen will) schreiben, und nicht wie gewohnt in die .cpp Datei ?
Kann ich die Membervariable in der anderen Klasse nur deklarieren, ohne ihr einen Wert zuzuweisen? - Wie kann ich ihr dann innerhalb der .cpp Klasse einen Wert zuweisen?
 
Ist m1ein Member einer anderen Klasse?

Dann musst du die Initialisierung in den Constructor eben dieser Klasse packen.
Z.Bsp so:

Header:
Code:
class COberMotz
{
...

  COberMotz();

  CBuildMatrix<int> m1;

Cpp:
Code:
COberMotz::COberMotz() :
  m1( 256, 256 )
{
}

Damit wird der Constructor deiner Template-Klasse mit den beiden Parametern aufgerufen.
 
Das funktioniert sogar! :)
Danke!

Aber warum zum Geier müssen die Membervariablen so
Code:
CPfurz::CPfurz() : m1(256,256)
{
}
initialisiert werden? Und nicht einfach so:
Code:
CPfurz::CPfurz()
{
   m1(256,256);
}
 
Die erste Methode (mit Initialisierungsliste) ruft direkt den passenden Konstruktor auf, um dein Objekt zu initialisieren. Das ist sehr effektiv.

Bei der zweiten Version steht innerhalb deines Konstruktors ein Konstruktoraufruf für ein Objekt, das bereits vor Eintritt in den Konstruktor erzeugt worden ist (nämlich m1). Da kannst du nicht im Nachhinein noch mal einen Konstruktor aufrufen.
 
Ja genau richtig, allerdings hat das mit Templates relativ wenig zu tun, denn das was Kachelator hier sagt, trifft allgemein auf Aggregationen von Objekten zu. (Aggregation kommt von UML)

Das ist eine Aggregation:
Code:
class A
{
public:
  A();
};

class B
{
public:
 B();
 A myA;  // hier eine Aggregation
}

Wie Kachelator schon sagte, wird das Objekt (myA)schon erzeugt bevor der Konstruktor von B durchlaufen wird.
Man kann das Ganze aber auch umgehen, in dem man einen Zeiger als Aggregation verwendet:
Code:
class A
{
public:
  A();
  A(int);
};

class B
{
public:
 B();
 ~B();
 A *myA;  // hier eine Aggregation allerdings "nur" als Zeiger auf A
}

B::B()
{
  myA = new A(5) // hier wird das Objekt erstellt
}

B::~B()
{
  delete myA;
}

So was hier passiert, ist, daß nur ein Zeiger deklariert wird, und erst der Kunstruktor von B aufgerufen wird und darin, dann der Kunstruktor von A, weil dort mit "new" erst das Objekt erzeugt wird.
Da dieses Objekt jetzt auf dem Heap-Speicher dynamisch erzeugt wird, muss man es natürlich auch wieder "selbst" löschen, sonst gibt es ein Speicherleck! Siehe Destruktor von B.

So ich hoffe das war etwas verständlich.

Gruß Homer
 
Hallo,

dazu benötige ich nochmal Hilfe: ich möchte ein Item anlegen mit einem Parameter eines gewünschten Typs. Dazu habe ich die Klasse Item und das template ItemValue. IM Item habe ich einen Pointer, auf den ich das entsprechende ItemValue legen will.

Das Template (ItemValue.h) sieht so aus:
Code:
template <class C> class ItemValue  
{
public:
	ItemValue();
//	virtual ~ItemValue();
	C value;
};


Mein Item (Item.h) sieht so aus:
Code:
#include "ItemValue.h"
class Item {
public:
	Item();
	void Get(int&);
	virtual ~Item();
private:
	int id;
	ItemValue *value;
};
typedef Item* pItem;

und die Item.cpp so:
Code:
#include "Item.h"

Item::Item() {}    //Constructor
Item::~Item() {}   //Destructor

void Item::Get(int& value)
{
	int lvalue = 0; 
	this->value =  new ItemValue <int>;

	this->value->value = lvalue;
}

Das geht aber leider nicht - der Typ stimmt nicht überein. Wie bekomme ich denn die Definition so hin, dass ich auf dem Pointer die Struktur zu liegen habe?

Gruß Bobbin.

Der Code ist stark vereinfacht - bis auf die Probleme :rolleyes:
 
Es gibt leider für Templates keine "Basisklasse" wie deinen ItemValue-Pointer.
Du müsstest dir da entweder ein Interface dazwischenschalten (frickelig) oder auf einen generell wandelbaren Typen gehen (oder sowas wie boost::any verwenden).

Ich war dann faul, und hab mir für einen Settings-Manager alles als String gespeichert. Bei ints oder floats wird dann einfach umgewandelt. Erspart einem eine Menge Ärger.
 
Zurück