Rückgabe einer unbekannten Anzahl von Elementen
-
Hi,
ich bräuchte mal ein paar Anregungen zu folgender Aufgabe (MFC-Hintergrund, allerdings ist das eigentliche Problem in diesem Forum besser aufgehoben, denke ich).
In meinem Programm wählt der User innerhalb eines Dialogs eine bestimmte Anzahl von Elementen aus, die aus Paaren eines CString und eines CBitmap* bestehen (Membervariablen der Dialogklasse). Ich will nun eine Methode innerhalb der Dialogklasse implementieren, die diese erst zur Laufzeit bekannte Anzahl von CString/CBitmap* Paaren zurückgibt bzw. zugänglich macht.
Folgende Varianten hatte ich dazu im Auge:
1.)
Ich übergebe der Methode (z.B.) einen std::vector<pair<CString, CBitmap*>>& und fülle ihn innerhalb der Methode mit den entsprechenden Paaren. Also etwas in dieser Art:void GetItems(std::vector<std::pair<Cstring, CBitmap*>>& itemContainer) const;2.)
Ich erzeuge innerhalb der Methode einen solchen vector und gebe diesen zurück:std::vector<std::pair<Cstring, CBitmap*>> GetItems() const;3.) Ich mache die aufrufende Klasse zum friend der Dialogklasse und greife direkt auf deren Membervariablen zu.
Zu diesen Ideen würde ich gerne ein paar Meinungen hören.
Welche Variante würdet ihr bevorzugen?
Sind alle drei gleichermaßen unbrauchbar? Wie würdet ihr das dann machen?Ich dachte, Variante 1 hat gegenüber 2 den Vorteil, dass keine Kopie des vectors erstellt werden muss.
Variante 3 wäre sicher bequem, aber ich dachte, das sollte man vielleicht vermeiden, wenn es auch anders geht.
-
Persönlich würde ich Variante 2 bevorzugen, weil sie am besten ausdrückt, was die Funktion tut. Variante 1 ist unter dem Gesichtspunkt der vermiedenen Kopie auch legitim - im Grunde geht es dabei ja nur um eine sprachtechnische Sache. Ob man dafür etwas Klarheit beim Interface opfern will, muss abgewogen werden. Übrigens lässt sich das Kopieren bei Variante 2 ebenfalls vermeiden:
- bei der Konstruktion des Rückgabewertes verlassen wir uns auf NRVO
- bei der Zuweisung/Intialisierung beim AUfrufer können wir auf swap ausweichen (nicht sehr schön, aber Move-Konstruktoren wird es erst in C++0x geben):vector<foo> bar(); int main() { vector<foo> x; bar().swap(x); }Variante 3 ist ein sehr böser Hack und an sich nicht diskussionswürdig.
-
Dann bin ich zunächst mal froh, dass ich nicht völlig auf dem Holzweg war! Ich werde also noch ein wenig abwägen und mich dann für eine der beiden ersten Varianten entscheiden

camper schrieb:
Variante 3 ist ein sehr böser Hack und an sich nicht diskussionswürdig.
Sehe ich ja ein, mir ist nur kein besserer dritter Vorschlag eingefallen...Danke jedenfalls für die Tipps!
-
Variante 4:
class Foo { public: template <class OutputIterator> void GetItems(OutputIterator outIt) const { // for all elements() { *outIt = ... outIt++; } } // ... };
-
@hustbaer: sehr schön
Denkt man in dieser Richtung etwas weiter, stellt sich die Frage, ob nicht der Dialog selbst ein Iteratorinterface haben sollte. Dann erübrigt sich eine Funktion GetItems.