[portable typeID] gibt es sowas?



  • 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 !



  • KasF schrieb:

    Kauf dir nen neuen Rechner 😉

    Geht nicht ist für nen Microcontroller, ohne RAM Erweiterung mit wenig KByte 😉



  • proggingmania schrieb:

    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');
    }
    
    template< class T >
    void bombensicher( T &a )
    {
    	string str = "Bitte geben Sie ein" + Filler(a) + " 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;
    }
    

    Hi,

    ich bin zwar nicht KasF und will auch nicht seine These in der Allgemeinheit stützen, aber das ist ein denkbar schlechtes "Gegenbeispiel", weil hier die Typinformation sowieso schon zur Compilezeit aufgelöst wird ... dafür braucht man wirklich keine Runtime-Type-Information.

    #include <iostream>
    #include <limits>
    #include <string>
    using namespace std;
    
    string Filler(const string& a) {
       return "en String";
    }
    
    string Filler(const double& a) {
       return "e Fließkommazahl";
    }
    
    string Filler(const char& a) {
       return " Zeichen";
    }
    
    template< typename T >
    void bombensicher( T &a )
    {
    	string str = "Bitte geben Sie ein" + Filler(a) + " 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');
    }
    

    ... und ausgelinkt braucht das auch nicht mehr Platz (eher weniger) und läuft schnller als Deine template-Variante.

    Gruß,

    Simon2.



  • pale dog schrieb:

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

    typeid() selbst ist schnell, allerdings type_info::operator == ist nicht immer so super schnell (oft einfach als strcmp implementiert).



  • Achja, C++ kann ja Funktionen überladen. Naguuut. 🙂



  • typeinfos kann man ordnen. siehe dazu den beitrag im magazin zu multi-dispatcher. dafür kann man typeid gut gebrauchen.



  • queer_boy schrieb:

    typeinfos kann man ordnen. siehe dazu den beitrag im magazin zu multi-dispatcher. dafür kann man typeid gut gebrauchen.

    eigentlich sollte jede sprache, mit der man vererbung machen kann, sowas wie 'typeid' haben. sonst würde es einfach fehlen...
    🙂


Anmelden zum Antworten