Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Verwenden von property in C++ Builder (https://www.delphipraxis.net/61276-verwenden-von-property-c-builder.html)

messie 19. Jan 2006 10:53


Verwenden von property in C++ Builder
 
Moin,

ich brech' mir gerade einen ab, eine TObjectlist im Builder 6 zu definieren.
Delphi-Quellcode:
class TParaLine : public TObject
{
  __published:
    TTntEdit *ParaLineEdit;
    TTntLabel *ParaLineLabel;
    TTntLabel *UnitLabel;
    TTntComboBox *Material;
    TTntComboBox *FlewRate;
    TTntButton *Get_h;
};

class TParas : public TObjectList
{
  private:
    TParaLine GetItem(int *index);
    void SetItem(int *index, TParaLine *Line);

  __published:
    int Add(TParaLine *ParaLine);
    __property TParaLine Items[int Id]"X" = {read=GetItem, write=SetItem};

   /* Compiler "X": E2459 VCL style classes must be constructed using operator new*/
};
Die Stelle mit dem "X" wird vom Compiler angemeckert, Meldung steht darunter.
Kommt mir komisch vor, denn die property items bringt die Vorfahrenklasse doch schon mit...

Ich habe gesehen, daß man bei einer Frage nach VCL-topics in den C-Foren erstmal eine Grundsatzdiskussion über das Erlaubt-/Verbotensein der VCL-Verwendung ertragen muß, stelle die Frage lieber hier.

Grüße, Messie

Der Jan 19. Jan 2006 11:18

Re: Verwenden von property in C++ Builder
 
Code:
    TParaLine* GetItem(int index);
    void SetItem(int index, TParaLine *Line);

  __published:
    int Add(TParaLine *ParaLine);
    __property TParaLine* Items[int Id]"X" = {read=GetItem, write=SetItem};  // "*" ist wichtig
Wenn du in C++ eine Klasse hast kannst du schreiben

Code:
TMyClass t; Klassenvariable wird definiert UND Klasse erzeugt
//oder
TMyClass *p; Zeiger auf Klasse
p = new TMyClass; Erzeugen
Erstere Variante ist bei VCL-Klassen nicht erlaubt.
Außerdem mußt du ja hier bei deinem Property Items eh einen Zieger zurückgeben und nicht die gesamte Klasse ;)

Hoffe, es war halbwegs verständlich :gruebel:

Edit: Hab grad noch was gesehen und korrigiert: int = integer , int* = ^integer. Also nicht GetItem(int *), du wirst kaum einen Zeiger auf ein Int übergeben wollen. Gäbe aber sicher schöne Exceptions :)

messie 19. Jan 2006 13:36

Re: Verwenden von property in C++ Builder
 
Zitat:

Hoffe, es war halbwegs verständlich :gruebel:
Naja,
ist schon etwas ungewohnt, die Sternchen an die richtige Stelle zu setzen, mache halt sonst nur Delphi..

Zitat:

Edit: Hab grad noch was gesehen und korrigiert: int = integer , int* = ^integer. Also nicht GetItem(int *), du wirst kaum einen Zeiger auf ein Int übergeben wollen. Gäbe aber sicher schöne Exceptions :)
Der Compiler hatte es aber gemerkt, leider ist die Anzeige der Fehlerposition bei weitem nicht so gut wie im Delphi - erinnert ein wenig an TP-Zeiten.

Hänge leider gleich an der nächsten Stelle: Das Erzeugen und Füllen der Objectlist mache in einer anderen Unit mit
Delphi-Quellcode:
TParas *Test;
Test = new TParas;
Test->Add(new TParaLine);
/*Linker meckert: [Linker Error] Unresolved external '__fastcall TParas::GetItem(int)' referenced from (...).OBJ
                  [Linker Error] Unresolved external '__fastcall TParas::SetItem(int, TParaLine *)' referenced from (...).OBJ */
Wenn ich die Zeile weglasse, in der Test erzeugt wird, ist der Linker zwar still, im Betrieb bekomme ich dann natürlich eine Zugriffsverletzung. Mir ist aber nicht klar, wo der Zusammenhang zu GetItem und SetItem beim Erzeugen ist.

Grüße, Messie

Der Jan 19. Jan 2006 14:11

Re: Verwenden von property in C++ Builder
 
Auf Anhieb sehe ich den Fehler jetzt auch nicht. Falls du dich bis heut abend gedulden kannst, poste ich dir mal ne Klasse für ne getypte Liste. Hab den BCB (und meine Sourcen) nur zuhause. Auf Arbeit muß ich Delphi...

Zitat:

Zitat von messie
Der Compiler hatte es aber gemerkt, leider ist die Anzeige der Fehlerposition bei weitem nicht so gut wie im Delphi - erinnert ein wenig an TP-Zeiten.

Im Gegenteil. Die Anzeige ist genauer. C/C++ ist viel freier als Pascal und der Compiler meckert erst dort, wo dann wirklich ein Fehler auftritt bzw. wo sich dein Fehler dann als solcher bemerkbar macht. Läßt sich schlecht erklären ohne einen Exkurs in die Tiefen von C++ zu unternehmen.

Ich würde dir im übrigen empfehlen, mal einen Blick auf die STL Container-Klassen zu werfen. Mit vector, deque oder aber list läßt sich sowas viiiieeel einfacher und effektiver realisieren als mit VCL-TList u.ä. Und wenn du deine Liste nicht unbedingt an eine VCL-Funktion übergeben mußt, die diesen Typ verlangt, solltest du den Weg über die STL auf jeden Fall vorziehen.

Code:
vector<TParaLine *> paras;
//...
paras.push_back(new TParaLine);
//...
//Zugriff z.B. über paras[i]

