Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

11

05.03.2015, 14:26

Wäre es nicht besser, die Sache mit dem vector in einem eigenen Foo Container zu kapseln, anstatt so umständlich mit irgendwelchen virtuellen Methoden und wild überladenen operator== rumzumachen? ;)

Nein, weil ich Momentan alle meine Foo Unterklassen in separate Container speichere, und die alle eine identische Funktionsweise haben. Würde ich eine compare Methode in den Container einbauen wollen, müsste ich das ganze polymorph gestalten, was absolut nicht in meinem Interesse ist.
Ich könnte natürlich auch per Funktionspointer eine compare Methode an den Container übergeben, aber das ist irgendwie einfach nur umständlich.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

12

05.03.2015, 14:29

Ich hatte früher mal die Frage gestellt warum Operatoren Global überladen werden (Bei Klassen des selben Typs).
Das wäre jetzt für mich der einzige Grund das Global zu machen (meine damalige Frage konnte für mich nie zufriedenstellend beantwortet werden).

Z.B. weil man will, dass Operator kommutativ ist:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
bool operator ==(const A& a, int x) // das würde auch als Member gehen
{
  ...
}
bool operator ==(int x, const A& a) // das nicht
{
  return a == x;
}


Außerdem: http://www.drdobbs.com/cpp/how-non-membe…capsu/184401197 ;)

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

13

05.03.2015, 14:35

Wäre es nicht besser, die Sache mit dem vector in einem eigenen Foo Container zu kapseln, anstatt so umständlich mit irgendwelchen virtuellen Methoden und wild überladenen operator== rumzumachen? ;)

Nein, weil ich Momentan alle meine Foo Unterklassen in separate Container speichere, und die alle eine identische Funktionsweise haben. Würde ich eine compare Methode in den Container einbauen wollen, müsste ich das ganze polymorph gestalten, was absolut nicht in meinem Interesse ist.
Ich könnte natürlich auch per Funktionspointer eine compare Methode an den Container übergeben, aber das ist irgendwie einfach nur umständlich.

Mach ein Containertemplate, das du dann für jede Unterklasse instanzierst... ;)

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

14

05.03.2015, 15:19

Es wäre immernoch gut zu wissen, was deine Foo- und Bar-Klassen repräsentieren. Wenn du wirklich Anregungen erhalten willst, wie du vorgehen könntest, dann brauchen wir diese Informationen, da es sonst eher ein rumgerate ist.
Mir kommt die ID der Element sehr komisch vor. Sie entspricht immer der Position des Elements in der Liste, unter Verrechnung eines konstanten Werts, wodurch dieser Wert faktisch redundant gespeichert wird. Über die Position in der Liste ergibt sich die ID.
Wenn an einer anderen Stelle außerhalb neue Objekte erstellt und mit einer ID versehen werden, dann müsste der Aufrufenden Stelle auch die "Seiteneffekte" bekannt sein (Überschreiben "zufälliger" Daten) bzw. die ID muss auf irgendeine Weise richtig bestimmt werden. Ist letzteres der Fall, wovon ich ausgehe, wäre es vielleicht sinnvoller, das richtige Element aus der Liste abzurufen und dieses zu verwenden. Wenn im Zuge dessen Änderungen durchgeführt werden, dann wurden Änderungen durchgeführt und das Flag kann gesetzt werden. (Idealerweise wird dieses Flag intern gesetzt, wenn die Änderungen durchgeführt werden.)
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

15

05.03.2015, 17:17

Hmmm an welcher stelle sind jetzt die Globalen Vergleichs Operatoren unbrauchbar geworden?

Habe da jetzt nichts rauslesen können, das die es nicht machen würden.

@Dot


Ich hatte früher mal die Frage gestellt warum Operatoren Global überladen werden (Bei Klassen des selben Typs).
Das wäre jetzt für mich der einzige Grund das Global zu machen (meine damalige Frage konnte für mich nie zufriedenstellend beantwortet werden).

Damit ist dein Bsp. schon aus dem rennen!
Link zur alten Diskusion

