Referenz zurückgeben
-
Hallo!
Folgende Situation:
Ich habe eine Klasse mit einem assoziativem Array auf das ich über Zugriffsfunktionen zugreifen will:
class Parameters { QVariant& parameter(const QString& name) { if(params_.contains(name)) return params_[name]; static QVariant& invalidParameter; return invalidParameter; } private: QMap<QString, QVariant> params_; };Ich möchte hier bei der Funktion parameter() eine Referenz benützen und weder Pointer noch eine Kopie des QVariants benützen.
Mein Problem:
Dadurch, dass die Funktion parameter() eine Referenz zurückgibt, kann man die intern benütze Variable eines ungültigen Parameters (invalidParameter) von außen ändern. Ich kann invalidParameter allerdings aufgrund der Signatur der Funktion nicht const machen (Und die Signatur soll nicht const sein).Die einzige Lösung, die mir einfällt, wäre vor dem zurückgeben von invalidParameter, dieses Wert wieder auf QVariant() zu setzen
if(invalidParameter.isValid()) invalidParameter = QVariant();Wisst ihr vielleicht eine bessere Lösung?
-
Mach's doch so wie das assoziative Array der Standardbibliothek: Gib einen Iterator anstatt einer Referenz zurück und als Fehlerwert eben einen ungültigen Iterator.
-
Exceptions
Deinen invalidParameter als Referenz anzulegen ist sowieso falsch.
-
ich hab natürlich gemeint
static QVariant invalidParameter;
-
@SeppJ:
Ist dann leider ein bisschen unpraktisch, weil ich zusätzlich eine Funktion machen muss, die dann angibt ob der Iterator gültig ist oder nicht@manni66:
In der Library, die ich erweitere werden sonst nirgends Exceptions benützt und daher wäre das ein Designbruch leider
-
basc_guess schrieb:
@SeppJ:
Ist dann leider ein bisschen unpraktisch, weil ich zusätzlich eine Funktion machen muss, die dann angibt ob der Iterator gültig ist oder nichtMach das doch auch so wie die Standardbibliothek und lass den end-Iterator eine Doppelschicht schieben. Einen end-Iterator hast du doch sicherlich sowieso.
PS: Beziehungsweise, wenn wir schon mit anderen Bibliotheken vergleichen: Die von dir genutzt QMap macht das doch genau so wie die C++-Standardbibliothek. Dann kannst du auch gleich Qmap::find nutzen, anstatt da deine eigene Abfrage zu machen, was wesentlich effizienter ist, da nicht doppelt gesucht werden muss. Selbst wenn du die Iteratorlösung aus irgendeinem Grund nicht übernehmen solltest, sehe ich nichts was dagegen spräche, wenigsten QMap::find zu nutzen und deine Funktion einfach mal eben so doppelt so schnell zu machen.
-
Wie baut man sich seien eigenen Iterator ? Da müssen Pointer ran oder?
-
how_to schrieb:
Wie baut man sich seien eigenen Iterator ? Da müssen Pointer ran oder?
Kommt ganz drauf an, kann man so pauschal nicht sagen. Letztlich ist ein Iterator aber ein pointerartiges Gebilde und die meisten Datentstrukturen arbeiten intern mit Pointern. Bei Iteratoren für Containerklassen ist daher wahrscheinlich, dass irgendwie Pointer beteiligt sind, wie auch immer gekapselt. In diesem Fall böte sich beispielsweise an, den QMap-Iterator direkt zu nutzen (der dann irgendwo ganz tief in den Interna ein Pointer sein wird). Der ganze Code scheint mir bloß ein sehr dünner Wrapper um QMap zu sein, der bloß ein paar Methoden umbenennt.
Ein Beispiel für Iteratoren, die ohne Zeiger auskommen wären beispielsweise die Streamiteratoren aus der Standardbibliothek.
Wenn du allgemein wissen möchtest, wie man Iteratoren schreibt, sie dir zuerst einmal die Klassierung unterschiedlicher Pointertypen im Standard an (zum Beispiel hier tabelliert). Da steht, was ein Iterator können sollte. Es ist keine Pflicht, sich da dran zu halten, aber wenn man es tut, kann man anderen Programmierern einfach kommunizieren, was der Iterator kann. Und besser noch, man kann fremdem Programmcode (z.B. den Standardbibliotheksalgorithmen) kommunizieren, was der Iterator kann:
http://www.cplusplus.com/reference/iterator/iterator_traits/
So kann dann ein cleverer Code mittels TMP rausfinden, welcher Algorithmus die beste Wahl für eine gegebene Art von Iterator ist.