Delphi Code Beispiel in CBuilder umsetzen



  • Tach.

    Ich habe mir eine XML Komponente geholt und möchte gern ein Delphi Beispiel in CBuilder umsetzen. Habe da aber ein verständnis Problem.

    //Attr ist eine StringList

    DELPHI
    CONSTRUCTOR TElementNode.Create (TheContent : STRING; TheAttr : TNvpList);
    ...
    Attr.Add (TNvpNode (TheAttr [i]).Name + '=' + TNvpNode (TheAttr [i]).Value);

    CBUILDER
    TElementNode(AnsiString TheContent, TNvpList *TheAttr)
    ...
    Attr->Add(TNvpNode(TheAttr->Items[i]).Name + "=" + TNvpNode(TheAttr->Items[i]).Value);

    FEHLERMELDUNG

    [C++ Fehler] Unit1.cpp(63): E2285 Keine Übereinstimmung für 'TNvpNode::TNvpNode(void )' gefunden
    [C++ Fehler] Unit1.cpp(63): E2459 Klassen im VCL-Stil müssen mit dem Operator new erstellt werden.
    [C++ Fehler] Unit1.cpp(63): E2459 Klassen im VCL-Stil müssen mit dem Operator new erstellt werden.
    [C++ Fehler] Unit1.cpp(63): E2294 Auf linker Seite der Struktur ist . oder .
    erforderlich.

    Ich werd aus dem Delphi Zeugs nicht ganz schlau. Er erwartet in TNvpNode() einen string, aber TNvpList welches drinsteht ist kein String.

    Falls wer das aufklären kann wäre echt toll. 🙄

    Delphi Source so aus:

    (*
      TNvpNode  = CLASS                     // Name-Value Pair Node
                     Name  : STRING;
                     Value : STRING;
                     CONSTRUCTOR Create (TheName : STRING = ''; TheValue : STRING = '');
                  END;
    
      TNvpList  = CLASS (TObjectList)       // Name-Value Pair List
                    PROCEDURE Add   (Node  : TNvpNode);
                    FUNCTION  Node  (Name  : STRING)  : TNvpNode;  OVERLOAD;
                    FUNCTION  Node  (Index : INTEGER) : TNvpNode;  OVERLOAD;
                    FUNCTION  Value (Name  : STRING)  : STRING;    OVERLOAD;
                    FUNCTION  Value (Index : INTEGER) : STRING;    OVERLOAD;
                    FUNCTION  Name  (Index : INTEGER) : STRING;
                  END;
    


  • Hallo

    Du must die Elemente einer StringList immer mit dem Pfeiloperator ansprechen. Vermutlich auch bei dem cast nach TNvpNode. Ich würde so in C++ umsetzen :

    TNvpNode* node = static_cast<TNvpNode*>(TheAttr [i]);
    Attr->Add (Node->Name + '=' + Node->Value);
    

    bis bald
    akari



  • Vielen vielen vielen Dank! Daran habe ich jetzt echt lang gesessen und du knallst die Lösung so hin 🙂

    Scheint zweierlei Dinge in CBuilder nicht zu funktionieren. Einmal das er Klassen direkt verarbeitet und Delphi benötigt scheinbar auch nicht die Items Eigenschaft bei Komponenten, sondern nur den Index.

    Hier nochmal etwas korrigiert, für die die es vielleicht nachvollziehen wollen:

    TNvpNode *node = static_cast<TNvpNode*>(TheAttr->Items[i]);
    Attr->Add (node->Name + '=' + node->Value);
    

    Jetzt habe ich aber gleich ne neue Frage 😉

    Diese bezieht sich auf das:
    EN := TElementNode.Create

    welches ich mit
    EN = new TElementNode

    mache. Frage ist, ist das so richtig?

    Falls ja, müsste ich nach der switch Abfrage ein "delete EN;" setzen.
    Mich wunderts nur, das in Delphi kein Free gemacht wird, daher glaube ich,
    das ich es falsch mache 🙄

    DELPHI

    VAR
        Node : TTreeNode;
        EN   : TElementNode;
      BEGIN
        WHILE XmlParser.Scan DO BEGIN
          Node := NIL;
          CASE XmlParser.CurPartType OF
            ptXmlProlog : BEGIN
                            Node := TrvDoc.Items.AddChild (Parent, '<?xml?>');
                            EN := TElementNode.Create (StrSFPas (XmlParser.CurStart, XmlParser.CurFinal), NIL);
    

    CBUILDER

    TTreeNode *Node;
        TElementNode *EN;
    
        while (XmlParser->Scan())
        {
            Node = NULL;
            switch (XmlParser->CurPartType)
            {
                ptXmlProlog :
                            Node = TrvDoc->Items->AddChild (Parent, "<?xml?>");
                            EN = new TElementNode(StrSFPas (XmlParser->CurStart, XmlParser->CurFinal), NULL);
                            Node->Data = EN;
                            break;
    


  • Ich bin doof, natürlich darf kein delete/free gemacht werden, sonst würd ich den Eintrag ja wieder löschen 🤡



  • Hallo

    Scheint zweierlei Dinge in CBuilder nicht zu funktionieren. Einmal das er Klassen direkt verarbeitet und Delphi benötigt scheinbar auch nicht die Items Eigenschaft bei Komponenten, sondern nur den Index.

    Was verstehst du unter direkt verarbeiten?

    Diese bezieht sich auf das:
    EN := TElementNode.Create

    welches ich mit
    EN = new TElementNode

    mache. Frage ist, ist das so richtig?

    Falls ja, müsste ich nach der switch Abfrage ein "delete EN;" setzen.
    Mich wunderts nur, das in Delphi kein Free gemacht wird, daher glaube ich,

    Ja die Übersetzung ist richtig. Das delete muß dann grundsätzlich auch an passender Stelle kommen. Allerdings vermute ich, das mit dieser Zeile

    Node->Data = EN;

    dafür gesorgt wird, das Node die Instanz in Data löscht, so das du nicht selber das delete machen must.

    bis bald
    akari



  • Danke 🙂

    Muss man dann eigentlich explizit bei Programmende TreeView->Items->Clear(); aufrufen um den Speicher "freizugeben" oder obliegt das der Programm Verwaltung selbst?



  • Verdammt ich war schon wieder zu schnell und habe eine Frage vergessen 🙄

    In der Original Quelle steht:

    im Konstruktor:
    INHERITED Create;

    und im Destruktor:
    INHERITED Destroy;

    Was genau macht das und was müsste ich im CBuilder dafür eintragen?

    CONSTRUCTOR TElementNode.Create (TheContent : STRING; TheAttr : TNvpList);
    VAR
      I : INTEGER;
    BEGIN
      INHERITED Create;
      Content := TheContent;
      Attr    := TStringList.Create;
      IF TheAttr <> NIL THEN
        FOR I := 0 TO TheAttr.Count-1 DO
          Attr.Add (TNvpNode (TheAttr [I]).Name + '=' + TNvpNode (TheAttr [I]).Value);
    END;
    
    DESTRUCTOR TElementNode.Destroy;
    BEGIN
      Attr.Free;
      INHERITED Destroy;
    END;
    


  • Was du vor dir stehen hast ist der Konstruktor und der Destruktor. Inhereted bedeutet, dass die Methode der Vorfahrklasse aufgerufen wird. Was an dieser Stelle auch logisch ist, denn in einem Konstruktor möchte man am Anfang die Methode der Vorklasse ausgeführt haben, in einem Destruktor dagegen der Destruktor der Vorfahrklasse zum Schluss aufgerufen.



  • Hallo

    Muss man dann eigentlich explizit bei Programmende TreeView->Items->Clear(); aufrufen um den Speicher "freizugeben" oder obliegt das der Programm Verwaltung selbst?

    Das macht das TreeView-Control schon alleine, wenn es selber gelösacht wird. Und das wird gelöscht wenn sein Owner, das Form gelöscht wird. Und das wird gelöscht, wenn die Anwendung geschlossen wird. Das alles unter der Annahme, das du die Verwaltung der Controls dem Objektinspektor überläßt bzw. die Owner manuell entsprechend setzt.

    In der Original Quelle steht:

    im Konstruktor:
    INHERITED Create;

    und im Destruktor:
    INHERITED Destroy;

    Was genau macht das und was müsste ich im CBuilder dafür eintragen?

    Das erste ist der Standardkonstruktor, das zweite der Destruktor.
    Arbeite am besten mal ein Tutorial zum Thema OOP in C++ durch, sonst kommst du nicht weiter.

    bis bald
    akari



  • Danke für eure Hilfe. Mit standard Klassen arbeite ich schon ne weile, aber dieses "INHERITED" war mir bisher nicht bekannt. Finde es auch nicht imk Tutorial.

    Verstehs aber immernoch nicht, da die Klasse nicht von einer anderen abgeleitet ist. Ich habe über google die Quelle sogar gefunden:

    http://www.koders.com/delphi/fidE30E3DCAE230F1189DEFB34F49907FEDC439837D.aspx

    Ab Zeile 95. Mein Problem ist nämlich das das TreeView immer nur die selbe Zeile ausgibt und ich wüsst jetzt gern obs an diesem "INHERITED" hängt oder doch ganz woanders dran. 🙄



  • Hallo

    Danke für eure Hilfe. Mit standard Klassen arbeite ich schon ne weile, aber dieses "INHERITED" war mir bisher nicht bekannt. Finde es auch nicht imk Tutorial.

    Nein das Wort findest du natürlich nicht in dem Tutorial. Denn das ist über Standard-C++, und das Wort ist Delphi-spezifisch.

    Ich kenn mich mit der Delphi-Syntax nicht sus, aber ich vermute das ohne Angabe einer Basisklasse dort alle Klassen von TObjekt abgeleitet sind, und deshalb sich das INHERIT auf den Destruktor von TObject beziehen.

    bis bald
    akari



  • Also etwas VCL spezifisches. Es besteht jetzt nur weiterhin die dumme Frage, ob dieses "inherited" irgendwie für mich relevant ist und falls ja wie das in CBuilder auszusehen hat 🕶

    Weil in der Function (184)
    "PROCEDURE TFrmMain.FillTree (XmlParser : TXmlParser);"

    welche ich für meinen CBuilder-Code umgeschrieben habe, nur '<?xml?>' im TreeView sehr oft aufgelistet wird und ich mich jetzt natürlich frage warum.

    Naja ich schau morgen nochmal frisch drauf, vielleicht fällt es mir dann wie Schuppen aus den Augen 😃


Anmelden zum Antworten