Pakete in ein CArray speichern
-
Der Titel ist ein wenig seltsam, aber mir fiel kein besserer ein. Folgendes Problem:
Es passiert mir oft, dass ich verschiedene Zeiger in Listen abspeichern muss. Oft kommt es dann auch vor, dass mehrere Zeiger zusammengehören und in der Liste als ein Paket gespeichert werden sollen. Bis anhin habe ich das folgendermasen gelöst:struct SEineStruktur { CObjektEins* pObjektEins; CObjektZwei* pObjektZwei; CObjektDrei* pObjektDrei; // usw. } // In der Klasse dann: CArray<SEineStruktur> m_Array;Dies gefiel mir irgendwie aber nicht, da die Pakete oft unterschiedlich waren und ich so allerhand kleiner blöder Strukturen hatte.
Also habe ich folgendes gemacht:
class CEineKlasse { // ... private: CTypedPtrArray<CPtrArray, void**> m_Array; // ... public: AddObject(CObjektEins* pObjektEins, CObjektZwei* pObjektZwei, CObjektDrei* pObjektDrei/*, usw.*/) { void** pObjectArray = new void*[3]; pObjectArray[0] = pObjektEins; pObjectArray[1] = pObjektZwei; pObjectArray[2] = pObjektDrei; m_Array.Add(pObjectArray); } }So ganz gefällt mir dies allerdings auch nicht, da man aufpassen muss mit dem aufräumen und das 0, 1 und 2 als Index gefällt mir auch nicht so gut. Und ein Enum oder #define will ich auch nicht machen, sonst kann ich ja gleich wieder zurück zur Struktur. Meine Frage deshalb nun, was gibt es da für sinnvolle Lösungen?
Grüssli
PS: Hab es nicht ins C++ Forum getan, wegen dem CArray und CTypedPtrArray. Falls es trotzdem dort hin soll, dann tut es mir leid für die Modarbeit.
-
Keine Vorschläge, Ideen oder sonst sowas? Oder anderst gesagt: *push*
Auch ansätze wären ganz nett.Grüssli
-
Du kannst auch Arrays in Arrays machen.
Das "Oberarray" enthält Arrays. In diesen einzelnen Arrays sind dann die Zeiger, die zueinandern gehören.
-
Pellaeon schrieb:
Du kannst auch Arrays in Arrays machen.
Das "Oberarray" enthält Arrays. In diesen einzelnen Arrays sind dann die Zeiger, die zueinandern gehören.Falls dir schon aufgefallen sein sollte, dass ist eigentlich in etwa meine zweite Lösung. Aber deine Lösung die geht nämlich überhaupt gar nicht oder endet soweit, dass es die meinige ist, nur müsste ich mich nicht mehr ums aufräumen kümmern. Dafür hätte ich ne Menge Zusatzfunktionen, welche ich gar nicht brauche und könnte verschiedentlich viele Zeiger reinpacken, obwohl es pro Oberarray sowieso immer gleichviele sind. Ich brauche nicht ein zweites Array im Array, sondern ich brauche ein Paket. Ein Paket, welches x verschiedene Dinge aufnehmen kann, am besten Zeiger und ich diese Pakete dann in ein Array speicher kann. Aber anscheinend gibt es keine vernünftigere Lösung.
Aber immerhin hat jemand geantwortet ^^
Grüssli
-
Und mit Vererbung? Kannst ne Schnittstelle aus deinem verschiedenen Paketen ziehen? Dann könntest mit Zeigern auf die Basisklasse der Pakete arbeiten.
-
Mach ich schon teilweise. Aber es gibt halt einfach Objekte, die nicht eine gemeinsame Basis haben können. Oder dann halt von einem leeren Objekt, aber das ist auch nicht unbedingt die Lösung. Zudem möchte ich ja, wenn es möglich ist, nicht nur Zeiger in das Paket reinzuschaufeln, sondern auch Objekte, Werte, Referenzen usw.
Das Paket sollte aber so gestaltet sein, dass man es zur Laufzeit so anpassen kann wie man es benötigt. Also mal 5 Integer, das andere mal 3 Objekte ein Float und 2 Zeiger. usw.
*hatte gerade eine Idee, während dem Schreiben*Hmmm ich schaue mal, ob ich das umsetzen kann, und komme dann notfalls mit Fragen wieder hierher ^^
Danke.
Grüssli
-
// DataBundle.h // #pragma once typedef unsigned char Byte; class CDataBundle { // Konstruktoren und Destruktoren // public: CDataBundle(); virtual ~CDataBundle(); CDataBundle(CDataBundle& db) { m_pMemory = db.m_pMemory; m_nSizeArray = db.m_nSizeArray; m_nCount = db.m_nCount; m_nMemorySize = db.m_nMemorySize; }; // Operatoren // CDataBundle& operator =(CDataBundle& db) { m_pMemory = db.m_pMemory; m_nSizeArray = db.m_nSizeArray; m_nCount = db.m_nCount; m_nMemorySize = db.m_nMemorySize; return *this; }; // Attribute // private: Byte* m_pMemory; size_t* m_nSizeArray; size_t m_nMemorySize; int m_nCount; // Funktionen // public: // Objekt dazufügen, holen und Objektgrösse holen. int AddObject(void* pObject, size_t nObjectSize); void GetObject(int nIndex, void* pBuffer) const; size_t GetObjectSize(int nIndex) const; // Grössen zurückgeben. int GetCount() const { return m_nCount; }; int GetUpperBound() const { return m_nCount - 1; }; // CDataBundle aufräumen. void Delete() { delete [] m_pMemory; delete [] m_nSizeArray; m_nCount = 0; m_nMemorySize = 0; }; };// DataBundle.cpp // #include "StdAfx.h" #include ".\databundle.h" CDataBundle::CDataBundle() : m_pMemory(NULL) , m_nSizeArray(NULL) , m_nMemorySize(0) , m_nCount(0) { } CDataBundle::~CDataBundle() { } int CDataBundle::AddObject(void* pObject, size_t nObjectSize) { // Prüfen ob pObjekt ungleich NULL ist, // wenn nicht dann negativen Wert als Fehler zurückgeben. if(!pObject) { return -1; } // void-Zeiger nach unsigned char* casten. Byte* pBuffer = static_cast<Byte*>(pObject); // Die neue Memorygrösse berechnen. size_t nNewMemorySize = m_nMemorySize + nObjectSize; // Neues Memoryarray und neues Array für die Objektgrössen anlegen. Byte* pNewMemory = new Byte[nNewMemorySize]; size_t* nSizeArray = new size_t[m_nCount + 1]; // Prüfen ob beide neuen Arrays auch existieren. if(!pNewMemory || !nSizeArray) { // Sicherstellen, wenn nur eines nicht erstellt worden ist, // dass trotzdem der Speicher wieder komplett freigegeben wird. delete [] pNewMemory; delete [] nSizeArray; // Negativen Wert als Fehler zurückgeben. return -1; } // Das neue Memoryarray durchlaufen. size_t nOldIndex = 0, nNewIndex = 0; for(size_t i = 0; i < nNewMemorySize; ++i) { if(i < m_nMemorySize) { // Alte Bytes eintragen. pNewMemory[i] = m_pMemory[nOldIndex]; ++nOldIndex; } else { // Neue Bytes eintragen. pNewMemory[i] = pBuffer[nNewIndex]; ++nNewIndex; } } // Alte Grössen ins neue Grössenarray eintragen. for(int i = 0; i < m_nCount; ++i) { nSizeArray[i] = m_nSizeArray[i]; } // Neue Grösse an der letzten Stelle eintragen. nSizeArray[m_nCount] = nObjectSize; // Altes Memoryarray und Grössenarray löschen. delete [] m_pMemory; delete [] m_nSizeArray; // Die Zeiger der neuen Arrays den Membervariablen zuweisen. m_pMemory = pNewMemory; m_nSizeArray = nSizeArray; // Die neue Gesamtgrösse der Membervariable zuweisen. m_nMemorySize = nNewMemorySize; // Die Anzahl der Objekte inkrementieren. ++m_nCount; // Den Index des dazugefügten Objektes zurückgeben. return (m_nCount - 1); } void CDataBundle::GetObject(int nIndex, void* pObject) const { // Prüfen ob der Buffer ungleich NULL ist und ob der Index gültig ist, // wenn nicht dann die Funktion abbrechen. if(!pObject || nIndex < 0 || nIndex >= m_nCount) { return; } // void-Zeiger nach unsigned char* casten. Byte* pBuffer = static_cast<Byte*>(pObject); // Die Grösse des Objektes holen. size_t nSize = m_nSizeArray[nIndex]; // Das Startbyte herausfinden. size_t nStart = 0; for(int i = 0; i < nIndex; ++i) { nStart += m_nSizeArray[i]; } // Die entsprechenden Bytes in den Puffer kopieren. for(size_t i = 0; i < nSize; ++i) { pBuffer[i] = m_pMemory[nStart + i]; } } size_t CDataBundle::GetObjectSize(int nIndex) const { // Prüfen ob der Index gültig ist, wenn nicht dann 0 zurückgeben. if(nIndex < 0 || nIndex >= m_nCount) { return 0; } // Die Grösse des Objektes zurückgeben. return m_nSizeArray[nIndex]; }Ist zwar noch nicht wirklich das Wahre und ich baue es womöglich noch ein wenig um, aber das war so der Ansatz meiner Idee. Gehört allerdings langsam ins C++ Forum ^^
Wenn wer Vorschläge/Verbesserungen hat, dann her damit. Vor allem was das Kopieren der Bytes angeht, bin ich noch nicht wirklich zufrieden. Aber wollte nicht memcpy und co brauchen, da diese ja C und nicht C++ sind. Allerdings habe ich keine Ahnung wie man in C++ dann ein memcpy ausführt. Und wenn man in C++ memcpy verwendet, dann jage ich alle zum Teufel, welche behaupten C++ und C seien zwei verschiedene Sprachen.

*so macht nun Pause* ^^
Grüssli