[gelöst] wxHashMap unterschiedlicher Type
-
Hallo,
ich brauche eine Liste, die verschiedene Typen definiert.
Ein Beispiel:class grundmusiker; class musikerGitarre : public grundmusiker; class musikerKeyboard : public grundmusiker; class musikerSchlagzeuger : public grundmusiker; WX_DECLARE_HASH_MAP(unsigned short, ???, wxIntegerHash, wxIntegerEqual, MusikBand); myFrame::myFrame() { MusikBand meineBand; meineBand[1]=new musikerGitarre(); meineBand[2]=new musikerGitarre(); meineBand[3]=new musikerKeyboard(); meineBand[4]=new musikerSchlagzeuger(); }
Dabei habe ich zwei Probleme: Zum einen, dass ich den Type für die Klasse nicht weiß. Dort wo in der DECLARE das große ??? steht komme ich nicht weiter, weil der Type ja erst zur Laufzeit festgelegt wird (keine Band ist gleich, mal kommt ein Keyboarder hinzu, mal noch ein Gitarrist, etc).
Also hab ich mir gedacht, ich übergebe vielleicht nur Zeiger in die Hash-Map. Allerdings stehe ich dann vor dem gleichen Problem (das ist das Zweite), weil ich ja die Zeiger mit
musikerGitarre* gitarreEins;
erzeuge am Typen direkt erzeuge.
Zeiger sind mir als alten PHPler leider immer noch nicht so klar, wie sie es sein sollten. Gerade bei dem Thema "Wann muss ich den Ziger mit delete wieder löschen" setzt es bei mir aus.
Ich bitte um Hilfe.Hintergrundinfos:
Ich schreibe eine Alleinunterhalter-Software auf Basis von Midi (RtMidi). In meinem Programm soll es möchlich sein, der Klasse MidiPlayer zu sagen, dass ich einen zusätzlichen Musiker (z.B. Keyboarder) brauche, der Streicher spielt. Die Bildschirmausgabe erfolgt ja in meiner Klasser myFrame (von wxFrame). Ich müsste jetzt den aktuellen Bestand der Musiker vom Frame aus abholen und am Bildschirm ausgeben und die Menüstruktur je nach Musikertypen ändern.Danke erstmal.
Stefan
-
bei ??? müsste
grundmusiker*
stehen.Dein new ist schon ok, da musikerGitarre usw. von grundmusiker abgeleitete Klassen sind, grundmusiker ist die Basisklasse.
Da du in myFrame::myFrame das Objekt meineBand erstellst musst du alle mit new erstellten Objekte am ende von myFrame::myFrame auch wieder löschen.
Du musst also alle Elemente der Map durchgehen und mit delete löschen.Schwieriger ist das auslesen der Map, da die Basisklasse als Zeiger angegeben ist, dieser aber auf eine abgeleitete Klasse zeigt. Das macht man mit "cast", schau mal bei wxDynamicCast nach.
Eventuell in grundmusiker eine Variable "int m_type" anlegen und im Konstruktor der abgeleiteten Klassen diese mit einem Wert belegen (1=musikerGitarre , 2=musikerKeyboard, 3=musikerSchlagzeuger ). Dann kannst du schon mit dem Zeiger grundmusiker->m_type erkennen, von welcher Klasse das Objekt ist, auf das der Zeiger zeigt und dann richtig casten.
-
Danke erstmal,
ich versuch mal mein Glück (aufs neue).
Allerdings kan ich kein "wxDynamicCast" in dem Manula finden:
http://docs.wxwidgets.org/stable/wx_classref.html#classref
auch kein anders "cast".
-
-
statt wxDynamicCast gehts auch so:
if (meineBand[1]->m_type == 1) musikerGitarre *pGitarre = (musikerGitarre*)meineBand[1]; else ...
-
Danke schön,
scheint zu funktionieren. Mir ist nur eines noch nicht ganz klar.Schema:
class grundmusiker { public: wxString Musikername; } class musikerGitarre : public grundmusiker { public: int GriffNummer; } OnInit/main () { musikerGitarre *pGitarre = new musikerGitarre(); *pGitarre->Musikername=_T("Udo"); *pGitarre->GriffNummer = 3; grundmusiker *pGrundmusiker = *pGitarre; musikerGitarre *pGitarre2 = (musikerGitarre*)pGrundmusiker; // Was steht in *pGitarre2->Griffnummer? delete *pGitarre2; }
Ich hab mich belesen und dabei rausbekommen, wieso musikerGitarre in grundmusiker passt. Dabei wird von musikerGitarre auf grundmusiker "verkleinert". Wenn ich jetzt wieder auf musikerGitarre vergrößere, habe ich dann die zusätzlichen Werte wieder da? So wie ich das verstehe ist der Wert dann weg (also 0?)???
-
Der Wert ist natürlich noch da.
Mit new wird ein Objekt im Speicher "angelegt" und bleibt auch erhalten bis es mit free gelöscht wird. Was du jetzt mit Zeigern machst, die auf das Objekt zeigen, hat keinen Einfluss auf das Objekt selbst.
Mit einem Basisklassen-Zeiger (grundmusiker*) kannst du nur auf Variablen zugreifen, die in der Basisklasse definiert wurden (sonst meckert der Compiler).
Um auf die Variable "GriffNummer" zugreifen zu können brauchst du den "musikerGitarre"-Zeiger (sonst meckert der Compiler), also muss gecastet werden.Deine Variante ist ok.
In *pGitarre2->Griffnummer steht 3.
-
Ich danke dir recht herzlich. Du hast mir echt weiter geholfen.
Falls du Keyboarder oder Alleinunterhalter bist schenke ich dir gerne das Programm wenn es mal fertig ist. Aber wahrscheinlich könntest du dir das ganze noch besser selbst schreiben. *g* Bin halt noch Neuling im großen Universum des C++.
Gruß,
Stefan