Will ich hier aber gar nicht weiter vertiefen!
Wer aufhört besser werden zu wollen hört auf gut zu sein!

aktuelles Projekt:Rickety Racquet

16

05.03.2015, 17:47

Es wäre immernoch gut zu wissen, was deine Foo- und Bar-Klassen repräsentieren. Wenn du wirklich Anregungen erhalten willst, wie du vorgehen könntest, dann brauchen wir diese Informationen, da es sonst eher ein rumgerate ist.
Mir kommt die ID der Element sehr komisch vor. Sie entspricht immer der Position des Elements in der Liste, unter Verrechnung eines konstanten Werts, wodurch dieser Wert faktisch redundant gespeichert wird. Über die Position in der Liste ergibt sich die ID.
Wenn an einer anderen Stelle außerhalb neue Objekte erstellt und mit einer ID versehen werden, dann müsste der Aufrufenden Stelle auch die "Seiteneffekte" bekannt sein (Überschreiben "zufälliger" Daten) bzw. die ID muss auf irgendeine Weise richtig bestimmt werden. Ist letzteres der Fall, wovon ich ausgehe, wäre es vielleicht sinnvoller, das richtige Element aus der Liste abzurufen und dieses zu verwenden. Wenn im Zuge dessen Änderungen durchgeführt werden, dann wurden Änderungen durchgeführt und das Flag kann gesetzt werden. (Idealerweise wird dieses Flag intern gesetzt, wenn die Änderungen durchgeführt werden.)


Die Bar Klassen sind letztendlich Datensätze meiner Spieldatenbanken. Ein solcher Datensatz ist z.B. eine Tile Art, oder eine WorldObject Vorlage oder sowas.
Diese Datensätze lade ich in meine Gui und gebe die Möglichkeit sie zu verändern. Da ich aber bei einer Veränderung nicht direkt den originalen Datensatz überschreiben möchte, speichere ich diesen zwischen und erst wenn wirklich gespeichert wird, werden die originalen Datensätze überschrieben.
Es ist durchaus auch richtig, das ich auch speichern könnte, ob die GUI-Elemente eine Änderung registriert haben, aber das möchte ich vermeiden, da nach einer Änderung durchaus auch auf den Ursprungswert gesetzt werden kann. Da scheint es mir sinniger zu sein, zu checken ob die Datensätze sich unterscheiden.

Mir ist bewusst, dass die ID durchaus redundant ist, allerdings nehme ich das hier in diesem Fall in Kauf, da ich sonst die ID teilweise separat mitschleppen müsste und ich darauf nicht wirklich Lust habe.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

17

05.03.2015, 17:53

@Dot


Ich hatte früher mal die Frage gestellt warum Operatoren Global überladen werden (Bei Klassen des selben Typs).
Das wäre jetzt für mich der einzige Grund das Global zu machen (meine damalige Frage konnte für mich nie zufriedenstellend beantwortet werden).

Damit ist dein Bsp. schon aus dem rennen!
Link zur alten Diskusion

Wie ich sehe, hab ich damals ja schon auf implizite Konvertierungen hingewiesen, das wäre z.B. ein Grund, wieso man es selbst bei 2x gleicher Typ würde machen wollen. Fazit: Es ist bestenfalls egal, oft aber hat die Variante mit der freien Funktion ein paar Vorteile. Imo stellt sich viel eher die Frage, wieso man es nicht als freie Funktion implementieren sollte... ;)

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

18

05.03.2015, 18:02

Ich gehe mal davon aus, dass die Bearbeitung der Daten über einen Dialog stattfindet, bei dem auch ein "Abbrechen"-Button vorhanden ist. Ist das der Fall kann man so vorgehen, dass das jeweilige Objekt abgerufen wird, die zu bearbeitenden Informationen in die UI-Elemente übertragen werden, und erst beim Speichern die Änderungen im UI wieder auf das Objekt übertragen werden.
Aber egal wie man vorgeht, damit für ein bestimmtes Element der richtige Dialog zur Bearbeitung angezeigt werden kann, muss bereits der richtige Typ bekannt sein. Selbst wenn man für die Bearbeitung im UI eine Kopie des ursprünglichen Objekts anlegt, beim Speichern _kennt_ man die beiden Typen und kann dementsprechend einen für genau diesen Typ implementierten Operator verwenden.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

