Seite 1 von 3

std::map unterschiedliche Typen aufnehmen lassen

Verfasst: Fr Aug 14, 2009 11:45 am
von Dirty Oerti
Tag :)

So, jetzt hab ich doch mal wieder was^^
Ich hab eine std::map, die als Key einen string nimmt und (im Moment, ich glaube da liegt der Fehler) als Wert ein void*
Sinn ist: In diese Map möchte ich (zusammen mit einer Beschreibung) Zeiger auf alle möglichen Objekte (Klassen hauptsächlich) legen. (Sozusagen eine Registry^^)

Nun folgendes:

Code: Alles auswählen

ModReg::~ModReg()
{
	while (!mods.empty())
	{
		map<string,void *>::iterator it = mods.begin();
		delete (it->second);
		mods.erase(it);
	}
}
So sieht der Destruktor meiner Klasse aus, die diese map verwaltet.
Ich denke aber (anhand von Debugausgaben in den in der Map gespeicherten Klassen), dass die Destruktoren der gespeicherten Klassen (in der Map) nicht aufgerufen werden.
Das ist natürlich nicht so toll.

Ich hab auch schon eine Vermutung, woran es hapert:
Ich benutze void*, der Compiler gibt mir schon nette Meldungen aus von wegen "Warnung: Löschen von »void*« ist nicht definiert"

Sollte ich es lieber mit einem enum versuchen?
Oder kann ich den Destruktor iwie anders aufrufen? Direkt?

Re: std::map unterschiedliche Typen aufnehmen lassen

Verfasst: Fr Aug 14, 2009 12:05 pm
von sonic
Der Compiler hat schon recht, wenn er sagt ein delete auf void* is undefiniert. Woher soll er wissen, welchen Destruktor er aufrufen soll, ohne jegliche Typinformation.

Den Destruktor kannst du nur aufrufen, wenn du den Typ kennst. Von daher kannst du den auch nicht aufrufen.

Infos über die zu speichernden Klassen wären nicht schlecht. Ist es vielleicht möglich eine gemeinsame Basisklasse zu bilden? Wenn nicht kannst du es vielleicht über Handles machen.

Gruß
sonic

Re: std::map unterschiedliche Typen aufnehmen lassen

Verfasst: Fr Aug 14, 2009 12:12 pm
von cloidnerux
Sinn ist: In diese Map möchte ich (zusammen mit einer Beschreibung) Zeiger auf alle möglichen Objekte (Klassen hauptsächlich) legen. (Sozusagen eine Registry^^)
Wozu? Sobald du versuchst verschiednene Objekte darin zu verwalten kannst du keins mehr aufrufen, da du nicht direkt weißt um welchen Typ es sich an der Stelle XY handelt. Und dann versuchst du ein Objekt a als Objekt b aufzurufen, das gibt also nur murks.
Du kannst wie sonic schon sagte eine gemeinsame Basisklasse mit Destruktor nutzen oder du verwaltest jedes unteschiedliche Objekt in einer jeweils eigenen Map.
Du kannst dir auch eine Verweisklasse basteln, die einen pointer auf deine Klasse enthält die du einfügen möchtest und Informationen über das Objekt.

MfG cloidnerux.

Re: std::map unterschiedliche Typen aufnehmen lassen

Verfasst: Fr Aug 14, 2009 12:34 pm
von Dirty Oerti
sonic hat geschrieben:Woher soll er wissen, welchen Destruktor er aufrufen soll, ohne jegliche Typinformation.
Jaja, das ist schon klar^^
Ich versuche das irgendwie zu umgehen.
cloidnerux hat geschrieben:Wozu?
Um alle Objekte möglichst zentral verwalten zu können.
Möglichst zentral -> weniger Aufwand für mich^^
cloidnerux hat geschrieben:Sobald du versuchst verschiednene Objekte darin zu verwalten kannst du keins mehr aufrufen, da du nicht direkt weißt um welchen Typ es sich an der Stelle XY handelt. Und dann versuchst du ein Objekt a als Objekt b aufzurufen, das gibt also nur murks.
Naja, doch. Da bei einem Aufruf (einem Suchen in der Map) suche ich nach einem bestimmten Typ.
Problem ist eben: Suche ich nach einem Objekt, dann weiß ich den Typ. Ich will ja genau diese eine Objekt. Gehe ich aber alle Objekte durch, dann weiß ich den eben Typ nicht.


