Frame, Mehrfachvererbung: Pointer zu Componenten NULL



  • Beim klicken des Buttons, als wenn ich von Form1 auf Funkionen von Frame2 zugrifen will, passiert es 😕

    Btw.: Mein OS: Vista



  • Ein Projekt mit einer Form und einem Frame darin erstellen.
    In den Frame ein Shape und in die Form ein Button.
    Jetzt mal als onClick-Anweisung des Buttons angeben: Frame2->Shape1->Top--;

    dann kommt die Verletzung (bei mir...)





  • Hallo,

    ich habe das mal eben mit BDS 2006 Professional ausprobiert und überhaupt keine
    Probleme gehabt.

    Ich bin folgendermaßen vorgegangen:
    1. Neues VCL-Projekt
    2. Neuen Frame innerhalb des Projekts mit 1 Button, 1 Label, 1 Edit
    3. Neue Header-Datei "IDummy.h" (s. unten)
    4. Frame von IDummy erben lassen
    5. Frame in Palette hinzufügen (lassen)
    6. Im Hauptformular Frame einfügen (MyFrame), außerdem 1 Button und 1 Memo
    7. Im Click-Ereignis des Buttons auf Frame-Komponenten zugreifen (s. unten)
    8. In der von IDummy geerbten Funktion foo() auf die Komponenten des Frames zugreifen (s. unten)

    Hier noch ein wenig Source-Code:

    IDummy.h

    #ifndef IDummyH
    #define IDummyH
    
    class IDummy
    {
       public:
          virtual void foo() = 0;
    };
    
    #endif
    

    Header-Datei des Frames

    //---------------------------------------------------------------------------
    
    #ifndef Unit2H
    #define Unit2H
    //---------------------------------------------------------------------------
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <Forms.hpp>
    
    #include <IDummy.h>
    //---------------------------------------------------------------------------
    class TFrame2 : public TFrame, public IDummy
    {
    __published:
       TButton *Button1;
       TLabel *Label1;
       TEdit *Edit1;
    public:
       __fastcall TFrame2(TComponent* Owner);
    
       virtual void foo();
    };
    //---------------------------------------------------------------------------
    extern PACKAGE TFrame2 *Frame2;
    //---------------------------------------------------------------------------
    #endif
    

    OnClick des Buttons auf Hauptformular

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
       IDummy* dummy = MyFrame;
       dummy->foo();
       Memo1->Lines->Add(MyFrame->Button1->Name + "::Caption = " + MyFrame->Button1->Caption);
       Memo1->Lines->Add(MyFrame->Label1->Name + "::Caption = " + MyFrame->Label1->Caption);
       Memo1->Lines->Add(MyFrame->Edit1->Name + "::Text = " + MyFrame->Edit1->Text);
    }
    

    Implementierung von IDummy::foo() im Frame

    void TFrame2::foo()
    {
       AnsiString componentProperties = "";
       componentProperties = Button1->Name + "::Caption = " + Button1->Caption + "\r\n"
                             + Label1->Name + "::Caption = " + Label1->Caption + "\r\n"
                             + Edit1->Name + "::Text = " + Edit1->Text;
       ShowMessage(componentProperties);
    }
    

    Keine Zugriffsverletzung, nichts um die Ohren geflogen.

    Ich habe auch mal eine Instanz des Frames dynamisch per Code erstellt. Auch
    keine Probleme.

    Irgendwas habt ihr wohl anders gemacht. Fragt sich bloß was.

    Gruß

    Alexander



  • hier mal das projekt, bei dem bei mir der fehler kommt:
    http://egaming-bonn.de/users/maze/moo.7z



  • Wie soll das funktionieren?
    Du verwendest nicht die Variable Deines Frames auf dem Formular,
    sondern die im Frame deklarierte globale Variable (die meiner Meinung
    nach standardmäßig nicht erstellt werden sollten).

    Header-Datei Deines Formulars:

    class TForm1 : public TForm
    {
    __published:
    	TFrame2 *Frame21; // <---------- Hier die Variable, die Du verwenden solltest
    	TButton *Button1;
    	void __fastcall Button1Click(TObject *Sender);
    public:
    	__fastcall TForm1(TComponent* Owner);
    };
    

    CPP Deines Formulars:

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    Frame2->Button1->Caption="test";  // <------- Falsch verwendet
    }
    

    Gruß

    Alexander



  • Erstes Interface:

    class IBla
    {
    	public:
      	virtual void machWas() = 0;
    };
    

    Zweites Interface:

    class IBlub
    {
    	public:
    		virtual void machMehr() = 0;
    };
    

    Frame 1:

    class TfrmOne : public TFrame, public IBla
    {
    __published:	// IDE-managed Components
    	TMemo *Memo1;
    	TLabel *Label1;
    	TEdit *Edit1;
    	TListBox *ListBox1;
    	TPanel *Panel1;
    private:	// User declarations
    public:		// User declarations
    	__fastcall TfrmOne(TComponent* Owner);
    	virtual void machWas();
    };
    

    Frame 2:

    class TfrmTwo : public TfrmOne, public IBlub
    {
    __published:	// IDE-managed Components
    	TListBox *ListBox2;
    	TRadioButton *RadioButton1;
    private:	// User declarations
    public:		// User declarations
    	__fastcall TfrmTwo(TComponent* Owner);
    	virtual void machMehr();
    };
    

    Frames mit paar Komponenten befüllen und auf ein Form knallen. Was kommt? Er kann die Klasse TfrmTwo nicht finden.

    Entferne ich nun ",public IBlub" von TfrmTwo, läuft das Programm einwandfrei. Entferne ich ",public IBla" von TfrmOne, aber ändere nichts an TfrmTwo, läufts auch. Anscheinend hat Borland Probleme sobald man bereits bei einem Parent Frame ein Interface implementiert hat und nun bei einem Child Frame ein anderes zusätzlich implementieren möchte.



  • ... was allerdings jetzt ein völlig anderes Problem als das eingangs beschriebene ist.
    Vielleicht komme ich heute abend mal dazu das nachzustellen.

    Gruß

    Alexander



  • Alexander Kempf schrieb:

    Wie soll das funktionieren?
    Du verwendest nicht die Variable Deines Frames auf dem Formular,
    sondern die im Frame deklarierte globale Variable (die meiner Meinung
    nach standardmäßig nicht erstellt werden sollten).

    Header-Datei Deines Formulars:

    class TForm1 : public TForm
    {
    __published:
    	TFrame2 *Frame21; // <---------- Hier die Variable, die Du verwenden solltest
    	TButton *Button1;
    	void __fastcall Button1Click(TObject *Sender);
    public:
    	__fastcall TForm1(TComponent* Owner);
    };
    

    CPP Deines Formulars:

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    Frame2->Button1->Caption="test";  // <------- Falsch verwendet
    }
    

    Gruß

    Alexander

    mit 2 forms geht das aber... warum nicht mit frame & form ??



  • maehze schrieb:

    mit 2 forms geht das aber... warum nicht mit frame & form ??

    Darüber solltest Du Dir mal in einer ruhigen Minute Gedanken machen.
    Kleine Denkanstöße:
    - Was bezweckt man eigentlich mit Frames?
    - Hast Du schon mal versucht 4 identische Forms auf einer Form im Designer abzulegen?

    Gruß

    Alexander



  • barristan schrieb:

    Er kann die Klasse TfrmTwo nicht finden.
    Entferne ich nun ",public IBlub" von TfrmTwo, läuft das Programm einwandfrei.

    Kann ich mit BCB2006pro nachvollziehen. In der Tat wird ordnungsgemäß kompiliert, aber zur Laufzeit
    wird die Klasse des vom ersten Frame erbenden Frames nicht gefunden.
    Wäre noch interessant herauszufinden, ob beim BCB2007 das Problem auch noch besteht.

    Glücklicherweise habe ich Frames noch nie in dieser Form verwenden müssen.

    Gruß

    Alexander



  • Das Problem besteht auch beim BCB2007. Ich denke man könnt den Fall mal bei QualityCentral reinstellen.



  • Braunstein schrieb:

    Das Problem besteht auch beim BCB2007. Ich denke man könnt den Fall mal bei QualityCentral reinstellen.

    Ja ja, man muss nur feste dran glauben, dass es hilft.
    Mein Bug-Report ist mittlerweile 6 Jahre alt. Passiert ist da allerdings überhaupt nichts...



  • Es geht mir ja nicht unbedingt darum, dass ich eine globale Variable des Frames durch desen Form ändere.
    Wenn ich versuche durch die Form eine Funktion des Frames aufrufen möchte, kommt ja das gleiche und es wäre doch sicherlich nicht falsch, wenn man durch den Frame auch auf ein paar Komponenten des Frames zufreifen kann ?!? (zB Frame2->Height)

    mfg, maehZe



  • Joe_M. schrieb:

    Passiert ist da allerdings überhaupt nichts...

    Im vorliegenden Fall könnte ich mir vorstellen, dass CodeGear auch nicht
    viel unternehmen wird. Wie wahrscheinlich ist es, dass Horden von Programmierern
    zwei Frames voneinander ableiten und jeweils mit einem "interface" verzieren.
    Da wird CodeGear eher das Risiko eingehen, dass sich im Jahr ein oder zwei
    Programmierer deswegen beschweren - wie vermutlich jede Firma, die begrenzte
    Ressourcen hat. Wir setzen bei unseren eigenen Produkten auch Prioritäten.

    Allerdings sind bei Borland/CodeGear in der Vergangenheit auch schon wichtiger
    Fehler nicht behoben worden.

    Gruß

    Alexander



  • maehze schrieb:

    Es geht mir ja nicht unbedingt darum, (...)

    Habe ich insgesamt überhaupt nicht verstanden. Kannst Du das für mich mal
    in einfacheres Deutsch übersetzen?

    Gruß

    Alexander



  • Also hat sich mein Anfangsverdacht doch bestätigt. Ich werde den Fehler auf jeden Fall melden, allerdings bleibt mir aus Zeitgründen sowieso nichts anderes übrig als die Frames anders zu programmieren.



  • barristan schrieb:

    Also hat sich mein Anfangsverdacht doch bestätigt.

    Nach meinem Verständnis ging Dein Anfangsverdacht in eine ganz andere Richtung (Null-Pointer bei
    einstufiger Mehrfachvererbung).
    Würde mich mal interessieren, was daraus eigentlich geworden ist. Das hat nämlich - soweit ich
    das überschauen kann - hier noch keiner offiziell bestätigen können.

    barristan schrieb:

    Ich werde den Fehler auf jeden Fall melden

    Solltest Du tun, obwohl ich befürchte, dass Joe_M. mit seiner schwarzseherischen Prognose
    recht behalten wird.

    Ich vermute, dass die ursprüngliche Intension von Frames nicht in die Richtung ging,
    wie Du sie jetzt verwendest. Wofür brauchst Du eigentlich diese Vererbungshierarchie,
    also Frame2 von Frame1 von TFrame und dann auch beide eigenen mit Mehrfachvererbung?
    Offenbar ist das ja kein künstlich konstruiertes Gerüst, das nur darauf abzielt,
    Fehler im BCB aufzuzeigen, sondern Du brauchst es wirklich.
    Kannst Du das nochmal in kurzen Worten erklären?

    Gruß

    Alexander


Anmelden zum Antworten