messie 19. Jan 2006 14:28

Re: Verwenden von property in C++ Builder
 
Zitat:

Auf Arbeit muß ich Delphi...
Gibt bestimmt Schlimmeres!
Ich hab' zum letzten mal vor über 10 Jahren mit C zu tun gehabt - da bin ich nie richtig reingekommen. Ist schon klar, das es mehr Freiheiten bietet aber das bedeutet auch daß man mehr wissen muß. Und für mein Projekt (Modifizieren eines kleinen Programms mit VCL-Komponenten) lohnt sich der tiefere Einstieg erstmal nicht. In meinem Bereich wird auch eher LabView immer wichtiger :kotz:
Ich warte also lieber bis heute abend...

Grüße, Messie

Der Jan 20. Jan 2006 09:44

Re: Verwenden von property in C++ Builder
 
Uh, sorry :oops: Jetzt fällt mir glatt ein was ich vergessen hab.... Heut abend denk ich dran...

messie 20. Jan 2006 11:29

Re: Verwenden von property in C++ Builder
 
Super.
Ich habe auch noch nicht weiter recherchiert weil ich gegen meinen Rechner kämpfe. Habe den ganzen vormittag gebraucht um die Elkos am Spannungsregler auszutauschen - auch was Schönes. Scheint aber jetzt zu laufen, CPU-Temperatur liegt 10 Grad unter dem Wert von gestern...

Grüße, Messie

Der Jan 20. Jan 2006 22:37

Re: Verwenden von property in C++ Builder
 
Soooo. Hab zwar nicht genau das gefunden, was ich posten wollte, aber etwas ähnliches. Erstmal der Source. Ist schon paar Jahre alt, nicht wirklich optimal, sollte aber das Prinzip zeigen.
Die Liste selbst ist allerdings nicht von TObjectList abgeleitet, wie man sieht. Hab noch paar Kommentare eingefügt...

Code:
// in .h

//Die Listenelemente sind von dieser Klasse
class TServer          
{
public:
    AnsiString asURL;
    AnsiString asLocation;

    __fastcall TServer();
    __fastcall TServer(AnsiString asDesc);
};
//---------------------------------------------------------------------------
class TServerList          //die Listeklasse als solches...
{
private:
    TList *pList;
protected:
//darf man: der Funktionsrumpf direkt in der Definition, da es keine wirkliche Trennung
//zwischen interface und implementation gibt, wie in Pascal
    int __fastcall GetCount() {return pList->Count;};
public:
    __fastcall TServerList();     //Konstruktor
    __fastcall ~TServerList();    //Destruktor

    TServer *GetItem(int iIndex);

//Die Methoden entsprechen denen der TList Klasee der VCL, man könnte noch mehr
//implemtieren, wie Exchange oder so, hab ich aber nicht gebraucht.
    int  __fastcall Add(TServer *pSite);
    void __fastcall Delete(int iIndex);
    void __fastcall Clear();
    int  __fastcall IndexOf(AnsiString asSearch);
    int  __fastcall Load();
    int  __fastcall Save();

    __property int Count = {read = GetCount};
    __property TServer *Item[int iIndex] = {read = GetItem};
};
Code:
//in .cpp
__fastcall TServer::TServer()
{
    asURL = "";
    asLocation = "";
}
//---------------------------------------------------------------------------
__fastcall TServer::TServer(AnsiString asDesc)
{
    int iPos = asDesc.Pos(";");
    if(iPos == 0)
    {
      asURL = asDesc;
      asLocation = "???";
    }
    else
    {
      asURL = asDesc.SubString(1, iPos - 1);
      asLocation = asDesc.SubString(iPos + 1, asDesc.Length() - 1);
    }
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
__fastcall TServerList::TServerList()
{
    pList = new TList;
}
//---------------------------------------------------------------------------
__fastcall TServerList::~TServerList()
{
    if(pList)
    {
      for(int i = pList->Count - 1; i >= 0 ; i--)
      {
//Ein Type-casting. TList->Items gibt TObject* (also ein Zeiger auf TObject) zurück,
//wir brauchen für die Freigabe aber TServer*
        delete (TServer *)(pList->Items[i]);
        pList->Delete(i);
      }
      delete pList;
      pList = NULL;
    }
}
//---------------------------------------------------------------------------
int __fastcall TServerList::Add(TServer *pSite)
{
    return pList->Add(pSite);
}
//---------------------------------------------------------------------------
void __fastcall TServerList::Delete(int iIndex)
{
    if(iIndex >= pList->Count)
      return;
    delete (TServer *)(pList->Items[iIndex]);
    pList->Delete(iIndex);
}
//---------------------------------------------------------------------------
void __fastcall TServerList::Clear()
{
    //Liste von hinten löschen
    for(int i = pList->Count - 1; i >= 0; i--)
    {
      delete (TServer *)(pList->Items[i]);
      pList->Delete(i);
    }
}
//---------------------------------------------------------------------------
int __fastcall TServerList::IndexOf(AnsiString asSearch)
{
    for(int i = 0; i < pList->Count; i++)
      if(asSearch == GetItem(i)->asURL)
        return i;
    return -1;
}
//---------------------------------------------------------------------------
TServer * TServerList::GetItem(int iIndex)
{
    return (TServer *)(pList->Items[iIndex]);
}
//---------------------------------------------------------------------------

//Load und Save lass ich weg, tut hier nix zur Sache
Ich hoffe es nützt was. Wenn nicht, frag ruhig. Wenns nötig auch per PM
:)
Wenn du nicht gerade 100000 Listenelemente hast, kannst du die Klasse nutzen, für richtig große Listen/Vektoren etc. sollte man die VCL-Klassen beseite lassen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:47 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz