Problem mit dynamischen Fenstern



  • Hallo

    Wenn beim konkreten Einsatz eines Templates die Implementation des Templates fehlt, kommt der Linker-Fehler den du ja schon kennst. Der Compiler kann nämlich erst beim konkreten Einsatz des Templates aus der Implementation des Template eine konkrete Funktion zusammensetzen, nach Übersetzung von Markos und Templates darf es nur noch exakt festgelegte Datentypen geben. Wenn du also dein CreateKomp-Template in deinem gesamten Projekt für insgesamt 3 verschiedene Datentypen spezifizierst, sind nach dem Kompilieren dann drei verschiedene Funktionen vorhanden, und das Template ist verschwunden.
    Kann der Compiler aber das deklarierte Template für einen konkreten Einsatz nicht auflösen kann weil die Implementation fehlt, merkt das der Linker und bricht ab. (Warum nicht gleich der Compiler den Fehler findet und abbricht ist mir jetzt auch nicht klar)

    bis bald
    akari



  • akari schrieb:

    Kann der Compiler aber das deklarierte Template für einen konkreten Einsatz nicht auflösen kann weil die Implementation fehlt, merkt das der Linker und bricht ab. (Warum nicht gleich der Compiler den Fehler findet und abbricht ist mir jetzt auch nicht klar)

    Weil du etwa eine explizite Template-Spezialisierung durchaus in einer anderen Quelldatei unterbringen kannst.



  • Hallo,
    ja, das klingt logisch. Ich verstehe dann nur nicht, warum ich die template Funktionen nicht mit dem Schlüsselwort "inline" versehen kann und sie dann auch in die .cpp Datei schreiben kann.

    edit: Mir ist noch eine Frage aufgekommen, die ich euch gerne stellen möchte.

    Wenn ich nun auf mein dynamisches Forumal ein Label setzen, dann kann ich darauf zugreifen, indem ich den Rückgabetyp von CreateKomp nutze. Also so:

    TLabel *label = f.CreateKomp<TLabel>(10,10,f.width-40,200,"");
     label->AutoSize = false;
    

    Wenn ich nun jedoch auf das Formular zugreifen möchte, dann habe ich ein Problem. Dieses erstelle ich nämlich im Konstruktor:

    TCreateForm f (0,Form1->Width/2,Form1->Height/2,400, 350, clHighlight, "Hello");
    

    Da ein Konstruktor keinen Rückgabetyp hat, kann hier nicht so arbeiten wie bei CreateKomp. Wie könnte ich dennoch auf das dynamisch erstelle Formular zugreifen? Führt nichts um eine Methode herum, die das Formular erstellt? Ich finde es nämlich schöner, wenn die Form im Konstruktor gemacht wird.

    Vielen Dank für eure Hilfe
    lg, freakC++



  • ...gelöscht...



  • Hallo

    freakC++ schrieb:

    Hallo,
    ja, das klingt logisch. Ich verstehe dann nur nicht, warum ich die template Funktionen nicht mit dem Schlüsselwort "inline" versehen kann und sie dann auch in die .cpp Datei schreiben kann.

    Soweit ich weiß, sollte laut C++ Standard mit dem Schlüsselwort export genau das funktionieren, aber die meisten Compiler (auch der von Borland) unterstützen das nicht. Für weitere Fragen zum Hintergrund solltest du aber besser mit einem neuen Thread im C++ Forum selber nachfragen.

    Da ein Konstruktor keinen Rückgabetyp hat, kann hier nicht so arbeiten wie bei CreateKomp. Wie könnte ich dennoch auf das dynamisch erstelle Formular zugreifen? Führt nichts um eine Methode herum, die das Formular erstellt? Ich finde es nämlich schöner, wenn die Form im Konstruktor gemacht wird.

    Doch ein Konstruktor hat einen Rückgabetyp, nämlich die erstellte Instanz. Ich verstehe dein Problem nicht. In deinem Beispiel-Code erstellt du zunächstmal keine dynamische Instanz, sondern eine statische (in der Variablen f). Und warum du f nicht nutzen können solltest oder warum du eine Funktion haben willst, verstehe ich auch nicht.

    bis bald
    akari



  • Hallo akari,
    aus einem geraden ebenfalls aktuellen Thread habe ich eine Idee bekommen: Ich möchte ein dynamisches Formular erstellen, darauf einen Button kleben und wenn dieser Button gedrück wird, soll nur das dynmische Formular geschlossen werden. Ich kann der OnClick Methode des Buttons nicht einfach "Close()" zuweisen, da sonst das ganze Programm geschlossen wird. Ich muss also einen Zeiger auf mein dynamisches Fenster übergeben.

    TButton *button = f.CreateKomp<TButton>(10,210,f.width-40,60,"Ok");
     button->OnClick = Button;
    
    ...
    void __fastcall TForm1::Button(TObject *Sender)
    {
     Close(): //Das ganze Programm würde geschlossen
    }
    

    Ich muss also der Methode Button meine dynamische Form übergeben. Da die Instanz "f" aber vom Typ TCreateKomp ist, kennt sie nicht "Close()". Daher muss ich erstmal die Form zurückgeben. Ich habe das dann so gelöst:

    TForm* GiveForm() //Member von TCreateForm
      {
       return form; //form ist das dynamisch erzeugte Formular
      }
    

    und dann:

    TButton *button = f.CreateKomp<TButton>(10,210,f.width-40,60,"Ende");
     TForm *form = f.GiveForm();
     button->OnClick = Button(Sender,form); //FEHLER!
    ...
    void __fastcall TForm1::Button(TObject *Sender, TForm *form)
    {
     form->Close():
    }
    

    Das geht aber nicht. Warum? Es sei "kein zulässiger Typ". Was muss ich hier machen?

    Ich hoffe, dass Du mein Problem verstehst.
    lg, freakC+



  • Hallo

    Du bringst da einiges durcheinander. Du kannst Eventmethoden nicht einfach um einen Parameter erweiteren, der Typ ist festgelegt. Sondern deine Close-Methode muß ein Member von TCreateForm sein.

    // CreateForm.h
    class TCreateForm : ...
    {
      public :
        void __fastcall CloseMe(TObject* Sender); // Manuell deklarieren
    }
    // CreateForm.cpp
    void __fastcall TCreateForm::CloseMe(TObject* Sender)
    {
      Close();
    }
    // Form1.cpp
    TButton *button = f.CreateKomp<TButton>(10,210,f.width-40,60,"Ende");
    button->OnClick = f.CloseMe;
    

    bis bald
    akari



  • Hallo,
    oh ja, da habe ich tatsächlich etwas durcheinander gebracht. Doch der Code funktioniert nicht ganz, da "Close()" auch in der Methode "CloseMe()" als Member von TCreateForm unbekannt ist, da TCreateForm nicht vom TForm abgeleitet ist.

    Nichtsdetotrotz dachte ich an diese Lösung:

    void __fastcall TCreateForm::CloseMe(TObject *Sender)
    {
     form->Close(); //form ist das dynamische Formular
    }
    

    form wurde ja im Konstruktor erstellt:

    TCreateForm::TCreateForm(TForm* parent, int i_left, int i_top, int i_width, int i_height, TColor clBack, String cap)
    {
     form = new TForm(parent); 
     ...
    }
    

    und ist in TCreateForm als private so deklariert:

    class TCreateForm
    {
     private:
      TForm *form; //die zu erstellende Form
    

    Hier die Zuweisung:

    void __fastcall TForm1::L_KB_hlpClick(TObject *Sender)
    {
     TCreateForm f (0,Form1->Width/2,Form1->Height/2,400, 350, clHighlight, "Hello");
     TButton *button = f.CreateKomp<TButton>(10,210,f.width-40,60,"Ok");
     button->OnClick = f.CloseMe;
    }
    

    Wenn ich jedoch auf den Button klicke, kommt eine Zugriffsverletzung. Das verstehe ich nicht, da es eigentlich mit der Zuweisung "form->Close()" keine Schwierigkeiten geben sollte

    Weißt Du da auch bescheid 🤡 ?
    lg, freakC++



  • f wird zerstört, wenn die Funktion und somit der Scope verlassen wird. Danach hast Du ein undefiniertes Verhalten...



  • Ach *gegendieWandlauf*....warum seh ich das nicht? Vielen Dank für den Hinweis. Jetzt läuft es natürlich! Super 👍

    Machts gut und liebe Grüße
    freakC++


Anmelden zum Antworten