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
Da machst Du Dir unnötige Sorgen
Im Umgang mit DirectX würde ich genauso wie im Umgang mit der WinAPI immer Rückgabewerte prüfen.
Und eine Exception reicht, weil Du ja dann nicht wirklich unterscheiden willst, warum genau es schiefgegangen ist, sondern willst nur möglichst sauber abschmieren und im Log eine Info für die Fehlersuche hinterlassen. Also reicht eine Exception-Klasse, theoretisch sogar die std::exception direkt benutzen.
Meine persönliche Richtlinie sieht so aus:
Wenn die Operation üblicherweise gut geht, und Du beim Scheitern eigentlich nicht sinnvoll weitermachen kannst, und es Dir eigentlich wurscht ist, woran genau die Operation schiefgegangen ist -> Ausnahme. Beispiele: Texturen anlegen, DrawCalls ausführen, Thread anlegen.
Wenn die Operation durchaus mal scheitern kann oder/und Du im Scheiterfall die Fehlerursache kommunizieren willst, weil es für den Aufrufer tatsächlich relevant ist -> Funktion mit Rückgabewert. Beispiele: Datei öffnen, IP-Verbindung, Nutzerdaten-Abfrage.
Community-Fossil
Du kannst assertions auch mit Exceptions kombinieren indem du dein eigenes assert Makro schreibst, welches eine beliebige Exception wirft.
C-/C++-Quelltext |
|
1 2 3 4 5 6 |
void Grid::spawn(ObjectID id, Vector2u position) { if (id > MAX_OBJECTS) { throw MyException("Invalid object #" + std::to_string(id)); } // ... } |
C-/C++-Quelltext |
|
1 2 3 4 |
void Grid::spawn(ObjectID id, Vector2u position) { MyAssertion(id <= MAX_OBJECTS); // ... } |
Alternativ gibt es in den meisten Test Frameworks auch ne moeglichkeit auf fehlgeschlagene asserts zu testen (z.B. EXPECT_DEATH in Google Test): http://stackoverflow.com/questions/37564…ith-google-test
Gibt bei Exceptions immer sinnvolle Informationen aus, z.B. welche Reichweite von Werten denn gültig wäre.
C-/C++-Quelltext |
|
1 2 3 |
throw ObjectNotFound(scene_id, object_id); throw PositionNotFound(scene_id, tile_pos); // usw. |
Quellcode |
|
1 |
ObjectID #17 is not used. |
Quellcode |
|
1 |
Invalid id #17. |
C-/C++-Quelltext |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
class GameError { public: virtual void dump(Logger& logger) = 0; }; class ObjectNotFound: public GameError { private: int scene_id, object_id; public: ObjectNotFound(int scene_id, int object_id) : GameError{} , scene_id{scene_id} , object_id{object_id} { } void dump(Logger& logger) override { logger << "Cannot find object #" << object_id << " at scene # " << scene_id << "\n"; } }; // etc. |
Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Glocke« (01.02.2015, 10:11)
Community-Fossil
Du brauchst für die Exceptions eine einheitliche Schnittstelle für den Logger
Um Dopplungen ein wenig zu reduzieren kannst du ja mehrere Konstruktoren bereitstellen, die dann die Parameter in eine sinnvolle Nachricht umbauen.
C-/C++-Quelltext |
|
1 2 3 4 5 6 7 8 9 10 11 |
class SceneException { SceneException(int scene_id) { logger << "Invalid Scene #" << scene_id << "\n"; } SceneException(int scene_id, int object_id) { logger << "Object #" << object_id << " not found in Scene #" << scene_id << "\n"; } SceneException(int scene_id, Point pos) { logger << "Scene #" << scene << " has no position " << pos << "\n"; } }; |
Community-Fossil
Werbeanzeige