Kann man überladen []
Bediener zweimal? Zuzulassen, etwa so: function[3][3]
(wie in einem zweidimensionalen Array).
Wenn es möglich ist, würde ich gerne einen Beispielcode sehen.
Eispopo
Kann man überladen []
Bediener zweimal? Zuzulassen, etwa so: function[3][3]
(wie in einem zweidimensionalen Array).
Wenn es möglich ist, würde ich gerne einen Beispielcode sehen.
Seth Carnegie
Sie können überladen operator[]
um ein Objekt zurückzugeben, das Sie verwenden können operator[]
nochmal um ein Ergebnis zu bekommen.
class ArrayOfArrays {
public:
ArrayOfArrays() {
_arrayofarrays = new int*[10];
for(int i = 0; i < 10; ++i)
_arrayofarrays[i] = new int[10];
}
class Proxy {
public:
Proxy(int* _array) : _array(_array) { }
int operator[](int index) {
return _array[index];
}
private:
int* _array;
};
Proxy operator[](int index) {
return Proxy(_arrayofarrays[index]);
}
private:
int** _arrayofarrays;
};
Dann können Sie es wie folgt verwenden:
ArrayOfArrays aoa;
aoa[3][5];
Dies ist nur ein einfaches Beispiel, Sie würden gerne eine Reihe von Begrenzungsprüfungen und so etwas hinzufügen, aber Sie verstehen die Idee.
könnte einen Destruktor verwenden. Und Proxy::operator[]
sollte zurückkehren int&
nicht nur int
– Ryan Haining
16. Dezember 2013 um 6:14 Uhr
Besser zu verwenden std::vector<std::vector<int>>
um Speicherlecks und seltsames Verhalten beim Kopieren zu vermeiden.
– Jarod42
20. August 2014 um 12:35 Uhr
Beide Boosts multi_array
und extent_gen
sind gute Beispiele für diese Technik. boost.org/doc/libs/1_57_0/libs/multi_array/doc/…
– alfC
23. Januar 2015 um 22:06 Uhr
Aber, const ArrayOfArrays arr; arr[3][5] = 42;
in der Lage sein, Kompilierung und Änderungen zu übergeben arr[3][5]
was sich irgendwie von der Erwartung der Benutzer unterscheidet arr
ist const
.
– abcdabcd987
8. November 2015 um 12:45 Uhr
@ abcdabcd987 Das ist aus mehreren Gründen nicht richtig. Zuerst, Proxy::operator[]
gibt in diesem Code keinen Verweis zurück (vorausgesetzt, Ihr Kommentar ist keine Antwort auf Ryan Haining). Noch wichtiger, wenn arr
ist dann konstant operator[]
kann nicht benutzt werden. Sie müssten eine konstante Version definieren, und natürlich würden Sie sie zurückgeben const Proxy
. Dann Proxy
selbst hätte konstante und nicht konstante Methoden. Und dann würde Ihr Beispiel immer noch nicht kompilieren, und der Programmierer wäre froh, dass im Universum alles in Ordnung ist. =)
– Reisfeld
5. April 2016 um 6:20 Uhr
Insbesondere für ein zweidimensionales Array könnten Sie mit einem einzigen Operator davonkommen[] -Überladung, die einen Zeiger auf das erste Element jeder Zeile zurückgibt.
Dann können Sie den integrierten Indizierungsoperator verwenden, um auf jedes Element innerhalb der Zeile zuzugreifen.
Sieht für mich nach der praktischsten und effizientesten Lösung aus. Frage mich, warum es nicht mehr Stimmen bekommt – vielleicht, weil es nicht den auffälligen Code hat.
– Yigal Reiss
26. April 2017 um 19:20 Uhr
Ein Ausdruck x[y][z]
benötigt das x[y]
wertet zu einem Objekt aus d
das unterstützt d[z]
.
Dies bedeutet, dass x[y]
sollte ein Objekt mit einem sein operator[]
das wertet zu einem “Proxy-Objekt” aus Auch unterstützt ein operator[]
.
Nur so können sie verkettet werden.
Alternativ überladen operator()
um mehrere Argumente zu nehmen, so dass Sie aufrufen könnten myObject(x,y)
.
Warum erlaubt die Überladung von Klammern, zwei Eingaben zu erhalten, aber Sie können das nicht mit den Klammern tun?
– A. Raserei
21. Mai 2020 um 22:49 Uhr
@A.Frenzy Weil: 1. das Überschreiben mit 2 Parametern zu einem Aufruf von myObj führen würde[2,3]nicht meinObj[2][3]. und 2. Die Anzahl der Parameter, die der Bediener übernimmt, kann nicht geändert werden [] operator akzeptiert nur einen int, während () eine beliebige Anzahl von Parametern beliebigen Typs akzeptiert.
– Skorpion
18. Dezember 2020 um 13:07 Uhr
Es ist möglich, wenn Sie zuerst eine Art Proxy-Klasse zurückgeben [] Anruf. Es gibt jedoch eine andere Option: Sie können operator() überladen, der eine beliebige Anzahl von Argumenten akzeptieren kann (function(3,3)
).
Ein Ansatz ist die Verwendung std::pair<int,int>
:
class Array2D
{
int** m_p2dArray;
public:
int operator[](const std::pair<int,int>& Index)
{
return m_p2dArray[Index.first][Index.second];
}
};
int main()
{
Array2D theArray;
pair<int, int> theIndex(2,3);
int nValue;
nValue = theArray[theIndex];
}
Natürlich darfst du typedef
der pair<int,int>
Dies wird viel attraktiver mit C++11 und geschweifter Initialisierung. Jetzt kannst du schreiben nValue = theArray[{2,3}];
– Martin Bonner unterstützt Monika
29. September 2016 um 16:51 Uhr
Knoten
Sie können ein Proxy-Objekt verwenden, etwa so:
#include <iostream>
struct Object
{
struct Proxy
{
Object *mObj;
int mI;
Proxy(Object *obj, int i)
: mObj(obj), mI(i)
{
}
int operator[](int j)
{
return mI * j;
}
};
Proxy operator[](int i)
{
return Proxy(this, i);
}
};
int main()
{
Object o;
std::cout << o[2][3] << std::endl;
}
Dies wird viel attraktiver mit C++11 und geschweifter Initialisierung. Jetzt kannst du schreiben nValue = theArray[{2,3}];
– Martin Bonner unterstützt Monika
29. September 2016 um 16:51 Uhr
Es wäre toll, wenn du mir sagen könntest, was function
, function[x]
und function[x][y]
sind. Aber lassen Sie mich es trotzdem als ein Objekt betrachten, das irgendwo deklariert ist
SomeClass function;
(Weil Sie gesagt haben, dass es sich um eine Operatorüberladung handelt, werden Sie sich wahrscheinlich nicht für Arrays interessieren SomeClass function[16][32];
)
Damit function
ist eine Instanz des Typs SomeClass
. Dann schlagen Sie Erklärung von nach SomeClass
für den Rückgabetyp von operator[]
Überlastung, genau wie
ReturnType operator[](ParamType);
Dann function[x]
wird den Typ haben ReturnType
. Schau wieder nach oben ReturnType
für die operator[]
Überlast. Wenn es eine solche Methode gibt, könnten Sie dann den Ausdruck verwenden function[x][y]
.
Beachten Sie, anders function(x, y)
, function[x][y]
sind 2 getrennte Anrufe. Daher ist es für Compiler oder Runtime schwierig, die Atomarität zu garantieren, es sei denn, Sie verwenden eine Sperre im Kontext. Ein ähnliches Beispiel ist, sagt libc printf
ist atomar, während die überladenen nacheinander aufgerufen werden operator<<
im Ausgabestrom sind es nicht. Eine Aussage wie
std::cout << "hello" << std::endl;
könnte ein Problem bei Multi-Thread-Anwendungen haben, aber so etwas wie
printf("%s%s", "hello", "\n");
ist gut.
Übrigens ist es viel einfacher und häufiger zu überladen
operator()(int, int)
stattdessen…– Invers
14. August 2011 um 1:23 Uhr
Warum das Rad nachbauen? Benutz einfach
std::vector
mit einem Bereichskonstruktor: stackoverflow.com/a/25405865/610351– Geoffroy
20. August 2014 um 13:22 Uhr
Oder Sie können einfach etwas wie verwenden
using array2d = std::array<std::array<int, 3>, 3>;
– Benutzer4640261
7. April 2020 um 2:05 Uhr