boost::shared_ptr downcasten



  • Hi ihrs!

    Ich habe folgende Situation:
    Bei mir werden die Klassen "texture", "surface" und "sound" von der Klasse "resource" abgeleitet und ich möchte mir nun einen resourcen-Manager schreiben um diese Klassen zu verwalten und nicht für jede Resource einen eigenen Manager zu schreiben.

    Der kleinste gemeinsame Nenner aller Klassen ist "resource", daher einen resourcen-Manager. 🙂 Ich habe mir also gedacht, dass es eine "get"-Methode in diesem Manager gibt und er mir einen resource-shared_ptr wiedergibt (oder ich es per Template bestimme). Da der Manager jedoch nur "resource" sichert (in einer Map) und nicht alle Abkömmlinge (sollen ja in Zukunft neue hinzu kommen) müsste ich also downcasten zu dem Typ der gefordert wird und bei der Erstellung mit new erstellt wurde.

    Ein Up-Cast geht ohne Probleme, doch bei einem Downcast hagelt es fehler. Hier ein kleines Beispiel:

    // textur erstellen
        boost::shared_ptr<texture> tex1 (new texture ());
        // upcast (funktioniert)
        boost::shared_ptr<resource> res1 (tex1);
        // downcast (geht nicht)
        boost::shared_ptr<texture> tex2 (res1);
    

    Folgenden Fehler kommen

    1>c:\programme\boost\boost_1_35_0\boost\shared_ptr.hpp(212) : error C2440: 'initializing' : cannot convert from 'resource *const ' to 'texture *'
    1>        Cast from base to derived requires dynamic_cast or static_cast
    1>        e:\test\main.cpp(63) : see reference to function template instantiation 'boost::shared_ptr<T>::shared_ptr<resource>(const boost::shared_ptr<resource> &)' being compiled
    1>        with
    1>        [
    1>            T=texture
    1>        ]
    1>c:\programme\boost\boost_1_35_0\boost\shared_ptr.hpp(212) : error C2439: 'boost::shared_ptr<T>::px' : member could not be initialized
    1>        with
    1>        [
    1>            T=texture
    1>        ]
    1>        c:\programme\boost\boost_1_35_0\boost\shared_ptr.hpp(475) : see declaration of 'boost::shared_ptr<T>::px'
    1>        with
    1>        [
    1>            T=texture
    1>        ]
    

    Also hab ich mal geguckt und folgendes probiert:

    // textur erstellen
        boost::shared_ptr<texture> tex1 (new texture ());
        // upcast (funktioniert)
        boost::shared_ptr<resource> res1 (tex1);
        // downcast ("funktioniert")
        boost::shared_ptr<texture> tex2 ((texture*)res1.get ());
    

    Ja es ist ein very bad cast von res1 auf tex2, doch der Inhalt stimmt. Jedoch wird der Zähler von tex1 nicht inkrementiert und tex2 fängt wieder bei 1 an zu zählen, wodurch ich das shared_ptr ordentlich "ausgehebelt" habe, da get den "echten Zeiger" wiedergibt.

    Also keine Hilfreiche Lösung.

    Auch ein direkter Cast geht nicht:

    // textur erstellen
        boost::shared_ptr<texture> tex1 (new texture ());
        // upcast (funktioniert)
        boost::shared_ptr<resource> res1 (tex1);
        // downcast (geht nicht)
        boost::shared_ptr<texture> tex2 ((boost::shared_ptr<texture>)res1);
    

    und wird mir gedankt mit folgendem Fehler:

    1>c:\programme\boost\boost_1_35_0\boost\shared_ptr.hpp(212) : error C2440: 'initializing' : cannot convert from 'resource *const ' to 'texture *'
    1>        Cast from base to derived requires dynamic_cast or static_cast
    1>        e:\test\main.cpp(66) : see reference to function template instantiation 'boost::shared_ptr<T>::shared_ptr<resource>(const boost::shared_ptr<resource> &)' being compiled
    1>        with
    1>        [
    1>            T=texture
    1>        ]
    1>c:\programme\boost\boost_1_35_0\boost\shared_ptr.hpp(212) : error C2439: 'boost::shared_ptr<T>::px' : member could not be initialized
    1>        with
    1>        [
    1>            T=texture
    1>        ]
    1>        c:\programme\boost\boost_1_35_0\boost\shared_ptr.hpp(475) : see declaration of 'boost::shared_ptr<T>::px'
    1>        with
    1>        [
    1>            T=texture
    1>        ]
    

    Hat jemand eine Idee wie ich das Problem lösen kann?


  • Mod

    boost::shared_ptr<resource> res1 (boost::dynamic_pointer_cast<resource>(tex1));
    


  • oh mein gott ihr seid so gut! Danke es geht und der Referenzzähler ist auch richtig, ich liebe euch 🙂


Anmelden zum Antworten