Gibt es hier eine Alternative zu reinterpret_cast?



  • Hallo,
    ich bin dabei Teile einer DBGridkomponente aus Delphi nach C++Builder2009 zu portieren. Dabei stoße ich immer wieder auf Umwandlungsprobleme, die in Delphi scheinbar reibungslos ablaufen.
    Seht Euch bitte die folgende Delphi-Funktion an und meine Übersetzung. Meine Umsetzung scheitert am cast von TEdit.
    Mit reinterpret_cast<TEdit>(ie)* kommt der Compiler zwar weiter, aber unwohl ist mir trotzdem, weil von dieser Konstruktion in allen mir bekannten C++Büchern abgeraten wird. Wie seht Ihr das?

    //Delphi:
    function myDBGrid.CreateEditor: TInplaceEdit;
    begin
      Result := inherited CreateEditor;
      with TEdit(Result) do
      begin
        Color := Self.Color;
        OnChange := EditChanged;
      end;
    end;
    
    //h
    class myDBGrid : public TDBGrid {
    typedef TDBGrid inherited;
    ...}
    
    //cpp
    TInplaceEdit* __fastcall myDBGrid::CreateEditor(void){
    TInplaceEdit* ie = inherited::CreateEditor();
      //TEdit* edit = dynamic_cast<TEdit*>(ie);   //geht nicht
      TEdit* edit = reinterpret_cast<TEdit*>(ie); //scheint zu gehen, wird aber nicht empfohlen!?
      edit->Color = this->Color;
      edit->OnChange = EditChanged;
      return(ie);
    }
    


  • Hallo

    Grundsätzlich ist das kein Problem von C++. Auch in Delphi wird von TInplaceEdit auf TEdit gecastet (with). Nur die Syntax ist in C++ eben anders.
    Das eigentliche Problem ist die VCL-Klassenhierachie. Denn TInplaceEdit ist nicht von TEdit abgeleitet, oder andersrum. Sondern die gemeinsame Basisklasse isr TCustomEdit. Das der dynamic_cast nicht geht, deutet schon auf diese Problematik hin. Der reinterpret_cast wird vom Compiler immer genommen, ist aber in diesem Fall strenggenommen ungültig und führt vom C++ Standard aus zu undefiniertem Verhalten. Das zur Laufzeit kein Fehler auftritt liegt nur daran, das TInplaceEdit und TEdit sich in dem einen Punkt, nämlich die Eigenschaften Color und OnChange, gleichen. TEdit muß verwendet werden, weil diese Eigenschaften bei TCustomEdit und TInplaceEdit nicht public sind.

    Also im Grunde ist es wirklich eine schlechte Lösung, du kannst nicht garantieren das diese Lösung immer unter allen Umständen funktioniert. Allerdings gibt es wohl keine bessere Lösung.

    bis bald
    akari



  • Die bessere Lösung wäre selber von TInplaceEdit abzuleiten und die Properties auf __published zu setzen.



  • Hallo

    Ja stimmt. Da habe ich nicht dran gedacht.

    bis bald
    akari



  • Vielen Dank für Eure Kommentierung.
    Habe es so, wie von @Th69 vorgeschlagen, gemacht.
    Zuerst TInplaceEdit abgeleitet und die gewünschten __properties auf published gesetzt. Über die temporäre Instanz TmyInplaceEdit ie werden die gewünschten Zuweisungen durchgeführt. Der Compiler nimmt das so an. Ein reinterpret_cast über TEdit ist dadurch überflüssig. Zuletzt wieder zurückcasten nach TInplaceEdit.

    class TmyInplaceEdit : public TInplaceEdit {
    typedef TInplaceEdit inherited;
    private:
    protected:
    public:
      __fastcall TmyInplaceEdit(TComponent* Owner);  //Konstruktor
    __published:
    //aus protected von TInplaceEdit	
      __property Grid;
    //aus protected von TCustomMaskEdit
      __property EditMask;
    //  ...
    //aus protected von TCustomEdit
    //  ...
      __property OnChange;
    //  ...
    //aus protected von TWinControl
      __property BevelEdges;
    //  ...
    //aus protected von TControl
    //  ...
      __property Color;
    //  ...	
    };
    
    //h
    class myDBGrid : public TDBGrid {
    typedef TDBGrid inherited;
    ...}
    
    //cpp
    TInplaceEdit* __fastcall myDBGrid::CreateEditor(void){
    TmyInplaceEdit* ie = dynamic_cast<TmyInplaceEdit*>(inherited::CreateEditor());
      ie->Color = this->Color;
      ie->OnChange = EditChanged;              //EditChanged ist Member aus myDBGrid
      return(dynamic_cast<TInplaceEdit*>(ie)); //zurückcasten;
    }
    

Anmelden zum Antworten