Dynamisches 2D-Array mit new erzeugen (Doublepointer)

  • Im Beispiel wir ein dynamisches 2D-Array mittels Doublepointern erzeugt, verwaltet und wieder gelöscht

__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
int iRasterX1 = 10; // 10*20 Elemente
int iRasterX2 = 20;

// 2D Array erzeugen
// dazu wird ein Pointer auf einen Pointer deklariert,
// erstmal einen einfachen Vektor mit iRasterX1 (10) Elementen erzeugen
float **faVal = new float*[iRasterX1];

// danach für jedes Element des Vektors iRasterX2 (20) Unterelemente erzeugen
for (int i=0; i

Mit einem TList – Objekt Bausteine verwalten

  • Das TList-Objekt verwaltet Adressen auf Objekte, dazu steht schon eine Vielzahl von Methoden (siehe Borland-Hilfe) zur Verfügung
  • Zur Beachtung: werden Objekte aus der Liste gelöscht, bedeutet das nicht zwingend, dass diese Objekte auch im Speicher automatisch freigegeben (delete) werden!
  • Zur Vereinfachung des TList-Zugriffes sollte man sich folgende Template-Klasse definieren:
template <class T-> class TListe : public TList // neue TListe von TList ableiten
{
    public:

    // im Destruktor auch schön alles wieder aufräumen
    virtual __fastcall ~TListe(){ delete_all(); };

    // die Funktion Item() gibt gleich das benötigte Listenelement ohne Cast-Kopfstand zurück
    T* __fastcall Item(unsigned int uiIndex)
    {
        T* R = NULL;
        if (uiIndex < Count)
        {
            R = ((T*)Items&#91;uiIndex&#93;);
        }

        return R;
    };

    // Item_from_Id() sucht ein Objekt anhand seiner ID aus der Liste heraus
    T* __fastcall Item_from_Id(unsigned int uiId)
    {
        T *R = NULL;
        for (unsigned int i=0; i<Count; i++)
        {
            if (((T*)Items&#91;i&#93;)->uiId == uiId)
            {
                R = (T*)Items[i];
                break;
            }
        }

        return R;
    };

    // _Last() gibt das letzte Element der Liste zurück
    T* __fastcall _Last(){ return (Count->0) ? (T*)Items[Count-1] : NULL; };

    // löscht ein Item anhand seines Indexes aus der Liste und aus dem Speicher
    void __fastcall _delete(unsigned int uiIndex)
    {
         T *R=((T*)Items[uiIndex]);

         Delete(uiIndex);

         if (R)
         {
            delete R;
            R = NULL;
         }
    };

    // _delete_by_id() löscht ein Item anhand der Id aus der Liste und aus dem Speicher
    // (auch mehrere mit der selben Id)
    // und gibt die Anzahl der gefundenen (gelöschten) Items zurück
    int __fastcall _delete_by_id(unsigned int uiId)
    {
        int iAnzDelObj = 0;
        for (unsigned int i=0; i<Count; i++)
        {
            if (((T*)Items&#91;i&#93;)->uiId == uiId)
            {
                _delete(i);
                iAnzDelObj++;
            }
        }

        return iAnzDelObj;
    };

    // delete_all() löscht alle Listenelemente aus der Liste und dem Speicher
    void __fastcall delete_all()
    {
         while (Count->0) _delete(0);
    };

    // GetNewBlockId() gibt eine gültige freie Block-ID -> 0 aus der Liste zurück
    unsigned int __fastcall GetNewBlockId()
    {
        bool bFound   = true;
        unsigned int uiIdCount = 0;

        while (bFound)
        {
              uiIdCount++;

              for (unsigned int i=0; i<Count; i++)
              {
                  if (Item(i)->uiId == uiIdCount)
                  {
                        bFound = true;
                        break;
                  }
                  else
                  {
                      bFound = false;
                  }
              }
        }
            
        return uiIdCount;
    };
};
  • dann eine Bausteinklasse definieren:
class TBaustein
{
    public:

    // Beispiel-Variablen
    unsigned int uiId;
    AnsiString sName;

    // hier können weitere Parameter stehen

    // Konstruktor
    TBaustein(unsigned int ID, AnsiString Name){ uiId=ID; sName=Name; };

    // Destruktor
    virtual __fastcall ~TBaustein(){};
};
  • Anwendung im Quellcode:
// neue Liste für Baustein-Objekte erzeugen
TListe<TBaustein-> *BausteinListe;
BausteinListe = new TListe<TBaustein->;

// neuen Baustein erzeugen
TBaustein *Bst = new TBaustein(1, &quot;Test&quot;);

// Bausteine (Objekte) zur Bausteinliste hinzufügen
BausteinListe->Add(Bst);

// den zweiten Baustein anhand seines Indexes aus der Liste holen und einen anderen Namen zuweisen
TBaustein *Bst = BausteinListe->Item(1);
Bst->sName = &quot;Test54&quot;;

// Baustein anhand seiner ID aus der Liste ermitteln und einen anderen Namen zuweisen
TBaustein *Bst = BausteinListe->Item_from_Id(Id);
Bst->sName = &quot;Test2&quot;;

// den letzten Baustein der Liste ermitteln
TBaustein *Bst = BausteinListe->_Last();

// Baustein aus der Liste löschen
BausteinListe->_delete(uiIndexWert);
// oder:
BausteinListe->_delete(BausteinListe->IndexOf(Bst));
// oder:
BausteinListe->_delete_by_id(5);

// Anzahl der Bausteine in der Liste ermitteln
int iAnzahl = BausteinListe->Count();

// alle Bausteine löschen (im Speicher!!) und aus der Liste entfernen
BausteinListe->delete_all();

// die Bausteinliste und alle Bausteine aus dem Speicher entfernen!!
if (BausteinListe)
{
    delete BausteinListe; // BausteinListe->delete_all() muss nicht explizit aufgerufen werden, da das im Destruktor der TListe erledigt wird
    BausteinListe = NULL;
}

Die Klasse DynamicArray

  • Im Beispiel kann durch Klick auf den Button1 eine beliebige Anzahl neuer Fenster in der Mainform erzeugt werden, hierzu wird ein dynamisches Array angelegt, in welchem Zeiger auf die Forms hinterlegt werden.
  • Ein Klick auf Button2 zerstört das jeweils letzte Fenster.
  • *.h
#ifndef Unit1H
#define Unit1H
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>

class TForm1 : public TForm
{
    __published: // Von der IDE verwaltete Komponenten
    TButton *Button1;
    TButton *Button2;
    TLabel *Label1;
    TLabel *Label2;
    void __fastcall Button1Click(TObject *Sender);
    void __fastcall Button2Click(TObject *Sender);
    private: // Anwender-Deklarationen
    public: // Anwender-Deklarationen

        __fastcall TForm1(TComponent* Owner);
        DynamicArray<TForm*->Form2; //dynamisches Array mit TForm-Zeigern
        int FensterNr;             //Nummer des letzten erzeugten Fensters
};
extern PACKAGE TForm1 *Form1;
#endif
  • *.cpp
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
    Randomize();
    FensterNr = 0;
    Form2.Length = 1; //Startlänge des Arrays = 1 setzen
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    // Neue Form mit Zufallsfarbe (rot, grün, blau) erzeugen
    Form2[FensterNr] = new TForm(Application);
    Form2[FensterNr]->Parent=this;
    Form2[FensterNr]->BorderStyle = bsSizeable;
    Form2[FensterNr]->Left=random(1000);
    Form2[FensterNr]->Top=random(700);
    Form2[FensterNr]->Height=300;
    Form2[FensterNr]->Width=300;

    switch (random(3))
    {
        case 0: Form2[FensterNr]->Color=clRed;
        break;
        case 1: Form2[FensterNr]->Color=clBlue;
        break;
        case 2: Form2[FensterNr]->Color=clGreen;
        break;
    }

    Form2[FensterNr]->Show();

    Form2.Length++; // Arraygröße erhöhen
    FensterNr++;    // Fensterzähler erhöhen
    Label1->Caption = IntToStr(FensterNr);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
    if (FensterNr > 0)
    {
        FensterNr--;                //Fensterzähler wieder erniedrigen
        delete Form2[FensterNr];    //Letztes Fenster zerstören
        Form2.Length--;             //Array wieder verkleinern
        Label1->Caption = IntToStr(FensterNr);
    }
}