Casten erlaubt?



  • Folgendes:

    typedef T * (*Func) ();
    
    U * foo ()
    { ... }
    
    Func func = reinterpret_cast<Func>(foo);
    
    T * bar = func();
    

    Ist das standardkonform?



  • mein gefühl (nicht der standard! was der sagt weiss ich nicht) sagt mir, dass das geht. aber es sagt mir auch, dass da jede menge sprengstoff drinn steckt und man dabei die ganze typensicherheit über bord wirft.



  • Ups, es fehlt 'ne wichtige Information:
    U ist von T abgeleitet.



  • 5.2.10.
    punkt 6 (relativ wörtlich übersetzt)
    "ein zeiger auf eine funktion kann explizit (durch reinterpret_cast) in einen zeiger auf eine funktion anderen typs konvertiert werden. der effekt eines funktionsaufrufes einer funktion durch einen zeiger auf einen anderen funktionstyp als der bei der funktiondefinition der originalfunktion, ist undefiniert [...]"



  • Helium schrieb:

    Ups, es fehlt 'ne wichtige Information:
    U ist von T abgeleitet.

    dann kann die funktion doch eh einen zeiger auf U zurückgeben, ohne das man gleich die ganze funktion casten muss, auch wenn der rückgabetyp ein zeiger auf T ist. oder lieg ich da falsch?



  • Hallo,
    mal abgesehen davon, dass das Verhalten undefiniert ist:
    Bei einfacher Vererbung, wo die Adresse des Base-Objekts in der Regel gleich der Adresse des gesamten Objekts ist, wird das auf vielen Compiler wahrscheinlich sogar funktionieren. Spätestens bei Mehrfachvererbung ist dann aber auf jeden Fall schluss. Der reinterpret_cast führt keine Offsetverschiebung durch, das verspricht natürlich lustiges Chaos.
    Auf meinem Compiler reicht z.B. das:

    class A
    {
    public:
    	virtual ~A() {}
    };
    
    class B
    {
    public:
    	virtual ~B() {}
    };
    
    class U : public A, public B
    {
    public:
    };
    
    typedef B* (*Func)();
    
    U globalU;
    U* f() {return &globalU;}
    
    int main()
    {
    	A* a = &globalU;    // A-Teil hat selbe Adresse wie ganzes Objekt
    	B* b = &globalU;    // Offsetverschiebung
    	assert((void*)a == (void*)&globalU);
    	assert((void*)b != (void*)&globalU);
    
    	B* anotherB = reinterpret_cast<B*>(&globalU);
    	assert((void*) anotherB == (void*)b);	// UPS!
    
    	Func pF = reinterpret_cast<Func>(f);
    	b = pF();
    	assert((void*)b != (void*)&globalU);	// UPS!
    }
    

Anmelden zum Antworten