Verschiedene Objekte in einem Container

Panda Cabrio

Grünschnabel
Hallo,

habe folgendes Problem:

Ich habe drei Klassen CIMDrawing, CIMText und CIMLine welche alle von der Klasse CIMElement abgeleitet sind.
Dann gibt es noch eine Klasse CIMImage die in einer Membervariable Objekte von den anderen drei Klassen aufnehmen soll.

Wenn ich dafuer jetzt einen STL-Container (vektor<CIMElement> ) nehme kann ich nur auf die gemeinsamen Attribute der Klassen zugreifen weil beim Einfuegen in den Vektor alle Objekte zu einem CIMElement werden.

Um das Problem einfach zu lösen könnte ich jetzt ja drei Container (fuer jeden Objektyp einen) nehmen, aber das finde ich nicht so schoen, denn wenn es nochmal nen vierten typ gibt muss ich dann ja auch einen vierten container nehmen.

gibt es da nicht vielelicht noch nen anderen Container oder etwas änliches in den/das ich alle objecttypen reintuen kann und die dann auch wieder rausbekomme!
 
Du könntest einen Container mit Zeigern auf CIMElement machen und Dir den konkreten Typ des Elementes zur Laufzeit ermitteln (entweder mit den Laufzeit-Typinformationen oder mit einer eigenen (enum-)Membervariablen, die den Typ des CIM-Elementes angibt). Dann machst Du je nach ermitteltem Typ einen dynamic_cast auf einen Zeiger des richtigen Typs.
 
das mit den Zeigern war meine erste Idee aber wie verhindere ich das ich dann lauter Speicherlecks bekomme?
Die Funktionen in denen die Objecte erzeugt werden sind schon lange vorbei wenn ich die Objekte noch brauche und wenn ich am ende der Funktione kein delete mache meckert der Debugger wegen eines Speicherlecks!
 
Hallo,

versuchst du lokale Objekte der Methode in das Array zu speichern oder sind das Classmember? Wenn es Classmember sind musst du die Objekte nur zu einem späteren Zeitpunkt deleten.
Ansonsten würde ich sagen lege in der Parentclass eine ObjectID an welche die Childklassen identifiziert und dann kannst du einen normalen cast auf das Object machen.


Grüße
R.
 
Zuletzt bearbeitet:
Das mit der Speicherverwaltung is nicht immer ganz einfach.
Die sauberste Methode wäre die folgende: Du legste eine Containerklasse CIMElementVector an, die protected von std::vector<CIMElement> erbt. Dann implementierst Du eigene Methoden zum Hinzufügen, Löschen und Finden von Elementen. Für das Hinzufügen von Elementen brauchst Du für jede von CIMElement abgeleitete Klasse eine eigene:
Code:
bool CIMElementVector::Add(const CIMDrawing & NewElem);
bool CIMElementVector::Add(const CIMText & NewElem);
bool CIMElementVector::Add(const CIMLine& NewElem);
In diesen Methoden allokierst Du mit new jeweils ein neues Element der entsprechenden Klasse und fügst es dem Vektor hinzu (Dafür ist ein Kopierkonstruktor ganz praktisch):
Code:
bool CIMElementList::Add(const CIMDrawing & NewElem)
{
    CIMDrawing *pNew = new CIMDrawing(NewElem);
    push_back(pNew);
}
Da ich annehme, die Elemente werden alle durch dieselbe Variable identifiziert (einen Namen oder eine ID in CIMElement), brauchst Du nur eine Methode zum Löschen, der Du eben den Namen bzw. die ID übergibst. Darin suchst Du Dir den Zeiger auf das entsprechende Element, deletest ihn und entfernst ihn aus dem Vektor (zu.B. indem Du das Vektor-Element mit NULL überschreibst).
Im Destruktor von CIMElementVector gehst Du den ganzen Vektor durch und löschst alle noch enthaltenen Elemente.

So hast Du die Speicherverwaltung komplett innerhalb der Klasse und es können eigentlich keine Speicherlecks mehr entstehen. Du mußt nur aufpassen, wenn Du einen Kopierkonstruktor oder den Operator '=' fur Deine Vektorklasse implementierst, daß Du nicht die Zeiger des Quellvektors in den Zielvektor kopierst, sondern da auch Kopien der enthaltenen Elemente anlegst.

Ich kenne ja den Anwendungsfall nicht, aber Du soltest beachten, daß Du Elemente, die nicht am Ende des Vektors sind, nur überschreiben, nicht aber löschen kannst. Evtl. könnte eine std::list oder - bei größeren Anzahlen von Elementen - eine std::map besser sein. Die oben beschriebene Vorgehensweise bleibt in beiden Fällen gleich.
 
Ich habe die Zeiger abgespeichert in einem STL_Vektor so wie es auch meine und deine erste Idee war!
Mein Fehler bei mersten Versuch war nur das ich den Destruktor der CIMElement Klasse nicht als virtual deklariert hatte daher dann die Speicherlecks!
Jetzt ist alles super ;-) !
 
Zurück