Instanz greift auf Instanz zu -> Zugriffsverletzung [gelöst]



  • Alternativ könntest Du dem dynmaischen Form einen aussagekräftigen Namen geben und über TApplication::Components iterieren um das gewünschte Form zu finden.



  • Braunstein schrieb:

    [...] Du kannst doch z.Bsp. im Konstruktor von TForm2 einen Zeiger auf TForm1 neben dem Owner mit übergeben und dort einer Membervariablen übergeben. [...]

    Ja, das habe ich schon versucht - das ist sicherlich auch das, was witte meint. Allerdings bekomme ich das nicht so recht hin...

    Für Form2 müsste das so aussehen:

    // .h:
    class TForm2 : public TForm
    {
    __published:
       // ...
    private:
    	TForm* pForm1;
    public:
    	__fastcall TForm2(TComponent* Owner, TForm* InstanzA);
    };
    
    // .cpp - Konstruktor:
    __fastcall TForm2::TForm2(TComponent* Owner, TForm* InstanzA)
    	: TForm(Owner)
    {
       pForm1= &InstanzA;
       //...
    }
    

    richtig?

    Dann müsste ich in der InstanzB-Funktion mit

    *pForm1->PublicVariable= Edit1->Text;
    

    die Variable von Instanz A ändern können, richtig?

    Nur, wie übergebe ich beim Instanziieren den Zeiger an den Konstruktor?



  • Na, indem Du einen weiteren Konstruktor anlegst:

    public:		// Anwender-Deklarationen
    	__fastcall TForm1(TComponent* Owner);
    	__fastcall TForm1(TComponent* Owner, TForm1* pCallingForm1);
    

    Den übergebenen Zeiger musst Du dann in einer Membervariablen speichern um ihn in anderen Methoden nutzen zu können. Im Standardkonstruktor solltest Du diese Membervariabel auf NULL setzen.



  • @Joe_M: Ok, ich muss also den Konstruktor überladen, das ist soweit klar. Allerdings verwirrt mich jetzt, dass du den Konstruktor von Form1 überladen hast. Ist das Absicht oder meintest du Konstruktor von Form2?

    Meine grosse Frage ist jetzt, wie ich den Zeiger richtig übergebe - sprich:

    void __fastcall TForm1::BtnInstBClick(TObject *Sender)
    {
        // ...
        if(...)
        {
            TForm2 *pInstanzB= new TForm2(0);                     // <==== !!!!
            // wird zu:
            TForm2 *pInstanzB= new TForm2(0, &pInstanzA);         // ????
            pInstanzB->Caption= " Geben Sie Dies und Das ein:";
            pInstanzB->BtnTest->Caption= "Test";
            pInstanzB->ShowModal();
            delete pInstanzB;
        }
        // ...
    }
    

    So?



  • Weiß nicht, hab den Überblick verloren. 😉 In welchem Form möchtest Du welche dynamische Forminstanz verwenden?



  • Prinzipiell richtig. Du solltest nur den Adressoperator weglassen. pInstanzA ist doch schon ein Zeiger.

    TForm2 *pInstanzB= new TForm2(0, pInstanzA);
    

    Damit das Löschen der Zeiger kein Problem mehr ist solltest du irgendwann mal was über Smartpointer lesen. Dann geht auch sowas.

    void __fastcall TForm1::BtnInstBClick(TObject *Sender)
    {
        // ...
        if(...)
        {
            std::auto_ptr<TForm2> pInstanzB(new TForm2(0, pInstanzA));
            pInstanzB->Caption= " Geben Sie Dies und Das ein:";
            pInstanzB->BtnTest->Caption= "Test";
            pInstanzB->ShowModal();
    //        delete pInstanzB; // delete kann jetzt entfallen
        }
        // ...
    }
    


  • Joe_M. schrieb:

    Weiß nicht, hab den Überblick verloren. 😉 In welchem Form möchtest Du welche dynamische Forminstanz verwenden?

    Bei mir ists auch gleich soweit mit dem Überblick 🙂
    * Ich erzeuge vom Hauptprogramm aus eine dynamische Forminstanz von Form1.
    * Von dieser dynamischen Forminstanz (Instanz A) aus erzeuge ich eine dynamische Forminstanz von Form2 (Instanz B).
    * Dann möchte ich in einer Methode von Instanz B schreibend auf eine public-Variable von Instanz A zugreifen.



  • Dann brauchst Du in Form2 einen Zeiger auf Form1.
    Siehe auch Braunsteins Post. Vermutlich hast Du aber an dieser Stelle die Variable pInstanzA nicht mehr, aber Du willst ja aus dem neuem Form2 auf die (dynamisch erzeugte) Instanz zugreifen, in der Du Dich gerade befindest (richtig?), dann kannst Du dort this übergeben.



  • Joe_M. schrieb:

    Dann brauchst Du in Form2 einen Zeiger auf Form1.
    Siehe auch Braunsteins Post.

    Genau.

    Joe_M. schrieb:

    Vermutlich hast Du aber an dieser Stelle die Variable pInstanzA nicht mehr...

    Naja, "nicht mehr" stimmt so nicht - pInstanzA ist eben scheinbar nur in der Klick-Methode des Hauptprogramms gültig, die ich ja mit pInstanzA->ShowModal() temporär verlasse.

    Joe_M. schrieb:

    ... Du willst ja aus dem neuem Form2 auf die (dynamisch erzeugte) Instanz zugreifen, in der Du Dich gerade befindest (richtig?)...

    Fast, aktuell befinde ich mich per ShowModal() in Instanz B (dynamische Instanz von Form2) und möchte auf Instanz A (vorher erstellte dynamische Instanz von Form1) zugreifen, welche ebenfalls aktuell noch mit ShowModal() angezeigt wird. Das geht aber einfach mit der Zeile in Instanz B

    pInstanzA->publicVariable= Edit1->Text;
    

    nicht (Zugriffsverletzung).

    Schema: Hauptprogramm ➡ Klick ➡ Erzeugen pInstanzA(Form1) ➡ ShowModal() ➡ Button-Klick auf pInstanzA ➡ Erzeugen pInstanzB(Form2) ➡ ShowModal() ➡ Button-Klick auf pInstanzB ➡ ändern von Public-Variable von pInstanzA

    Joe_M. schrieb:

    ...dann kannst Du dort this übergeben.

    Wo jetzt?

    Ich glaube ich habs schon halbwegs kapiert, Instanz B kennt halt Instanz A nicht, und deswegen brauch ich nen Zeiger auf Instanz A, den ich beim Erzeugen von Instanz B an den (überladenen) Konstruktor übergeben kann. Damit ich innerhalb Instanz B mit dem Zeiger arbeiten kann, muss ich den übergebenen Zeiger in eine Member-Variable von Instanz B packen und zwar im Konstruktor. Und da ist momentan noch mein Problem: Wie muss die Member-Variable aussehen, in die ich den Zeiger "packe"? Ist das eine public-Variable von Instanz B? Ist es ebenfalls ein Zeiger? Wenn ja, welchen Typ muss dieser "Member-Zeiger" haben? Und was "packe" ich in den hinein? Die Adresse? Ich raffs nicht...
    Hat mal einer nen Codeschnipsel bitte, wie das "Packen des übergebenen Zeigers in eine Member-Variable" im überladenen Konstruktor aussehen muss?

    Edit: Rechtschreibung 🙄



  • Kolumbus schrieb:

    Wie muss die Member-Variable aussehen, in die ich den Zeiger "packe"? Ist das eine public-Variable von Instanz B? Ist es ebenfalls ein Zeiger? Wenn ja, welchen Typ muss dieser "Member-Zeiger" haben? Und was "packe" ich den hinein? Die Adresse? Ich raffs nicht...

    Es sollte eine membervariable im private-Bereich von TForm2 sein. Der Typ wäre dann Zeiger auf TForm1.

    // .h:
    class TForm2 : public TForm
    {
    __published:
       // ...
    private:
        TForm1* pForm1;
    public:
        __fastcall TForm2(TComponent* Owner, TForm1* InstanzA);
    };
    
    // .cpp - Konstruktor:
    __fastcall TForm2::TForm2(TComponent* Owner, TForm1* InstanzA)
        : TForm(Owner), pForm1(InstanzA)
    { 
    }
    


  • Braunstein schrieb:

    Es sollte eine membervariable im private-Bereich von TForm2 sein. Der Typ wäre dann Zeiger auf TForm1.

    Schön, dann bin ich ja doch nich so doof - so hab ich mir das gedacht.

    Braunstein schrieb:

    // .cpp - Konstruktor:
    __fastcall TForm2::TForm2(TComponent* Owner, TForm1* InstanzA)
        : TForm(Owner), pForm1(InstanzA)
    { 
    }
    

    Das hat mir gefehlt, Danke - wird sofort getestet! 🙂



  • __fastcall TForm2(TComponent* Owner, TForm1*/**/ pInstanzA);
    

    [C++Fehler] 2.h(27): ) expected.

    Hilfe schrieb:

    Am Ende einer Parameterliste wird eine abschließende rechte Klammer erwartet.

    Is doch eine da??? 😕

    Edit: da wo ich die Kommentar-Zeichen gemacht habe, steht der Cursor bei der Fehlermeldung, falls das was zu bedeuten hat!?!



  • Ich schätze mal er kennt TForm1 nicht. Mach einfach mal eine Forwarddeklaration oben in der Headerdatei.

    class TForm1;
    


  • Na, haste denn den header von TForm1 in den header von TForm2 eingebunden?



  • Um den nächste Frage zu überspringen: Haste Include-Guards verwendet?



  • Den Header von Form1 habe ich in 1.cpp eingebunden... reicht das nicht?

    Und include-Guards hab ich standardmäßig drin in allen Headern, ja - aber is ja nicht relevant, weil #include "1.h" in 2.cpp steht.



  • Aber auch in 2.h?



  • Nein das reicht nicht. TForm1 muss auch im header bekannt sein wegen der Deklaration deines Konstruktors. Ich sagte ja schon, eine Forwarddeklaration von TForm1 reicht da.
    Include-Guards werden beim BCB sowieso standardmäßig erzeugt.



  • Ok, Danke für den Hinweis. Jetzt kann ich auch problems einen Zeiger vom Typ Form1 als private-Variable in 2.h deklarieren...

    Und was soll ich sagen Leute, es wäre zwar viel einfacher gewesen die Forms beim Programmstart zu erzeugen, aber wer wills schon einfach? Es funktioniert jetzt, also special thanks to: Braunstein, Joe_M und witte! Ihr seid Spitze 👍
    Schön, dass ihr nicht die Nerven verliert wenn man sich doof anstellt!
    Was ich Alles gelernt habe:

    * ich habe zum 1. Mal einen Konstruktor überladen
    * ich habe zum 1. Mal einen Zeiger an einen Konstruktor übergeben
    * ich habe zum 1. Mal Daten zwischen 2 dynamischen Form-Instanzen ausgetauscht
    * ich weiß jetzt, dass ich auch im Header ein #include setzen muss, wenn ich dort Objekte eines anderen Forms zugänglich machen will

    Das nur Mal so auf die Schnelle... Ich poste dann gleich mal noch das Ergebnis als Codeschnipsel!



  • Wenn du den Include wirklich im Header gestzt hast, dann nimm ihn doch probeweise wieder raus und befolge meinen Hinweis mit der Forwarddeklaration. Jetzt mag das für dich vielleicht noch keinen Unterschied machen aber glaube mir, bei größeren Projekten macht sich das bemerkbar.
    1. Du verringerst Abhängigkeiten
    2. Du erhöhst die Compilegeschwindigkeit


Anmelden zum Antworten