?
Naja. Aber sag mal, du hast offenbar einiges an Erfahrung. Bezüglich dem was ich im vorletzten post schrieb... hast du für dich Regeln gefunden, nach denen du breites vs. schlankes interface abwägst?
Naja, so allgemein tu' ich mir schwer dazu viel zu sagen. Aber...
Ich meide GUI Code wie die Pest (Beulenpest, die schwarze), u.A. weil ich bis jetzt noch keine ordentliche GUI Lib gesehen hab. Das Teil von Adobe könnte was können, is mir dann aber wieder viel zu heftig (eigene VM bloss für die GUI, und das ist erst der Anfang).
Ich meide wenn möglich Polymorphismus in meinen *Designs* zu haben, wenn dann als Implementierungs-Detail, aber das wars dann auch schon. Wenn möglich wie gesagt Geht bloss leider nicht immer ganz einfach, und bei so Sachen wie nem Szenengraph ist es eigentlich doof was anderes zu machen. Reine "Interfaces" sind eine andere Sache, aber wenns geht bitte auch ohne Vererbung. Natürlich braucht man dann öfter mal Adapter, z.B. wenn man zwei generische Interfaces "RandomAccessStorage" und "InputStream" komplett getrennt voneinander definiert dann braucht man einen "InputStream_From_RandomAccessStorage_Adapter" (und ja, ich verwende so lange Klassennamen :)) der aus dem RandomAccessStorage einen InputStream macht. Allerdings kann man da wieder etwas Code sparen indem man ein Template als Adapter verwendet welches bloss voraussetzt dass der Typ mit dem man es instanziert Funktionen mit gewissen Namen hat die gewisse Dinge erledigen (also quasi ein "Concept" erfüllt). Für Fälle wo das nicht zutrifft (weil die Funktionen vielleicht anders heissen oder nicht 1:1 kompatible Semantik haben) kann man dann leicht das Template spezialisieren wo man seinen Glue-Code reinschreibt und fertig.
Eine Sprite-LIB die ich mal baute hatte das auch, also Sprite und SpriteContainer, wobei SpriteContainer selbst ein Sprite war. Da hatte ich intern auch nen dynamic_cast (weil das nackte "Sprite" eben kein Container sondern eindeutig ein Leaf des Szenengraphen war), bloss hab ich den auf die "Insert" Funktion des SpriteContainer beschränkt (ich hatte sowieso schon wesentlich mehr State zu einem Sprite als bloss den Pointer auf selbiges, da war der zusätzliche Pointer auf das SpriteContainer Interface auch schon egal). Somit in den Such- und Szenengraph-Durchklaub-Funktionen kein dynamic_cast mehr sondern nur Test ob der Pointer null ist. Im Nachhinein bin ich mir aber nichtmehr sicher ob es nicht besser gewesen wäre gleich nur eine Klasse zu haben.
dynamic_cast ist wie goto: grundsätzlich nicht böse, man muss bloss wissen was man tut (und ja, ich verwende goto, z.B. als "double-break", aber bloss ganz selten *pfeiff*)
Nochmal zu dem spezifischen Fall Szenengraph zurück: wenn dein einziger (oder schwerwiegendster) Grund der ist dass du in GetChild() weniger Fehlerfälle haben willst, dann ist es wurst, weil du wie Shade Of Mine schon schrieb sowieso immer den Fall handlen muss dass jmd. ein Child haben will welches es in dem Container aber nicht gibt. Anders sieht es mit den "Insert()" und "Remove()" Funktionen aus, aber die musst du ja nicht unbedingt in Control implementieren. Genausowenig wie die GetChild() Funktion in Control public sein muss - wozu gibts "friend"? Und die GetChild() Funktion eines Composite-Controls muss ja auch nicht unbedingt die einzelnen Elemente aus denen das zusammengesetzt ist zugänglich machen.
Grundsätzlich solltest du aber beim Interface anfangen, also quasi aus Sicht des Programmierers der deine LIB verwendet. Erstmal ohne grossartig zu überlegen wie du das dann im Detail implementierst. Wenn du dann mal ein gutes Interface hast kannst du dir Gedanken machen ob du dann in der Implementierung nen dynamic_cast oder eine "IsFrame" Funktion oder eine private "GetChild" Funktion verwendest. Vergiss dabei aber z.B. nicht dass User auch selbst ihre eigenen Composite-Controls implementieren werden wollen -- du solltest also auch diverse Sachen die du z.B. selbst brauchst um gewisse Controls zu implementieren dem User nicht völlig verschliessen, der ärgert sich sonst nämlich.
Und klapper ruhig gewisse Foren zu gewissen bestehenden GUI LIBs ab und frag die Leute dort was gut ist und was schlecht, was sie häufig einsetzen, was nie, was fehlt etc.
Ja nu, viel geschrieben, wenig gesagt. Vielleicht ein andermal mehr, jetzt muss ich heia, auch Räuber mit geschüttelten Namen müssen arbeiten