19

05.03.2015, 18:15

Ich gehe mal davon aus, dass die Bearbeitung der Daten über einen Dialog stattfindet, bei dem auch ein "Abbrechen"-Button vorhanden ist. Ist das der Fall kann man so vorgehen, dass das jeweilige Objekt abgerufen wird, die zu bearbeitenden Informationen in die UI-Elemente übertragen werden, und erst beim Speichern die Änderungen im UI wieder auf das Objekt übertragen werden.

Praktisch richtig, nur das man nicht für jedes Objekt auf "speichern" klicken muss, sondern man direkt in einer Liste angezeigt bekommt, welche Objekte es gibt und man per Klick auf einen Eintrag einen neuen Datensatz auswählt. Der vorher ausgewählte wird dabei temporär gespeichert. Aber ja, so in etwa funktioniert das.


Aber egal wie man vorgeht, damit für ein bestimmtes Element der richtige Dialog zur Bearbeitung angezeigt werden kann, muss bereits der richtige Typ bekannt sein. Selbst wenn man für die Bearbeitung im UI eine Kopie des ursprünglichen Objekts anlegt, beim Speichern _kennt_ man die beiden Typen und kann dementsprechend einen für genau diesen Typ implementierten Operator verwenden.

Es war auch nie meine Frage, wie ich 2 unterschiedliche Typen miteinander vergleiche, sondern verhindere dass das Problem mit 2 unterschiedlichen Typen auftreten kann und mir gleichzeitig Aufwand und potenzielle Fehlerquellen erspare.
Die Klassenhierarchie ist ein wenig tiefer (nicht viel, aber der Aufwand potenziert sich eben), deswegen versuche ich für mich die optimalste Lösung zu finden.
Das System mit dem speichern und verwerfen steht, lediglich der Vergleich ist das letzte Puzzlestück, das fehlt ;)

Helmut

5x Contest-Sieger

Beiträge: 692

Wohnort: Bielefeld

  • Private Nachricht senden

20

05.03.2015, 18:18

Mach's doch einfach so wie im Code vom aktuellen Contest:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//Basisklasse für Spieler und Bälle
class GameObject
{
public:
    int xPos, yPos;//Position
    int xVel, yVel;//Geschwindigkeit. X-Komponente wird für Player nicht benutzt
public:
    GameObject();
    GameObject(int xPos, int yPos);
    bool operator==(const GameObject& rhs) const;
    bool CollidesWith(const GameObject& Other, int RadiusSum) const;
    void ProcessCollision(GameObject& Other);
};
bool GameObject::operator==(const GameObject& rhs) const
{
    if(xPos != rhs.xPos) return false;
    if(yPos != rhs.yPos) return false;
    if(xVel != rhs.xVel) return false;
    if(yVel != rhs.yVel) return false;
    return true;
}
class Player : public GameObject
{
public:
    int LastKeys; //Welche Tasten letzten Frame ausgeführt wurden
    int Score; //Punkte
    bool Scores; //Hat er gerade einen Punkt gemacht
public:
    Player();
    void ResetPosition(int Player);
    bool operator==(const Player& rhs) const;
};
bool Player::operator==(const Player& rhs) const
{
    if(!GameObject::operator==(rhs)) return false;
    if(LastKeys != rhs.LastKeys) return false;
    if(Score != rhs.Score) return false;
    if(Scores != rhs.Scores) return false;
    return true;
}

Solange keine Polymorphie im Spiel ist (und du sagst ja, dass es das nicht ist), ist doch alles einfach.
Sei stets geduldig gegenüber Leuten, die nicht mit dir übereinstimmen. Sie haben ein Recht auf ihren Standpunkt - trotz ihrer lächerlichen Meinung. (F. Hollaender)

Werbeanzeige