geht sowas in c++?


  • Mod

    da in java alle klassen polymorph sind, stellt das keine verschlechterung dar. und nein, es gibt keine möglichkeit, es sei denn Base1 ode Base2 haben irgendwein eigenes interface für einen derartigen übergang.



  • camper schrieb:

    da in java alle klassen polymorph sind, stellt das keine verschlechterung dar.

    hab ich versucht, Base1 eine virtuelle funktion verpasst, geht aber nicht 😞
    es wird compiliert, aber der cast scheint nicht zu klappen (gibt immer false zurück)
    ich poste hier mal nen java code der sowas macht:

    interface I1 {}
    interface I2 {}
    
    class C1 implements I1 {}
    class C2 implements I1, I2 {}
    
    public class Ftest 
    {
    	public static boolean is_derived_from_I2 (I1 x)
    	{
    		return x instanceof I2;	
    	}
    
    	public static void main (String[] args) 
        	{
    		C1 c1 = new C1();
    		C2 c2 = new C2();
    
    		System.out.println(is_derived_from_I2(c1)); // false   	
    		System.out.println(is_derived_from_I2(c2)); // true   	
    	}
    }
    

    wie würde man sowas in c++ machen?



  • Alexandrescu hat in modern c++ design sowas gebastelt, musst du mal in seiner loki-lib (gibts auf sourceforge.net) suchen



  • Das was dir camper gesagt hat, ist doch sozusagen das instanceof von Java. Du kannst damit das gleiche erreichen. Anstatt das ein true oder false zurück kommt, kommt halt ein ungültiger oder gültiger Pointer (bei Referenzen wird eine Exception geworfen).

    Wenn es bei dir zur Laufzeit nicht funktioniert, obwohl das objekt polymorph ist, hast du vielleicht kein RTTI in deinem Compiler eingeschaltet?



  • Artchi schrieb:

    Wenn es bei dir zur Laufzeit nicht funktioniert, obwohl das objekt polymorph ist, hast du vielleicht kein RTTI in deinem Compiler eingeschaltet?

    doch, rtti ist aktiv. ohne rtti crashed das dynamic_cast. irgendwie geht's nicht bei mir. ich benutze visual studio 2002...


  • Mod

    class Base1 { public: virtual ~Base1() {} };
    

    sonst wie im ersten post. wenn es damit nicht geht, ist dein compiler kaputt.



  • camper schrieb:

    class Base1 { public: virtual ~Base1() {} };
    

    sonst wie im ersten post. wenn es damit nicht geht, ist dein compiler kaputt.

    ich hab jetzt folgenden code in dev-cpp getestet

    #include <iostream>
    #include <stdlib.h>
    
    class Base1 {public: virtual ~Base1() {} };
    class Base2 {};
    
    class A : public Base1 {};
    class B : public Base1, Base2 {};
    
    bool is_derived_from_Base2 (Base1 *x)
    {
        return dynamic_cast<Base2*>(x) != 0;
    }
    
    int main()
    {
        A *a = new A;
        B *b = new B;
    
        bool b1 = is_derived_from_Base2 (a);  // muss false ergeben
        bool b2 = is_derived_from_Base2 (b);  // muss true ergeben
    
        std::cout << b1 << ' ' << b2 << std::endl;
    }
    

    schmeisst bei mir 0 0 raus 😡
    rtti ist doch für gewöhnlich eingeschaltet beim gcc oder?
    (man muss es mit -fno-rtti abschalten wenn man's nicht haben will).



  • du brauchst mindestens eine virtuelle methode.



  • .w schrieb:

    du brauchst mindestens eine virtuelle methode.

    hab ich gerade gemacht

    class Base1 
    {
          public: 
          virtual ~Base1() {} 
          virtual void dummy() {}
    };
    

    ...ändert nix 😞 😞 😞


  • Mod

    class B : public Base1, [b]public[/b] Base2 {};
    


  • Dr. Prof schrieb:

    Alexandrescu hat in modern c++ design sowas gebastelt, musst du mal in seiner loki-lib (gibts auf sourceforge.net) suchen

    Das war aber iirc die Compiletime Variante, für die der eigentliche Typ schon bekannt sein muss.

    So klappts:

    #include <iostream>
    
    #include <FerrisLoki/TypeManip.h>
    
    using namespace Loki;
    
    class Base1 {};
    class Base2 { public: virtual ~Base2 () {} };
    
    class A : public Base1 {};
    class B : public Base1, public Base2 {};
    
    template <typename T, typename U>
    bool is_derived_from_impl (U* x, Int2Type<0>)
    {
        return false;
    }
    
    template <typename T, typename U>
    bool is_derived_from_impl (U* x, Int2Type<1>)
    {
        return dynamic_cast<T*> (x) != 0;
    }
    
    template <typename T, typename U>
    bool is_derived_from (U* x)
    {
        return is_derived_from_impl<T> (x, Int2Type<SuperSubclass<T, U>::value ? 1 : 0> ());
    }
    
    int main()
    {
        A* a = new A;
        B* b = new B;
    
        std::cout << is_derived_from<Base2> (a) << std::endl;  // muss false ergeben
        std::cout << is_derived_from<Base2> (b) << std::endl;  // muss true ergeben
    }
    

    /edit: Sorry, hatte campers Post nicht gesehen. Aber zumindest bei mir war der Rest der Änderungen auch nötig.


  • Mod

    allerdinsg ist

    Base1* c = new B;
        std::cout << is_derived_from<Base2> (c) << std::endl;  // ergibt false
    

    mit deiner variante, filmor. es ging ja gerade darum, einen cross-casts durchzuführen. im übrigen würde ich hier boosts is_convertible benutzen - ist schließlich das, was wir irgendwann im standard sehen werden.



  • Stimmt, aber ohne den Code oben hats bei mir nicht kompiliert. Loki hab ich nur verwendet, um auf Dr. Prof's Post näher einzugehen.


  • Mod

    .filmor schrieb:

    Stimmt, aber ohne den Code oben hats bei mir nicht kompiliert.

    Base1 ist bei dir auch nicht polymorph. das argument muss polymorph sein, nicht der zieltyp.



  • Autsch ... 😞



  • camper schrieb:

    class B : public Base1, [b]public[/b] Base2 {};
    

    hey, danke, das war's 🙂
    sorry, aber ich bin c-freak. bei c++ fehlt mir einfach die praxis...


Anmelden zum Antworten