if( dynamic_cast...(Sender) ) = Zugriffsverletzung?



  • Grüß Gott,

    ich habe in der FAQ den (hoffentlich) hilfreichen Beitrag zum Zugreifen auf den Sender gelesen, und dachte mir nun, ganz einfach bei mehreren buttons in einer menüleiste zum beispiel alle in einer funktion unterbringen zu können:

    if( dynamic_cast<TTBItem*>(Sender)->Checked ) // TTBItem ist ein Menüitem von externer Komponente

    ein TTBItem-Element besistzt 100% die Eigenschaft "Checked" ... wieso kommt bei dieser Abfrage eine Zugriffsverletzung?



  • Wahrscheinlich ist dein Sender nicht vom TypTTBItem. Das solltest du vor dem eigentlichen Zugriff auf die Eigenschaften und Methoden immer prüfen:

    TTBItem *tbi = dynamic_cast<TTBItem*>(Sender);
    if (tbi /* tbi existiert, Cast war erfolgreich */ && tbi->checked)
      // mach was
    


  • Du kannst es auch ganz einfach machen. Schreib die Routinen in die Function eines Buttons und binde dann alle Button in die Routine ein. Sowas macht man gern bei wenig Code bzw. um auch gleich das Gruppenverhalten zu regeln.



  • Omega-X: Rate mal, worum sich das Problem handelt? Ich will ja alle Elemente über eine Routine abhandeln, nur muss ich da eben mit Object* Sender arbeiten und das geht nicht!!!



  • vielleicht funktionierts damit:

    if( ((dynamic_cast<TTBItem*> )Sender)->Checked )
    

    oder auch nicht



  • Reichlich witzig, @ich_bin_verzweifelt. Wieso muß ich raten, wenn du verzweifelt bist? Fang bloß nicht auch diese fingerzeigerischen Töne an!!! Mir reicht's völlig von dem, was ich hier beinahe permanent zu lesen bekomm!!!

    Zu deiner gnädigen Info, sowas caste ich normalerweise nicht.

    TControl * oTmpControl = (TControl *)Sender;

    Sonst noch Fragen? Vielleicht noch die eine, warum diese Komponente möglicherweise einiges Standardverhalten nicht unterstützt?

    Aber ich glaub, langsam kapier ich, was du versuchst. Der CheckButton war vielleicht mal irgendwann gecheckt worden. Jetzt ist er nicht Sender. Das Control, in dem du grad arbeitest, ist Sender. Daher die Zugriffsverletzung. Der Operator && könnte das möglicherweise klären. Dann passiert eben einfach nichts.

    (Hier) nicht: if (Sender == myButton) //gefahrlos, aber hilft hier nicht
    sondern: if (myButton->Checked) // eine Zustandsabfrage

    Nichts erzwingen wollen, was nicht funktionieren darf.

    <edit>Sowas eignet sich auch wunderbar für eine switch case Routine.



  • @Omega-X

    Vielleicht ist ja auch was dran an den "Anfeindungen der Anderen" 😮

    @ich_bin_verzweifelt

    dynamic_cast hat die tolle Eigenschaft, das der Zeiger NULL ist falls der Cast nicht erfolgreich durchzuführen war. Wenn man dann auf die Speicheradresse NULL zugreifen will, führt das natürlich zu einer Exception.

    goto Jansen



  • Original erstellt von F98:
    goto Jansen

    *kopfschüttel* F98, goto is evil! (-;

    -junix



  • @junix

    Irre ich, oder steckt nicht in einer Switch-Anweisung ein verkapptes Goto? :p



  • Du irrst (:

    -junix



  • Warum?



  • @F98, switch verhält sich grundsätzlich wie if, ist nur die elegantere Schreibweise - wenn es in der Situation einsetzbar ist. Die case-Zweige werden der Reihe nach durchlaufen. An das break gelangt die Routine nur, wenn eine Bedingung true war. Die Ausführung geht dann zurück auf den übergeordneten Block/in die Function. Kein Sprung also sondern eine Abkürzung des Durchlaufs, wenn die Arbeit bereits erfolgreich war.

    Zu den Anfeindungen und Zeigefingern, beides versteh ich sowieso nicht. Mein Gesprächspartner ist selbst groß und selbst frei. Er ist wahlfrei zu lernen. Er kann ersatzweise aber auch den eigenen Zeigefinger gegen die eigene Stirn richten. Gesund ist/bleibt, wem bei sich selbst die richtige Mischung gelingt. 😃

    Bin ich Kuli? Ist es meine höchste niedere Aufgabe, anderen in der Nase rumzupopeln? 🙄 Wenn ich mich am liebsten mit würdigen Gesprächspartnern unterhalte, soll ich diese und mich als stark und würdig verstehen lernen.

    Unwissenheit, Irrtum, Brett vor dem Kopf, dummes Gelaber liegen sehr nah beieinander. Wer kann immer die Wahrheit kennen? Wer über andere den Stab bricht, macht sich selbst zum Popanz.



  • Original erstellt von <Omega-X>:
    Unwissenheit, Irrtum, Brett vor dem Kopf, dummes Gelaber liegen sehr nah beieinander.

    Halleluhja! 🙂

    Jetzt aber bitte keine goto/switch/case/if-Diskussion mehr, das hat nichts mit dem Thema des Threads zu tun. Bei Bedarf bitte einen entsprechenden Thread in "Rund um" beginnen.



  • Hallo euch allen, Diskussion scheint etwas abgerutscht zu sein. trotzdem habe ich mal alles versucht, was ihr als mögliche lösungen des problems dargestellt habt (einmal ohne dynamic-cast und einmal abprüfen, ob das auch wirklich existiert)...

    Code:

    TTBItem* tbi = (TTBItem *)Sender;
        if (tbi /* tbi existiert, Cast war erfolgreich */ && tbi->Checked)
        {
            WorkspaceWindow->Visible = true;
            TbWorkspace->Checked = true;
            ItemWorkspace->Checked = true;
        }
        if (tbi /* tbi existiert, Cast war erfolgreich */ && !tbi->Checked)
        {
            WorkspaceWindow->Visible = false;
            TbWorkspace->Checked = false;
            ItemWorkspace->Checked = false;
        }
    

    es kommt keine exception oder fehler mehr, aber die codes innerhalb der bedingungen werden nie erreicht! von daher wäre die logische konsequenz anzunehmen, dass tbi eben nicht existiert, ABER ES EXISTIERT UND IST VOM TYP TTBItem!!!!! Obwohl es eine externe Komponente ist, kann ich mir trotzdem nicht vorstellen, dass man keine allgemeinen instanzen ausgehend vom Sender erstellen kann (also TTBItem* tbi = (TTBItem *)Sender;) <-- Wieso sollte das bei einer externen Komponente nicht gehen, wenn diese über TTBItem verfügt (ein Menüitem)?



  • werte doch mal den Sender aus.
    Gehe mal mit dem Debugger durch dein Programm und untersuche dann den Sender hinsichtlich des Classname's.
    Dadurch weisst du dann, welches Objekt dein Ereignis ausgelöst hat.



  • Und die Prüfung funktioniert nur mit dynamic_cast, ein C-style cast ala (TTBItem 😉 tut es hier nicht!



  • switch verhält sich grundsätzlich wie if, ist nur die elegantere Schreibweise - wenn es in der Situation einsetzbar ist. Die case-Zweige werden der Reihe nach durchlaufen.

    Das ist nicht richtig.



  • Wer unbedingt noch weiter über switch-case diskutieren will soll einen eigenen Thread im Rund um die Programmierung-Forum eröffnen!

    Weitere Off-Topic-Beiträge werden kommentarlos gelöscht!

    -junix





  • @ich_bin_verzweifelt, ich versuch mir grad vorzustellen, wie du die Sache anfangen mütest, um den Code für den nächsten Button zu implementieren. Das wäre doch sicher die gleiche Abfrage? - Oder hab ich es total immer noch nicht verstanden? Dann sorry. -

    Kannst du die Button nicht innerhalb der Routine mit ihren Namen ansprechen?

    if (TTBItem1->Checked)
    ...
    if (TTBItem2->Checked)
    ...

    Sieht vielleicht altmodisch aus, arbeitet aber zuverlässig. Es gibt dann eben noch die Variante mit dem tempButton. Aber ansich würde ich hier versuchen, auf das casten zu verzichten.

    Mal ein Standardbeispiel für den Sinn vom casten:

    Du arbeitest in einer MDI zB. im Texteditor-Child. Nun triffst du eine Auswahl in einer Combobox mit der Hauptanwendung als Parent. Dein Child bleibt das ActiveMDIChild. Und doch kannst du es nur über casten ansprechen. Wenn du versuchst, die Werte direkt zuzuweisen und SelStart wieder zu setzen, erfolgt ohne das casten eine Exeption.

    In deiner Situation scheint erst mal keine Notwendigkeit für dynamic_cast zu bestehen. Beschreib doch vielleicht mal die Situarion. Befindet sich die Maus zB. in der Form der Button? Was klickt oder tut sie, wenn das Ereignis ausgelöst werden soll? So sollte eigentlich deutliches Licht in die Situation kommen können.


Anmelden zum Antworten