Also eine Basisklasse zu bilden wäre sicherlich möglich.
In der Basisklasse müsste ich dann auch ein Feld zur Objektidentifitkation lassen.
Problem ist nur:
Wie rufe ich dann unterschiedliche Destruktoren (je nach Wert in diesem Identifikationsfeld) auf...

Code: Alles auswählen

class basis
{
private:
  int typ;
};
Über Handles...was genau meinst du damit?

Was mir noch einfällt:

Code: Alles auswählen

class basis
{
public:
virtual void kill_me()=0;
};
Wenn ich nun Klasse von dieser Basis ableite...dann müsste ich ja eigene Kill_me Funktionen einbinden können.
Anstatt meines void* nehme ich dann ein basis* in meine Map und rufe anstatt delete (bzw davor) kill_me auf.
Die Frage ist nur, ob das dann auch wirklich auf die jeweilige Kill_me Funktion hinausläuft...


Achja: @ sonic:
Herzlich willkommen im Forum :)

*edit* Warum muss QUOTE und CODE eigntl direkt nebeneinander sein? *verzweifel* ^^

Re: std::map unterschiedliche Typen aufnehmen lassen

Verfasst: Fr Aug 14, 2009 12:51 pm
von Xin
Dirty Oerti hat geschrieben:Also eine Basisklasse zu bilden wäre sicherlich möglich.
In der Basisklasse müsste ich dann auch ein Feld zur Objektidentifitkation lassen.
Problem ist nur:
Wie rufe ich dann unterschiedliche Destruktoren (je nach Wert in diesem Identifikationsfeld) auf...

Code: Alles auswählen

class Object
{
  public: 
    virtual ~Object();
};
Dirty Oerti hat geschrieben:Achja: @ sonic:
Herzlich willkommen im Forum :)
Dito :)

Re: std::map unterschiedliche Typen aufnehmen lassen

Verfasst: Fr Aug 14, 2009 12:55 pm
von Dirty Oerti
Xin hat geschrieben:

Code: Alles auswählen

class Object
{
  public: 
    virtual ~Object();
};
Danke^^

Re: std::map unterschiedliche Typen aufnehmen lassen

Verfasst: Fr Aug 14, 2009 12:59 pm
von Xin
Dazu vielleicht noch ein Tipp, falls es Dir passiert ^^

http://www.proggen.org/doku.php?id=c:fa ... _to_vtable

Re: std::map unterschiedliche Typen aufnehmen lassen

Verfasst: Fr Aug 14, 2009 1:07 pm
von sonic
Dirty Oerti hat geschrieben:Wenn ich nun Klasse von dieser Basis ableite...dann müsste ich ja eigene Kill_me Funktionen einbinden können.
Anstatt meines void* nehme ich dann ein basis* in meine Map und rufe anstatt delete (bzw davor) kill_me auf.
Die Frage ist nur, ob das dann auch wirklich auf die jeweilige Kill_me Funktion hinausläuft...
Natürlich wird weitergeleitet. Du rufst die kill_me funktion der abgeleiteten Klasse auf. Allerdings ist die Lösung von Xin zu bevorzugen
Xin hat geschrieben:

Code: Alles auswählen

class Object
{
  public: 
    virtual ~Object();
};]
Von Object ableiten und dann delete aufrufen.

@Dirty Oerti and Xin
Thanks

Re: std::map unterschiedliche Typen aufnehmen lassen

Verfasst: Fr Aug 14, 2009 1:11 pm
von Dirty Oerti
Ok, Frage^^

Wie sieht dann die abgeleitete Klasse aus? (Es ist schon etwas her, dass ich mit Klassen arbeiten konnte :D)

Code: Alles auswählen

class iwas : OBJ
{
 //egal
public:
 //ebenfalls
 ~iwas();
};
Dann bekomme ich:
In function `iwas::~iwas()':
undefined reference to `OBJ::~OBJ()'
undefined reference to `OBJ::~OBJ()'

Re: std::map unterschiedliche Typen aufnehmen lassen

Verfasst: Fr Aug 14, 2009 1:17 pm
von cloidnerux

Code: Alles auswählen

In function `iwas::~iwas()':
undefined reference to `OBJ::~OBJ()'
undefined reference to `OBJ::~OBJ()'
is doch ganz klar: Du versuchst den Destruktor deiner basisklasse aufzurufen, der aber ist Als (rein) Virtuelle deklariert, desswegen kann er nciht genutzt werden, er muss überschrieben werden.
Du brauchst die Basisklasse nur um deine Objekte zu Down-Casten um den Destruktor zu nutzen.