std::map unterschiedliche Typen aufnehmen lassen

Schnelle objektorientierte, kompilierende Programmiersprache.
Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

std::map unterschiedliche Typen aufnehmen lassen

Beitrag von Dirty Oerti » Fr Aug 14, 2009 11:45 am

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?
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

sonic
Beiträge: 29
Registriert: Do Aug 13, 2009 6:58 pm

Re: std::map unterschiedliche Typen aufnehmen lassen

Beitrag von sonic » Fr Aug 14, 2009 12:05 pm

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
Frei nach dem refrain für Let it be...

Write in C, Write in C,
Write in C, yeah, Write in C.
Only wimps use BASIC.
Write in C.

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3123
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: std::map unterschiedliche Typen aufnehmen lassen

Beitrag von cloidnerux » Fr Aug 14, 2009 12:12 pm

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.
Redundanz macht wiederholen unnötig.
quod erat expectandum

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: std::map unterschiedliche Typen aufnehmen lassen

Beitrag von Dirty Oerti » Fr Aug 14, 2009 12:34 pm

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* ^^
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: std::map unterschiedliche Typen aufnehmen lassen

Beitrag von Xin » Fr Aug 14, 2009 12:51 pm

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 :)
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: std::map unterschiedliche Typen aufnehmen lassen

Beitrag von Dirty Oerti » Fr Aug 14, 2009 12:55 pm

Xin hat geschrieben:

Code: Alles auswählen

class Object
{
  public: 
    virtual ~Object();
};
Danke^^
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: std::map unterschiedliche Typen aufnehmen lassen

Beitrag von Xin » Fr Aug 14, 2009 12:59 pm

Dazu vielleicht noch ein Tipp, falls es Dir passiert ^^

http://www.proggen.org/doku.php?id=c:fa ... _to_vtable
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

sonic
Beiträge: 29
Registriert: Do Aug 13, 2009 6:58 pm

Re: std::map unterschiedliche Typen aufnehmen lassen

Beitrag von sonic » Fr Aug 14, 2009 1:07 pm

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

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: std::map unterschiedliche Typen aufnehmen lassen

Beitrag von Dirty Oerti » Fr Aug 14, 2009 1:11 pm

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()'
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3123
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: std::map unterschiedliche Typen aufnehmen lassen

Beitrag von cloidnerux » Fr Aug 14, 2009 1:17 pm

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.
Redundanz macht wiederholen unnötig.
quod erat expectandum

Antworten