alternative für RTTI



  • Ich frage mich nur, woher du dann die ID's hast.. Wenn du die irgendwo speicherst, kannst du es ja machen, wie es ein Vorposter gesagt hat und gleich die Zeiger darauf speichern..



  • drakon schrieb:

    Ich frage mich nur, woher du dann die ID's hast..

    ich hab sie von "reinterpret_cast<button *>(g->getelement(1742)->getelement(8765))->settext(...);" im ersten posting.

    im letzten posting scheint fragezeichen? sie nicht mehr zu brauchen. 😕



  • volkard schrieb:

    drakon schrieb:

    Ich frage mich nur, woher du dann die ID's hast..

    ich hab sie von "reinterpret_cast<button *>(g->getelement(1742)->getelement(8765))->settext(...);" im ersten posting.

    im letzten posting scheint fragezeichen? sie nicht mehr zu brauchen. 😕

    Ah, ne Sorry. Ich habe auf den Post vor dir bezogen geschrieben. 😉

    Ich meinte im Programm allgemein. Wenn er die ID's irgendwo speichert, ala "myButtonIDContainer", dann ist das ganze Spiel ja eh für die Katze und man hätte gleich die Zeiger speichern können.



  • die IDs muss man sich halt merken. zeiger kann man sich aber nicht merken.
    entweder ich speichere irgentwo unmengen an zeigern, die nur für eine methode
    aufgerufen werden, oder ich löse das über IDs.

    (ich will in der rendermothode an einen knopf kommen der aus der main stammt)

    die z.b. getedit methode braucht keine id, sie wird ja von einem generischen
    zeiger aufgerufen, dessen typ zu ermitteln ist.

    bsp:

    guimain->getactivepage()->getelement(1)->getelement(1)->getprogressbar()->setpercent(val);
    

    getprogressbar gibt standardmäßig 0 zurück. nur wenn es sich wirklich um eine
    progressbar handelt, kommt this zurück. das vermeidet gleichzeitig das casten.

    exeptions, hm.. naja.. das ist auch geschmackssache, aber es vergrößert den code
    nur. außerdem fliegt die exeption eh wenn die methode 0 liefert.

    volkard schrieb:

    wer sagt das? ich hab nicht verraten, wie die innendrin gehen.

    weil

    volkard schrieb:

    ok, ich geb's zu: das ist nur ne andere schreibweise für
    g->dynamic_cast<Window&>(getelement(1742)).dynamic_cast<Button&>(getelement(1765)).settext(...);



  • premature optimization schrieb:

    Badestrand schrieb:

    fragezeichen? schrieb:

    dynamic_cast für (geringe) performance-probleme bekannt ist

    Gegenüber dem, was dem cast dann folgt, ist das aber ein Witz 😉

    Also auf 64-Bit Windowssystemen können dynamic_casts ein Problem sein, vorallem wenn man ein paar 100000 pro Sekunde macht.
    http://blogs.msdn.com/junfeng/archive/2006/10/17/dynamic-cast-is-slow-in-x64.aspx
    http://archives.windowshpc.net/blogs/dev_gen/archive/2006/10/17/647.aspx

    Wenn ich das richtig verstehe, ist das nicht Win64-, sondern MSVC64-spezifisch.
    Falls dem so ist: hoffen wir mal, daß CodeGear es besser macht 😉



  • dynamic_cast war bei MSVC immer schon langsam. Irgendwie krass dass MS es geschafft hat die noch langsamer zu machen. Und schade. Es gibt einige wenige Stellen wo dynamic_cast wirklich hilfreich wäre, und manchmal sind da auch performance-kritische Dinge dabei. 👎 für MS



  • fragezeichen? schrieb:

    volkard schrieb:

    wer sagt das? ich hab nicht verraten, wie die innendrin gehen.

    weil

    volkard schrieb:

    ok, ich geb's zu: das ist nur ne andere schreibweise für
    g->dynamic_cast<Window&>(getelement(1742)).dynamic_cast<Button&>(getelement(1765)).settext(...);

    oh. ich hab nicht dazugeschrieben, daß ich innen schon sowas wie deine virtuellen funktionen haben wollte. ich mag nämlich dynamic_cast gar nicht.
    anfangs dachte ich, daß dich die aufrufsyntax nervt und die unsicherheit, vielleicht nen nullzeiger zu benutzen.
    "ok, ich geb's zu: das ist nur ne andere schreibweise für" war aus sicht des aufrufers gemeint.

    die template-funktion getElement merke ich mir, die wird praktisch sein, wenn ich mal groß bin und ein MMORPG schreibe. über's netz fliegen ja nur IDs von den mobs, vielleicht ist es dann gut, wenn ich alle objekte mit IDs verwalte. macht auch das speichern und laden viel einfacher.



  • fragezeichen? schrieb:

    die IDs muss man sich halt merken. zeiger kann man sich aber nicht merken.
    entweder ich speichere irgentwo unmengen an zeigern, die nur für eine methode
    aufgerufen werden, oder ich löse das über IDs.

    Und das mit den IDs ist Quatsch wie du doch schon selber merkst. Ob du dir eine ID oder nen Pointer als Member einer Klasse hältst ist doch egal. Schau dir mal andere GUI Frameworks an.
    http://doc.trolltech.com/4.0/examples.html



  • volkard schrieb:

    die template-funktion getElement merke ich mir, die wird praktisch sein, wenn ich mal groß bin und ein MMORPG schreibe. über's netz fliegen ja nur IDs von den mobs, vielleicht ist es dann gut, wenn ich alle objekte mit IDs verwalte. macht auch das speichern und laden viel einfacher.

    es lebe das id system 😃

    premature optimization schrieb:

    Und das mit den IDs ist Quatsch wie du doch schon selber merkst. Ob du dir eine ID oder nen Pointer als Member einer Klasse hältst ist doch egal.

    wenn man die ids eh als member speichert, macht das wenig sinn, da hast du recht.
    wenn man aber statische ids vergibt, und in der lage ist sich diese 2min zu
    merken, kann man in einer anderen methode oder funktion (die keinen zugriff
    auf die verwaltungsklasse hat) den zeiger weiterverwenden.

    und wie volkard schon sagte, wenn man übers netz auf objekte zugreifen will,
    werden zeiger sicherlich probleme machen. man kann die gültigkeit nicht
    prüfen und das auf jedem client die daten an der selben stelle liegen, ist
    sehr unwahrscheinlicht.



  • volkard schrieb:

    die template-funktion getElement merke ich mir, die wird praktisch sein, wenn ich mal groß bin und ein MMORPG schreibe. über's netz fliegen ja nur IDs von den mobs, vielleicht ist es dann gut, wenn ich alle objekte mit IDs verwalte. macht auch das speichern und laden viel einfacher.

    Ok, dass verstehe ich jetzt nicht. War das ironisch gemeint oder ist der Zugriff auf Objekte per ID wirklich so toll 😕

    Kann man sich denn die Objekte (Buttons, Scrollbars usw...) nicht in unterschiedlichen Listen merken und vieleicht mit sowas hier den Zeiger holen?

    // Verschiedene Gui Elemente
    class Gui {
    public:
      enum type{
        Undefined,
        Button,
        Scrollbar
      }
    }
    
    // ein Steuerelement
    class Button public Control {
    private:
      int type;
    public:
      Button() {
        type = Gui::Button;
      }
    }
    
    // ein Menü mit Buttons usw...
    class MainMenu public Gui {
    protected:
      std::map<int,Button*> buttons;
      std::map<int,Scrollbar*> bars;
    public:
      bool typeOf(id, Gui::type);
      Button* getButton(id);
      Scrollbar* getScrollbar();
    
      void addElement( Control* ctrl, int posX, int posY );
    }
    
    // irgendwo im Code
    int foo {
      MainMenu menu;
    
      menu.addElement( new Button(1234), x, y );
    
      if( menu.typeOf(1234,Gui::Button) ) {
        Button* button = menu.getButton(id);
        button.setText("Ok");
      }
    
    }
    

    Ok der Code ist mit Vorsicht zu genießen (hab schon lange kein C++ mehr programmiert und jetzt auch keine Zeit die genaue Syntax rauszusuchen). Aber eigentlich könnte man doch auf diese Weise auch ohne dynamic Cast auskommen. Oder muss ich in addElement von Control* nach Button* casten?



  • fragezeichen? schrieb:

    meine jetzige lösung ist ein

    virtual edit	  *getedit() 	 {return 0;}
    virtual button	*getbutton()	{return 0;}
    virtual window	*getwindow()	{return 0;}
    // ...
    

    die jeweilige methode wird von den abgeleiteten klassen durch return this
    ersetzt. das klappt ganz gut, ist dem prinzip ziemlich ähnlich aber ist schneller.

    was haltet ihr davon?

    Es würde reichen, wenn du nur eine getFunktion in der Basisklasse definieren würdest.

    Basis:
    virtual element* getTyp() = 0;
    
    Button:
    virtual button* getTyp() { return this; }
    
    Window:
    virtual window* getTyp() { return this; }
    

    Nennt sich CoVariant-Returntype ...



  • KasF schrieb:

    Es würde reichen, wenn du nur eine getFunktion in der Basisklasse definieren würdest.

    Basis:
    virtual element* getTyp() = 0;
    
    Button:
    virtual button* getTyp() { return this; }
    
    Window:
    virtual window* getTyp() { return this; }
    

    Nennt sich CoVariant-Returntype ...

    fein. und geht dann auch

    g->getTyp(4711)->getTyp(1234)->funktionDieNurButtonHat("hallo");
    

    ?
    woher weiß der compiler, daß es dort erlaubt ist, funktionDieNurButtonHat aufzurufen? oder läßt er prophylaktisch einfach mal alle funktionen zu, die in irgendeiner geerbten klasse liegen?



  • fragezeichen? schrieb:

    premature optimization schrieb:

    Und das mit den IDs ist Quatsch wie du doch schon selber merkst. Ob du dir eine ID oder nen Pointer als Member einer Klasse hältst ist doch egal.

    wenn man die ids eh als member speichert, macht das wenig sinn, da hast du recht.
    wenn man aber statische ids vergibt, und in der lage ist sich diese 2min zu
    merken, kann man in einer anderen methode oder funktion (die keinen zugriff
    auf die verwaltungsklasse hat) den zeiger weiterverwenden.

    und wie volkard schon sagte, wenn man übers netz auf objekte zugreifen will,
    werden zeiger sicherlich probleme machen. man kann die gültigkeit nicht
    prüfen und das auf jedem client die daten an der selben stelle liegen, ist
    sehr unwahrscheinlicht.

    Klingt für mich nach nem extrem kaotischen Design. Warum must du den so verteilt auf deine GUI zugreifen? Schon mal was von Observer-Pattern, MVC usw. gehört? Und warum willst du bitte übers Netz direkt auf die GUI zugreifen?



  • premature optimization schrieb:

    Und warum willst du bitte übers Netz direkt auf die GUI zugreifen?

    will ich nicht, es geht nur darum dass man das mit einem ID system könnte.

    das system ist garnicht caotisch. kein cast, exeption bei fehlgriff und
    kein dynamic_cast overhead. und wer die implementierung nicht kennt sieht
    auch nix caotisches.



  • Die Architektur deiner Software ist schlecht, wenn du von so vielen verschiedenen Stellen auf die GUI zugreifst, das hat nix mit dynamic_cast und exceptions zu tun. Aber ich gebs jetzt auf, wenn du unnötig komplizierte Sachen mit IDs usw. machen willst, dann mach.



  • das ist nicht unnötig kompliziert.

    ich habe eine zentrale instanz von der gui und will davon auf alle elemente
    zugreifen.

    was würdest du den für diese situation vorschlagen?

    ich will nicht für jeden knopf den ich erzeuge ein zeiger speichern.



  • fragezeichen? schrieb:

    ich will nicht für jeden knopf den ich erzeuge ein zeiger speichern.

    Schau dir einfach an wie es bestehende Systeme machen.



  • volkard schrieb:

    g->getTyp(4711)->getTyp(1234)->funktionDieNurButtonHat("hallo");
    

    ?
    woher weiß der compiler, daß es dort erlaubt ist, funktionDieNurButtonHat aufzurufen? oder läßt er prophylaktisch einfach mal alle funktionen zu, die in irgendeiner geerbten klasse liegen?

    Ok, kommt davon, wenn man den Thread nur überfliegt.

    volkard schrieb:

    fein

    🙄
    Es wäre erwünschenswert, wenn du dir mal ne andere Haltung im Forum angewöhnen könntest. 90% deiner Beiträge klingen so, als ob ganz TOLL wärst und über uns allen stehen würdest.

    Nur ne Bitte ...



  • ich finde deinen code aber wirklich fein. deswegen schrieb ich "fein". nur löste er in diesem fall keine wchtigen probleme.


Anmelden zum Antworten