[portable typeID] gibt es sowas?



  • was genau meinst du mit selber machen?

    derzeit muss ich meine Klassen immer um folgende elemente erweitern, damit ich das creator template nutzen kann:

    class A{
    public:
    const static std::string objectTypeID;
    static A* create() { return new A(); }
    virtual std::string getObjectTypeID() { return A::objectTypeID; }
    
    };
    

    und eigentlich finde ich es etwas lästig. da wäre mir so eine "automatische" typerkennung recht lieb.



  • muffmolch schrieb:

    was genau meinst du mit selber machen?...

    Genau das, was Du da tust. 😃
    "Lästig" aber IIRC die einzige portable/zuverlässige Möglichkeit.
    Vielleicht wird das mit einem neuen Standard ja anders ....

    Gruß,

    Simon2.



  • oh man. ja, da kommt mal wohl nicht drum rum...
    jetzt wollte ich das irgendwie in ein Interface stecken.
    Das einzige, was mir noch Schwierigkeiten bereitet, ist die automatische typeID-Zuweisung des static const strings...



  • muffmolch schrieb:

    oh man. ja, da kommt mal wohl nicht drum rum...

    Ist halt eine Folge davon, dass in C++ eigentlich gar keine technischen Formate spezifiziert sind...
    Vielleicht ist man da mit der "Optimierungsmöglichkeit für Plattformen" ein wenig zu weit gegangen ... oder man hätte sich einen "ABI-" und einen "native-Modus" ausdenken können. Letztlich haben sie halt eine Programmiersprache spezifiziert und kein Programmierprodukt... aber ein wenig "Kompatibilität" hätte wohl gut getan (und wenn man nur fordert, dass typeid() auf allen Plattformen vergleichbare Ergebnisse liefert)....

    Gruß,

    Simon2.



  • Ja, ist wirklich an manchen Stellen etwas zu ungenau spezifiziert. Sowas wie den Aufbau einer ID hätte man tatsächlich vorgeben können. Ich denke auch, das niemand typeid benutzt, außer für Debug-Ausgaben oder um einen what-Exception-String etwas informativer zu gestalten. Funktional ist das Ding nutzlos.



  • Artchi schrieb:

    Ich denke auch, das niemand typeid benutzt, außer für Debug-Ausgaben oder um einen what-Exception-String etwas informativer zu gestalten. Funktional ist das Ding nutzlos.

    wieso? wenn man einen pointer auf die basisklasse hat und wissen will, wissen auf wen der wirklich zeigt, ist 'typeid' doch gut zu gebrauchen.
    🙂



  • pale dog schrieb:

    wieso? wenn man einen pointer auf die basisklasse hat und wissen will, wissen auf wen der wirklich zeigt, ist 'typeid' doch gut zu gebrauchen.
    🙂

    Ich gebe da Artchi Recht! Was net ( 😃 ) sagt deutet auf ein Design Fehler hin. Mach mir mal ein Beispiel mit typeId und ich mache daraus eins ohne 😉



  • KasF schrieb:

    Mach mir mal ein Beispiel mit typeId und ich mache daraus eins ohne 😉

    #include <iostream>
    #include <typeinfo>
    #include <vector>
    using namespace std;
    
    class B {public:virtual ~B(){}};
    class X : public B {};
    class Y : public B {};
    
    vector<B*> vec;
    
    int main()
    {
        int s;
        for (s=0; s<10; s++)
        {
            switch (rand()%3)
            {
                case 0:
                vec.push_back (new B);
                break;
    
                case 1:
                vec.push_back (new X);
                break;
    
                case 2:
                vec.push_back (new Y);
                break;    
            }
        }
    
        for (s=0; s<10; s++)
            cout << typeid(*vec[s]).name() << " -->\t" 
                 << (typeid(*vec[s])==typeid(B)) << '\t' 
                 << (typeid(*vec[s])==typeid(X)) << '\t'
                 << (typeid(*vec[s])==typeid(Y)) 
                 << endl;
    }
    

    😉



  • Ein Beispiel das auch Sinn macht, wo du auf unterschiedliche Typen unterschiedlich reagieren musst 😉



  • KasF schrieb:

    Ich gebe da Artchi Recht! Was net ( 😃 ) sagt deutet auf ein Design Fehler hin. Mach mir mal ein Beispiel mit typeId und ich mache daraus eins ohne 😉

    #include <typeinfo>
    #include <iostream>
    #include <limits>
    #include <string>
    using namespace std;
    
    template< class T >
    void bombensicher( T &a )
    {
    	string str = "Bitte geben Sie ";
    
    	if ( typeid( a ) == typeid( double ) )
    	{
    		str += "eine Zahl ein: ";
    	}
    
    	if ( typeid( a ) == typeid ( char) )
    	{
    		str += "ein Zeichen ein: ";
    	}
    
    	if ( typeid( a ) == typeid ( string ) )
    	{
    		str += "eine Zeichenkette ein: ";
    	}
    
    	cout << str;
    
    	while( !( cin >> a ) )
    	{
    		cin.clear();
    		cin.ignore(numeric_limits<streamsize>::max(),'\n'); 
    	    cout << endl << "Fehlerhafte eingabe! " << endl << str;
    	}
    
    	cin.ignore(numeric_limits<streamsize>::max(),'\n');
    }
    
    int main()
    {    
    	double	d = 0;
    	char	c = 0;
    	string  s ;
    
    	bombensicher( d );
    	cout << d << endl;
    
    	bombensicher( c );
    	cout << c << endl;
    
    	bombensicher( s );
    	cout << s << endl;
    
    	return 0;
    }
    


  • Ich habe das Gefühl es grübeln gerade viele Leute um es mir zu zeigen, dass meine Aussage nicht stimmt 🙂

    proggingmania schrieb:

    #include <typeinfo>
    #include <iostream>
    #include <limits>
    #include <string>
    using namespace std;
    
    template< class T >
    void bombensicher( T &a )
    {
    	string str = "Bitte geben Sie ";
    
    	if ( typeid( a ) == typeid( double ) )
    	{
    		str += "eine Zahl ein: ";
    	}
    
    	if ( typeid( a ) == typeid ( char) )
    	{
    		str += "ein Zeichen ein: ";
    	}
    
    	if ( typeid( a ) == typeid ( string ) )
    	{
    		str += "eine Zeichenkette ein: ";
    	}
    	
    	cout << str;
    
    	while( !( cin >> a ) )
    	{
    		cin.clear();
    		cin.ignore(numeric_limits<streamsize>::max(),'\n'); 
    	    cout << endl << "Fehlerhafte eingabe! " << endl << str;
    	}
    
    	cin.ignore(numeric_limits<streamsize>::max(),'\n');
    }
    
    int main()
    {    
    	double	d = 0;
    	char	c = 0;
    	string  s ;
    	
    	bombensicher( d );
    	cout << d << endl;
    	
    	bombensicher( c );
    	cout << c << endl;
    	
    	bombensicher( s );
    	cout << s << endl;
    
    	return 0;
    }
    

    Sowas würde kein C++ Programmierer schreiben, ein paar überladene Funktionen und gut is die Sache ...

    Vllt nen schönes OO - Beispiel, wo jemand denkt er käme ohne typeid nicht aus.

    (hoffentlich habe ich mir nicht selber ne Grube gegraben 🙂 )



  • KasF schrieb:

    Ein Beispiel das auch Sinn macht, wo du auf unterschiedliche Typen unterschiedlich reagieren musst 😉

    musste nur etwas abändern...

    #include <iostream>
    #include <typeinfo>
    #include <vector>
    using namespace std;
    
    class B {public:virtual ~B(){}};
    class X : public B {public:void f(){cout<<"hello B"<<endl;}};
    class Y : public B {};
    
    vector<B*> vec;
    
    int main()
    {
        int s;
        for (s=0; s<10; s++)
        {
            switch (rand()%3)
            {
                case 0:
                vec.push_back (new B);
                break;
    
                case 1:
                vec.push_back (new X);
                break;
    
                case 2:
                vec.push_back (new Y);
                break;    
            }
        }
    
        for (s=0; s<10; s++)
            if (typeid(*vec[s]) == typeid(X))  // nur X hat f() ;)
                ((X*)vec[s])->f();
    }
    


  • Hab ich was verpasst, oder warum posten hier alle soviel Code? 😕



  • pale dog schrieb:

    Artchi schrieb:

    Ich denke auch, das niemand typeid benutzt, außer für Debug-Ausgaben oder um einen what-Exception-String etwas informativer zu gestalten. Funktional ist das Ding nutzlos.

    wieso? wenn man einen pointer auf die basisklasse hat und wissen will, wissen auf wen der wirklich zeigt, ist 'typeid' doch gut zu gebrauchen.
    🙂

    😕 Verstehe nur Bahnhof...



  • KasF schrieb:

    Sowas würde kein C++ Programmierer schreiben, ein paar überladene Funktionen und gut is die Sache ...

    Geht nicht, zu wenig RAM.



  • KasF schrieb:

    pale dog schrieb:

    wieso? wenn man einen pointer auf die basisklasse hat und wissen will, wissen auf wen der wirklich zeigt, ist 'typeid' doch gut zu gebrauchen.
    🙂

    Ich gebe da Artchi Recht! Was net ( 😃 ) sagt deutet auf ein Design Fehler hin. Mach mir mal ein Beispiel mit typeId und ich mache daraus eins ohne 😉

    Mußte über diese Antwort seeehr lange nachdenken. Aber jetzt verstehe ich den ganzen unsinnigen geposteten Code.

    Ich habe nicht gesagt, das man typeid nicht gebrauchen kann!!! Ich habe gesagt, das ihn niemand benutzt! Warum? Weil typeid nicht zu gebrauchen ist! Aber man KÖNNTE es nutzen, wenn typeid zu gebrauchen WÄRE!

    Das der Threadersteller typeid gebrauchen könnte, steht außer fragen. Aber wir mußten ihm klar machen, das er es nicht gebrauchen kann, weil typeid nicht das macht, was er sich erhofft. Und als Lösung für sein Anforderung, muß er sich ein eigenes Typeid bauen.



  • pale dog schrieb:

    musste nur etwas abändern...

    #include <iostream>
    #include <typeinfo>
    #include <vector>
    using namespace std;
    
    class B {public:virtual ~B(){}};
    class X : public B {public:void f(){cout<<"hello B"<<endl;}};
    class Y : public B {};
    
    vector<B*> vec;
     	
    int main()
    {
        int s;
        for (s=0; s<10; s++)
        {
            switch (rand()%3)
            {
                case 0:
                vec.push_back (new B);
                break;
                
                case 1:
                vec.push_back (new X);
                break;
                
                case 2:
                vec.push_back (new Y);
                break;    
            }
        }
    
        for (s=0; s<10; s++)
            if (typeid(*vec[s]) == typeid(X))  // nur X hat f() ;)
                ((X*)vec[s])->f();
    }
    

    Naja nen Code der bissl mehr aussagt und nen Bezug auf die reale Welt hat, wäre zwar schöner, aber dennoch hier:

    #include <iostream>
    #include <typeinfo>
    #include <vector>
    using namespace std;
    enum IAM { BCLASS , XCLASS , YCLASS };
    
    class B { public: virtual ~B(){} virtual  IAM type() const { return BCLASS;} };
    
    class X : public B { public:void f(){cout<<"hello B"<<endl;} virtual  IAM type() const { return XCLASS;}};
    class Y : public B { public: virtual  IAM type() const { return YCLASS;} };
    
    vector<B*> vec;
    
    int main()
    {
        int s;
        for (s=0; s<10; s++)
        {
            switch (rand()%3)
            {
                case 0:
                vec.push_back (new B);
                break;
    
                case 1:
                vec.push_back (new X);
                break;
    
                case 2:
                vec.push_back (new Y);
                break;
            }
        }
    
        for (s=0; s<10; s++)
            if ( vec[s]->type() == XCLASS)  // nur X hat f() ;)
                ((X*)vec[s])->f();
    }
    

    proggingmania schrieb:

    Geht nicht, zu wenig RAM.

    Kauf dir nen neuen Rechner 😉
    Zudem macht das nicht viel aus, mit deinem Template werden auch drei Funktion generiert.
    Dann sowas wie die Eingabe könnte man noch auslagern ...

    Edit: Beispiel abgeändert ...



  • Oder du behältst dein Code und änderst deine Schleife:

    for (s=0; s<10; s++)
    {
        X* xx = dynamic_cast<X*>(vec[s]);
        if ( xx )  
            xx->f();
    }
    


  • KasF schrieb:

    Naja nen Code der bissl mehr aussagt und nen Bezug auf die reale Welt hat, wäre zwar schöner,

    ist es denn so exotisch, wenn man pointer auf die basisklasse in einen vector steckt?

    KasF schrieb:

    aber dennoch hier:

    #include <iostream>
    #include <typeinfo>
    #include <vector>
    using namespace std;
    
    enum IAM { BCLASS , XCLASS , YCLASS };
    
    class B { IAM matype; public: B(IAM t = BCLASS):matype(t) { }; virtual ~B(){} IAM type() const { return matype; }};
    
    class X : public B { public: X():B(XCLASS) { }; void f(){cout<<"hello B"<<endl;} };
    class Y : public B { public: Y():B(YCLASS) { };  };
    
    vector<B*> vec;
    
    int main()
    {
        int s;
        for (s=0; s<10; s++)
        {
            switch (rand()%3)
            {
                case 0:
                vec.push_back (new B);
                break;
    
                case 1:
                vec.push_back (new X);
                break;
    
                case 2:
                vec.push_back (new Y);
                break;
            }
        }
    
        for (s=0; s<10; s++)
            if ( vec[s]->type() == XCLASS)  // nur X hat f() ;)
                ((X*)vec[s])->f();
    }
    

    glückwunsch, du hast typeid nachgebaut 😃

    KasF schrieb:

    Oder du behältst dein Code und änderst deine Schleife:

    for (s=0; s<10; s++)
    {
        X* xx = dynamic_cast<X*>(vec[s]);
        if ( xx )  
            xx->f();
    }
    

    ich hab' mal gehört, dass 'typeid' sehr schnell geht und konstante laufzeit hat, während 'dynamic_cast' die ganze vererbungshirarchie durchrödeln muss...



  • pale dog schrieb:

    glückwunsch, du hast typeid nachgebaut 😃

    Ich habe doch gesagt, das ich es ohne typeid machen kann 😉

    Mit bissl schöner und so meinte ich Sachen wie:
    Wieso gibt es kein f() in B. Sollte B abstrakt. Einfach ein Beispiel hinklatschen kann ja jeder, wenn man weiß was der Autor genau machen will, kann man vllt das Design umändern ...

    Aber ich glaube wir belassen das hier mal so !


Anmelden zum Antworten