Konvertierung in Basisklassen-Objekt



  • 1)Kann es sein, dass die Methode GetBitmap() keine const Methode ist? Du darfst auf eine const referenz keine Methode anwenden, die diese Referenz veraendern koennte...

    2)Ein Kopierkonstruktor koennte evtl. helfen, wenn er das zu kopierende Objekt const laesst:

    CBitmapEx::CBitmapEx(const CBitmapEx& other) {}...
    
    //...
    
    CBitmapEx tmpBitMapEx(myObj->GetEmblem());
    bRetVal = tmpBitMapEx.GetBitmap(&bmpstruct);
    

    ein const_cast ginge vermutlich auch, ist in meinen Augen aber etwas "schmutzig" 😉



  • Oje, in die komplett falsche Richtung gedacht...

    Da ich an der Klasse, die GetEmblem() bereitstellt eigentlich nichts mehr ändern möchte, werde ich es mal über den Kopierkonstruktor probieren. Sollte ich daran scheitern, muss es halt der "schmutzige" Weg sein 😉

    Danke für die Antworten!



  • Nanuq schrieb:

    Oje, in die komplett falsche Richtung gedacht...

    Da ich an der Klasse, die GetEmblem() bereitstellt eigentlich nichts mehr ändern möchte, werde ich es mal über den Kopierkonstruktor probieren. Sollte ich daran scheitern, muss es halt der "schmutzige" Weg sein 😉

    Danke für die Antworten!

    Na - ich wüsste nicht, wie das scheitern sollte. Und wo doch, wüsste ich nicht, warum "der schmutzige Weg" dann funktionieren sollte. 😉

    Gruß,

    Simon2.



  • Möglicherweise stelle ich mich extrem blöd an, aber ich komme tatsächlich mit den beiden von euch angegebenen Lösungsmöglichkeiten nicht weiter.

    1.) Kopierkonstruktor für CBitmapEx
    Wie würde denn ein Kopierkonstruktor in diesem Fall aussehen?
    Normalerweise würde ich das so machen:

    CBitmapEx::CBitmapEx(const CBitmapEx& other)
     : CBitmap(other) // Initialisierung des Basisklassen-Subobjekts
    {
        // zusätzliche Member kopieren: entfällt hier
    }
    

    Wie schon gesagt, gibt es allerdings in CBitmap (und den anderen "Oberklassen") keinen Kopierkonstruktor, den ich in der Initialisierungsliste aufrufen könnte. (Weitere Membervariablen hat meine abgeleitete Klasse nicht).

    2.) const_cast<>
    Ich muss zugeben, dass ich mich nicht erinnern kann, den const_cast jemals verwendet zu haben. Aber wenn ich es richtig verstanden habe, müsste es sich damit doch folgendermaßen verhalten:
    Meine Methode

    GetEmblem()
    

    liefert const CBitmapEx&

    const_cast<CBitmapEx> (myObj->GetEmblem())
    

    sollte dann also ein CBitmapEx sein, da das const Attribut entfernt wurde.
    Demzufolge sollte die komplette Zeile dann so aussehen:

    bRetVal = const_cast<CBitmapEx>(myObj->GetEmblem()).GetBitmap(&bmpstruct);
    

    Mein Compiler meint dazu:
    error C2440: 'const_cast' : cannot convert from 'const CBitmapEx' to 'CBitmapEx'
    Conversion requires a constructor or user-defined-conversion operator, which can't be used by const_cast or reinterpret_cast

    Und wie ein solcher conversion-operator aussehen sollte, weiß ich dann auch wieder nicht...:(

    Ich bin versucht, das ganze ein extrem schlechtes Design dieser MFC-Klasse zu nennen, aber ich fange vorsichtshalber mal mit der Suche bei mir selbst an ;).

    Sollte mir hier allerdings jemand zustimmen, werde ich die Frage vielleicht noch einmal im MFC-Forum posten und hoffen, dass ich über einige MFC-Umwege vielleicht doch zum Ziel komme 😕


  • Mod

    Nanuq schrieb:

    aber ich fange vorsichtshalber mal mit der Suche bei mir selbst an ;).

    Ein gute Idee. const_cast kann nur für Pointer- und Referenz-casts benutzt werden. Mithin

    bRetVal = const_cast<CBitmapEx&>(myObj->GetEmblem()).GetBitmap(&bmpstruct);
    

    Das impliziert, dass const_cast niemals einen copy-ctor aufruft - was aber nichts mit dem Design der Klasse zu tun hat.



  • Tatsache, jetzt ist mein Compiler einverstanden :), danke!

    Mit dem schlechten Design meinte ich allerdings eigentlich die Klasse CBitmap, weil sie keinen Kopierkonstruktor bereitstellt...

    pumuckl schrieb:

    ein const_cast ginge vermutlich auch, ist in meinen Augen aber etwas "schmutzig" 😉

    ...und deswegen würde mich natürlich nach wie vor interessieren, ob bzw. wie in diesem Fall die Variante mit dem copy-ctor funktionieren würde.
    Weil ich es schon auch ein wenig unschön finde eine Referenz auf const zurückzugeben und nachher das const durch den cast wieder aufzuheben.

    CStoll schrieb:

    Als Lösung kannst du entweder deine GetEmblem() soweit ändern, daß sie eine nicht-konstante Referenz (oder ein Objekt per Kopie) zurückgibt

    Und ich meine mich zu erinnern irgendwo gelesen zu haben, dass man Objekte (d.h. keine Standarddatentypen) in Get-Methoden normalerweise per const & zurückgeben sollte (Kopie sparen)...



  • Da ich an der Klasse, die GetEmblem() bereitstellt eigentlich nichts mehr ändern möchte

    Der einzig saubere Weg wäre IMHO CBitmap::GetBitmap const zu machen. Blöderweise hat MS das bis jetzt nicht gemacht... *g*

    GetEmblem stattdessen zu ändern dass es einen non-const Referenz zurückgibt halte ich für einen Fehler, wieso auch, das Problem liegt ja bei CBitmap (eine Funktion die ganz klar KEIN Mutator ist ist nicht const -> Fehler, pöse).

    Ich würde hier also wahrscheinlich auch nen const_cast machen, und nen Kommentar dazuschreiben. CBitmap::GetBitmap verwendet intern bloss ::GetObject(), und mir wäre nicht bekannt dass ::GetObject an dem übergebenen Objekt was ändern darf.


  • Mod

    Sinnvoll wäre, GetBitmap zu überladen (als const Funktion) und den const_cast dort zu verstecken.



  • hustbaer schrieb:

    Der einzig saubere Weg wäre IMHO CBitmap::GetBitmap const zu machen. Blöderweise hat MS das bis jetzt nicht gemacht... *g*

    GetEmblem stattdessen zu ändern dass es einen non-const Referenz zurückgibt halte ich für einen Fehler, wieso auch, das Problem liegt ja bei CBitmap (eine Funktion die ganz klar KEIN Mutator ist ist nicht const -> Fehler, pöse).

    Na also! Auch wenn es mir eigentlich nicht weiterhilft, ist das doch genau das, was ich hören wollte 😃 -> schlechtes CBitmap-Design

    camper schrieb:

    Sinnvoll wäre, GetBitmap zu überladen (als const Funktion) und den const_cast dort zu verstecken.

    Dann sollte ich mir allerdings absolut sicher sein, dass CBitmap::GetBitmap() an dem übergebenen Objekt wirklich nichts ändert...
    Werde noch einmal zusehen, dass ich das sicherstellen kann.



  • camper schrieb:

    Sinnvoll wäre, GetBitmap zu überladen (als const Funktion) und den const_cast dort zu verstecken.

    Inzwischen habe ich das so umgesetzt.

    int CBitmapEx::GetBitmap(BITMAP* pBitMap) const
    {
    	return const_cast<CBitmapEx&>(*this).CBitmap::GetBitmap(pBitMap);
    }
    

    Da mich der Aufruf der Basisklassenmethode über den Punktoperator aber ein wenig irritiert (eigentlich irritiert mich der ganze Ausdruck ;)), wollte ich noch einmal absichern, ob das so korrekt ist.


Anmelden zum Antworten