Problem bei einem Growable Array
-
ok, hier die TArray.h
#pragma once #include "BaseUsings.h" #include "TBaseClass.h" class TArray { private: void** m_lpVoid; int m_iCount; int m_iLenght; int m_iResizeVector; bool m_bResizable; void ReArrange(int); public: TArray(int); ~TArray(void); void Add(void*); void Remove(void*); void RemoveAt(int); void* GetItemAtIndex(int); void SetResizeable(bool); bool GetResizeable(); void SetResizeVector(int); int GetResizeVector(); int Count(); int Lenght(); };
-
*keuch und sterb*
-
...
-
Namenloser324 schrieb:
Du hast in deinem Klassencode die Überladung des operator[] nirgends aufgeführt. Daher wird dir beidem speziellen problem niemand helfen können.
Überladung ist hier nicht im Spiel.
TArray* arr = new TArray(10); TObject * o = new TObject(); // ... // TObject* oo = ((TObject *)&arr[-1]); <-- Warum hier -1???? // äquivalent zu TObject* oo = reinterpret_cast<TObject*>(&*(arr-1)); // wahrscheinlich Verwaltungsdaten im free storein jedem Fall Unfug
-
TArray soll nicht nur Elemente eines Types halten.
Ich habe eine Basisklasse TComponent die TArray enthält.
ich möchte ettliche Componenten schreiben und einen Componenttree aufbauen.Ich habe gesehen ich muss noch defensiver arbeiten.
Ich möchte derzeit nicht vector oder cgrowable von Microsoft nutzen,
ich will es lernen und verstehen. Leider sind meine C++ Kenntnisse noch
nicht so gut.Ich werd die Klasse noch einmal Schritt für Schritt durchgehen und Defensiver arbeiten, einige Schönheitsfehler sind mir noch aufgefallen.
Danke Trozdem
-
Wie willst du ein TArray benutzen, wenn du nicht weißt, welchen Typ ein Element hat? Casten und hoffen? Das ist doch Murks.
Halt einen std::vector<std::unique_ptr<TComponent>> oder so und sorg dafür, dass TComponent alle Operationen beherrscht, die du für den component tree brauchst. Und verwirf deinen bisherigen Ansatz -- egal, wie defensiv du den umsetzt, du polierst da Katzengold.
-
Alle meine Klassen haben eine Basisklasse, ich frag einfach um welchen Type es
sich handelt.
-
...
-
Also TObject is meine Mutter aller Klassen, und hält den Classname.
Dann kann ich schon Fragen, um wen es sich handelt und dann weiß ich auch was das
Object kann, oder nicht?
-
Willst du jedes Mal, wenn du eine neue Komponente baust, allen Code anfassen müssen, der TArray verwendet?
Ich lass mal nen Link da: https://de.wikipedia.org/wiki/Liskovsches_Substitutionsprinzip
Ich rate dir dringendst, das in deinem Design zu berücksichtigen, und zwar ganz unabhängig von der Programmiersprache. Bau dir eine Basisklasse, die die Operationen hat, die du brauchst, und dann merk dir, dass du Objekte dieses Typs verwaltest. Typinformationen zu vergessen und später wieder auszuklamüsern ist kein sinnvoller Ansatz.
-
seldon schrieb:
Willst du jedes Mal, wenn du eine neue Komponente baust, allen Code anfassen müssen, der TArray verwendet?
Verstehe ich nicht ganz, nur 2 Klassen haben TArray und zwar die Basis Komponente
von der alle Komponenten erben und eine Kindklasse von der alle Visuellen Komponenten erben werden, um einen SceneGraph aufzubauen.Ich werd mir den link mal anschauen danke
-
adonis schrieb:
Hallo ich habe mir eine Array Klasse geschrieben [...]
hier die TArray.h
#pragma once #include "BaseUsings.h" #include "TBaseClass.h" class TArray { private: void** m_lpVoid; int m_iCount; int m_iLenght; int m_iResizeVector; bool m_bResizable; void ReArrange(int); public: TArray(int); ~TArray(void); void Add(void*); void Remove(void*); void RemoveAt(int); void* GetItemAtIndex(int); void SetResizeable(bool); bool GetResizeable(); void SetResizeVector(int); int GetResizeVector(); int Count(); int Lenght(); };- TArray::TArray(int) sollte explizit sein.
- Viel zu viel
void! Du schmeißt wertvolle Typinformation weg. - Hier und da fehlt
const. - Verletzung der Dreierregel! (Bitte selbst nachgucken, was das ist)
adonis schrieb:
Hier meine Array Klasse:
#include "TArray.h" #include <malloc.h> TArray::TArray(int Length) { m_iCount = 0; m_iLenght = 0; m_iResizeVector = 0; m_bResizable = false; m_lpVoid = (void**)malloc(Length*sizeof(void*)+1); m_iLenght = Length; } TArray::~TArray(void) { for(int i = 0; i < m_iLenght; i++) { free(m_lpVoid[m_iLenght]); } } ...- Speicherleck: Es fehlt ein free(m_lpVoid) im Destruktor
- Du versuchst hier die Pointees zu mit free löschen, ohne zu wissen, was eigentlich hinter den void*-Zeigern steht. Ganz schlechte Idee! So werden beispielsweise garantiert keine Destruktoren aufgerufen.
adonis schrieb:
hier der Fall:
//////Test Area////// //TComponent* root = new TComponent(NULL); //TComponent* Child1 = new TComponent(root); //TComponent* Child2 = new TComponent(root); //TComponent* Child3 = new TComponent(root); //int x = root->getTreeSize(); TArray* arr = new TArray(10); TObject * o = new TObject(); o->SetTClassName(EnumClassName::ClassEnum::T3DDevice); arr->Add(o); TObject* oo = ((TObject *)&arr[-1]); <-- Warum hier -1???? const char* c = (oo)->ClassNameToString(oo->GetTClassName()); /////////////////////- Zuviel
new. Wozu legst du Dein Array im Heap an? - Speicherlecks: Nirgens wird irgend etwas freigegeben.
- Wenn du Dein Array statt im Heap einfach im automatischen Speicher anlegst, wird es automatisch freigegeben. Dann läuft der Destruktor, der aber die per
newerzeugten Objekte mitfreefreigegben will. Das ist falsch. Zu einemnewgehört eindelete. Zu einemnew[]gehört eindelete[]. Allerdings muss der Zeigertyp beim delete schon der richtige sein: Entweder der einer Basisklasse mit virtuellem Destruktor oder der richtige dynamische Typ.
Ich will Dich da nicht demotivieren, aber das, was du da gebaut hast, ist längst nicht so toll, wie Du es Dir wahrscheinlich vorgestellt hast. Es sieht für mich so aus, als hättest Du großes Pech mit der Auswahl Deines Lehrmaterials gehabt. Ich würde Dir empfehlen, den Kram zu vergessen und nochmal von vorn anzufangen, ohne malloc, ohne free, ohne new, ohne delete. Ich würde Dir empfehlen, auch wenn Du noch nicht weißt, wie die Sachen aus der Standardbibliothek intern funktionieren, doch erst mal diese Sachen zu verwenden, um ein "richtiges C++ Gefühl" zu bekommen. Später kann man sich dann angucken, wie man so etwas selbst schreibt.
Die C++ Community hat Dir gegenüber einen großen Lern-Vorsprung. Das ist jetzt nichts schlimmes. Du musst nur nicht jeden Fehler wiederholen, die andere schon vor Dir gemacht haben. Vor der aktuellen Standardbibliothek gab es u.a. Container-Bibliotheken, die so ähnlich gestrickt waren wie Deine. Und die sind zu Recht ausgestorben.
-
Kann das sein, dass Du früher mit Delphi gearbeitet hast? Namensgebung und Konzept erinnern an die VCL.
In C++ kann man im Gegegsatz zu Delphi Objekte nicht nur dynamisch auf dem Heap anlegen sondern auch "automatisch" auf dem Stack. Außerdem gibt es auch so nette Sachen wie Smartpointer. Wenn Du es richtig machst und die Tips aus den Beiträgen hier befolgst musst Du dich bei C++ um die Speicherverwaltung Deiner Objekte nicht selber kümmern.