const_cast



  • Gibt es (welche?) Situationen, in denen ein const_cast sinnvoll ist?



  • Ja. Scott Meyer erklärt das in folgender Situation:

    class Foo
    {
    public:
    	const Bar& operator[](std::size_t i) const
    	{
    		const Bar& b = /*get i-th Bar object*/; // Annahme: aufwendig zu programmieren
    		return b;
    	}
    
    	Bar& operator[](std::size_t i)
    	{
    		const Foo& This = static_cast<const Foo&>(*this); // cast damit operator[]-const aufgerufen wird, ansonsten endlos Rekursion
    
    		const Bar& result = This[i];
    
    		return const_cast<Bar&>(result);
    	}
    }
    

    Intuitiv implementieren das viele genau andersrum, also den const-[] mithilfe des non-const-[] Operators. Meyers erklärt das in dem Kapitel ganz gut und vor allem auch warum.



  • Man kann das ohne const_cast lösen, falls das zu findende Element intern nicht unbedingt die const ness von this erbt.

    class Foo
    {
    public:
        const Bar& operator[](std::size_t i) const
        {
    		return find(i);
        }
    
        Bar& operator[](std::size_t i)
        {
    		return find(i);
        }
    
    private:
    
        Bar *m_root; //zum Beispiel
    
    	Bar &find(std::size_t i) const
    	{
    		/*get i-th Bar object*/; // Annahme: aufwendig zu programmieren
    	}
    }
    


  • Ich habs genau einmal benutzt um Funktionen einer älteren C-Library aufzurufen (libpng). Bei neueren Versionen wurde die API tatsächlich geändert und der Parameter ist jetzt const wie es sein sollte.



  • edit: Ah, das kommt davon, wenn man vergisst, seine Antwort, die man vor 'ner Stunde getippt hat, abzuschicken. sebi707 war jetzt schneller 🙂

    Eine andere Situation, in der ein const_cast sinnvoll ist, ist folgende:

    // Funktion einer C-Bibliothek, die Du gerne benutzen willst, aber
    // wo der Autor ein const "vergessen" hat.
    void lib_ausgabe(char* msg)  
    {
        // so lange wie hier *msg nicht verändert wird, ist alles OK
        puts(msg);
    }
    
    // C++ wrapper für die C lib
    inline void cpp_ausgabe(const char* msg)
    {
        lib_ausgabe(const_cast<char*>(msg));
    }
    
    int main()
    {
        cpp_ausgabe("hello world!");
    }
    


  • Skym0sh0 schrieb:

    Intuitiv implementieren das viele genau andersrum, also den const-[] mithilfe des non-const-[] Operators. Meyers erklärt das in dem Kapitel ganz gut und vor allem auch warum.

    Mal aus Neugierde (ich habe das Buch nicht): Wieso sollte man das so machen?



  • weil du sonst oft 2 Implementierungen hast: eine const einen non-const



  • Gast3 schrieb:

    weil du sonst oft 2 Implementierungen hast: eine const einen non-const

    Genau.

    Das Problem ist:
    Nehmen wir an, wir rufen aus dem konstanten operator[] den nicht-konstanten oeprator[] auf. Das geht aber nicht, weil wir nicht aus const-Methoden non-const Methoden aufrufen können.

    Also bleibt da der einzige Weg, indem wir das umgekehrt machen. Oder wir leben mit doppeltem Code(was wir eigentlich auch nicht wollen).
    Const wollen wir ja normalerweise nicht wegcasten, da es gefährlich sein könnte. Hier in dem Fall ist dem aber nicht so, da wir ja ein nicht-konstantes Objekt von vornerein haben, wo wir nur eine konstante Methode aufrufen, dessen Ergebnis wir wiederum von const befreien, was ja durch unsere Vorraussetzung legal ist.



  • Ah klar, das macht natürlich Sinn. Ich war irgendwie im Glauben es ginge um den const-Rückgabetyp und hab nicht daran gedacht, dass die gesamte Funktion const ist.


Anmelden zum Antworten