Friend Class und Vererbung
-
übrigens warum verwendest nicht einfach das visitor oder observer pattern
-
Ui, muss ich erst mal nachschlagen
-
ja was ist das denn?
ich hab echt noch nicht den schnall im design.
wie ich meine klassen mach ist wahrscheinlich horror für euch.population ----------------- cyclce() ----------------- vector<lifeform*> ----> lifeform ----------- bool is alive ----------- life() population* // <--- Zugehörigkeit zu einem Stamm -----------
und davon erb ich für verschiedene species.
eher chaoutisch oder sinnvol?
-
Meinst du so
struct population { }; struct lifeform : population { }; struct concretespeciesnA : lifeform { }; struct concretespeciesB : lifeform { };
?
-
nein so
class population { friend class lifeform_... // alle virtual cycle() = 0 {}; protected: vector<lifeform*> breed; // den brauch ich } class lifeform { virtual life() = 0 {}; } class population_rabbit: public population { virtual cycle() { //iterate through breed and call (*it)->life } } class lifeform_rabbit: public lifeform { virtual life() { eat(); move(); } }
-
Sieht eher nach ner UML-Imitation aus:
struct population { vector<lifeform*> members; // assoc: 0..n ---> lifeform }; struct lifeform { protected: bool alive; population* fellows; // assoc: 1 ---> population }; struct concreteSpeciesA : lifeform { }; struct concreteSpeciesB : lifeform { };
-
das problem ist, das die verschiedenen species auch verschiedene cycles in der population haben.
in der main hab ich dann nen vector<population> und davon (*iterator).cycle darum die abstrakten basisklassen.
es soll eben ohne grössere umstände ne specie dazugefügt werden.
-
Wozu brauchen die lifeform_* nun Zugriff auf den vector? Was hast du vor?
-
finix schrieb:
Wozu brauchen die lifeform_* nun Zugriff auf den vector? Was hast du vor?
Berechtigte Frage:
Jedes Lebewesen reageirt mit anderen,
also das Gras braucht Nachbarn (Game of Life)
der Hase frisst Gras und paart sich
dwer Fuchs friss Hasen und paart sich etc..
deshalb braucht eine Lebensform den Zugriff auf die Individuen jeder Population.Hatte erst Gras das wächst, und Hasen die hüpfen, nun sollen die aber interagieren. Hase hüpft nur auf grünes Gras und frisst das, Kollision mit anderen Hasen und so weiter..(Feld Wald Wiesen Simulation)
Ist mein Design falsch?
[edit]
Ich bin kein Informatiker (rate mal: Biologe) und DesignPatterns hab ich mir noch nicht angetan, sollte ich wohl..
[/edit]
-
Kenne dein insgesamtes Design nicht, aber von dem was ich da sehe sollte sich dein Problem recht leicht lösen lassen, denn ein Hase ist eine lifeform und er ist ein Bestandteil der population, also
struct rabbit : lifeform, population { };
-
struct rabbit : lifeform, population { };
Versteh ich jetz nicht ganz
-
Kennst du keine Mehrfachvererbung?
class AbgeleiteteKlasse : // hinter den Doppelpunkt kommen die Basisklasse(n) //sichtbarkeitsbereich, kann public, private oder protected sein public //public bedeutet ist ein und alle können auf die Methoden und Attribute der Basisklasse zugreifen Basisklasse1, private //private bedeutet hat ein (ist implementiert mit) und nur die abgeleitete Klasse kann auf die Methoden und Attribut der Klasse zugreifen Basisklasse2, protected //protected gibts wohl nur der vollständigkeit halber und wirst du wohl nie brauchen, könnte man verwenden um ist implementiert mit auszudrücken und die zweite Eigenschaft auszunützen, denn alle abgeleiteten Klassen von "AbgeleiteteKlasse" können ebenfalls auf die Methoden und Attribute der BasisKlasse2 zugreifen Basisklasse2 { };
so das war ne Kurzeinführung
-
ok sorry. dann hast Du mich falsch verstanden.
doch ich kenn mehrfachvererbung.
aber Population und Lifeform sind verschiedene klassenarten. Lifeform ist keine Population, sondern Population besitzt in seinem Vector 10000 Lifeform pointer. (siehe auch mein posting weiter oben)
diese alle zusammen werden von der Pop. gesteuert, beeinflussen sich aber untereinander. darum der zugriff über die Pop.klasse von einem Lifeform zum anderen.
hoffe das versteht irgendwer noch.mfg
ein verwirrter bio-logikerps ich brauch ne Pause
-
Dr. Prof schrieb:
Kenne dein insgesamtes Design nicht, aber von dem was ich da sehe sollte sich dein Problem recht leicht lösen lassen, denn ein Hase ist eine lifeform und er ist ein Bestandteil der population, also
struct rabbit : lifeform, population { };
Hier ist der springenden Punkt. "Ein Bestandteil" führt nicht zur öffentlichen Vererbung, denn die heißt nach Liskov "ist ein" und "verhält sich wie". Ein Hase ist aber weder eine Population noch verhält er sich wie eine.
-
1310-Logik: Die "Kollision" (d.h. wenn zwei Objekte nah genug beieinander kommen) sollte global erkannt und behandelt werden. Dann fällt dein Problem automatisch weg. Du hast dafür ein neues, nennt sich Double Dispatching. In Mehr effektiv C++ Programmieren wird ein ganz ähnliches Modell implementiert.
-
In dem Buch http://www.c-plusplus.net/oop_dummies.htm gibts im vorletzten Kapitel ne objektorienterte Implementierung des Game of Life. Falls du eh vor hast nen Buch über Objektorientierung in C++ zu kaufen, kann ich dir das nur empfehlen, sehr angenehm geschrieben, wenn du jedoch schon fortgeschrittener bist, dann wird dich das Buch nicht wirklich fordern.
-
Denkst du nicht es wäre etwas geschickter (und evtl intuitiver) nicht sämtliche Populationen zu durchforsten sondern eher von der Örtlichkeit aus nach benachbarten Kreaturen ausschau zu halten? Wie sieht denn deine "Welt" aus?
-
jeje danke mal allen
also..ich muss erst mal überlegen
@michael e.
kollision ist nicht das einzige problem, da wär die nachbarschaft, das fressen etc. das kann ich kaum global lösen, oder?
@finix
wie könnte ich das am dümmsten anstellen, die nachbarschaft nach vorhandenen lebensformen bestimter art zu durchsuchen?meine welt wird mit sdl dargestellt.
die population hat ein 2D array: int field[x][y], das fragt die main ab um die bilder zu bliten.
das array wird nach jedem cyclus, indem die lifeforms ein bestimmtes artspezifisches verhalten gemacht haben, upgedatet, ob sich an der entsprechenden x/y stelle eine befindet oder nicht.
artspezifisches verhalten ist sowieso das stichwort, denn das gras hat total anderes verhalten als der hase. es bewegt sich nicht, frisst nicht, und der hase spriesst nicht. die wiese (grasspopulation) enthält immer 10000 (100*100) gräser, manche tot manche lebend. das hasenrudel ist dynamisch, da die hasen ihre position ändern können. wenn ein hase stirbt wird er aus dem vector entfernt.hoffe es wird klarer was ich mein..
da heut sonntag ist werd ich mir sicher kein buch mehr kaufen. zumal das "Mehr effektiv C++ Programmieren" für mich als hobby programmierer wahrscheinlich eh oversized ist.
-
1310-Logik schrieb:
@michael e.
kollision ist nicht das einzige problem, da wär die nachbarschaft, das fressen etc. das kann ich kaum global lösen, oder?Doch, du findest global heraus, was sich grad ziemlich nah ist und rufst dann die entsprechenden Funktionen auf.
wie könnte ich das am dümmsten anstellen, die nachbarschaft nach vorhandenen lebensformen bestimter art zu durchsuchen?
Indem du in der Basisklasse eine rein-virtuelle Funktion getType() deklarierst, die dann von jeder abgeleiteten Klasse überschrieben werden muss.
die population hat ein 2D array: int field[x][y], das fragt die main ab um die bilder zu bliten.
Versteh ich nicht.
artspezifisches verhalten ist sowieso das stichwort, denn das gras hat total anderes verhalten als der hase. es bewegt sich nicht, frisst nicht, und der hase spriesst nicht.
Kein Problem, du hast ne rein-virtuelle Funktion in der Basisklasse, nenn sie meinetwegen doWhatYoureSupposedToDoInTheRealWorld() (
) und dann brauchst du einfach nur noch die Funktion für jedes Lebewesen aufzurufen.
da heut sonntag ist werd ich mir sicher kein buch mehr kaufen. zumal das "Mehr effektiv C++ Programmieren" für mich als hobby programmierer wahrscheinlich eh oversized ist.
Je nachdem, wie intensiv du dein Hobby betreiben willst.
-
Michael E. schrieb:
die population hat ein 2D array: int field[x][y], das fragt die main ab um die bilder zu bliten.
Versteh ich nicht.
population_grass* grass_a; population_rabbit* rabbit_a; // ... grass_a->cycle(); rabbit_a->cycle(); // ... for( int i = 0; i < FIELD_SIZE; i ++ ) { for( int j = 0; j < FIELD_SIZE; j ++ ) { if( grass_a->get_field(i, j) == 1 ) blit( i*CELL_SIZE, j*CELL_SIZE, tile_grass, screen ); if( rabbit_a->get_field(i, j) == 1 ) blit( i*CELL_SIZE, j*CELL_SIZE, tile_rabbit, screen ); } }
Michael E. schrieb:
Kein Problem, du hast ne rein-virtuelle Funktion in der Basisklasse, nenn sie meinetwegen doWhatYoureSupposedToDoInTheRealWorld() (
) und dann brauchst du einfach nur noch die Funktion für jedes Lebewesen aufzurufen.
aber genau das tu ich doch
do_what_ever_youre_suppose_to_do_in_the_real_world() find ich besser lesbar, einfacher find ich cycle() :p
werde mein design nach dem x-ten umbau nochmal überdenken.Je nachdem, wie intensiv du dein Hobby betreiben willst.
naja im moment nicht so schlimm, spätestens für den nachdiplom-studiengang in bioninformatik will ich fit sein auf c++ und phyton.
aber ich arbeit ja auch noch nebenbei, hab ein privatleben, einen (single-)haushalt in schwung zu halten, und ausserdem ist endlichh frühling (22°C jupee)jedenfalls big thx an euch.