Problem bei Operatorüberladung [] und =
-
Hallo, ich bin neu hier bei euch und hätte mal eine kleine Frage. Es geht um Operator Überladung.
Ich habe an einen AVR Xmega zusätzlichen SRAM(512kb) angeschlossen. Dummerweise kann der avr-g++ diesen nicht verwalten. Also habe ich mir eine kleine Klasse geschrieben mit der ich mir zumindest schonmal "Arrays" dynamisch im externen RAM anlegen kann. Das funktioniert soweit auch schonmal ganz gut. Jetzt möchte nur noch, mit Hilfe von Operatorüberladung, auf die einzelnen Elemente wie bei einem Array zugreifen.
Derzeit sieht das ganze bei mir so aus:
ExtRAM* test1 = new ExtRAM(100); test1->writeByte(5, 0xAA); uint8_t value5; value5 = test1->readByte(5);Ich würde das ganze aber gerne so verwenden:
ExtRAM* test1 = new ExtRAM(100); test1[5] = 0xAA uint8_t value5; value5 = test[5];Probiert habe ich das ganze so (Auszug):
class ExtRAM { public: uint8_t operator[](uint32_t const index); } uint8_t ExtRAM::operator[](uint32_t const index) { return this->readByte(index); } int main(void) { ExtRAM* test1 = new ExtRAM(100); uint8_t value5; value5 = test1[5]; }Nur leider funktioniert das nicht. Der Compiler sagt mir
Error 11 cannot convert 'ExtRAM' to 'uint8_t {aka unsigned char}' in initializationUnd wie kann ich es anstellen das, dass auch bei einer Zuweisung funktioniert
test[5] = 0xAAAchja: die datentypen uint8_t und uint32_t gehören auf den AVR's zu den Standartdatentypen.
Ich hoffe das ihr mir helfen könnt

-
Warum legst du test1 mit new an? Dann muss es (*test1)[5] heissen.
Zum Lesen kannst du den Operator verwenden, zum Schreiben müsste er aber eine Referenz liefern.
-
manni66 schrieb:
Warum legst du test1 mit new an? Dann muss es (*test1)[5] heissen.
Danke, manchmal bin ich echt zu blöd. Klar muss ich (*test1)[5] so drauf zugreifen. Ist ja ein Zeiger. Und natürlich macht es in meinen einfachen Beispiel keinen Sinn test1 mit new anzulegen. Aber später schon ;).
manni66 schrieb:
Zum Lesen kannst du den Operator verwenden, zum Schreiben müsste er aber eine Referenz liefern.
Und das kann ich nicht. Ist ja ein einfaches Byte was ich aus meinem externen RAM hole.
-
Neo87 schrieb:
manni66 schrieb:
Zum Lesen kannst du den Operator verwenden, zum Schreiben müsste er aber eine Referenz liefern.
Und das kann ich nicht. Ist ja ein einfaches Byte was ich aus meinem externen RAM hole.
Wieso soll man ein einfaches Byte nicht per Referenz übergeben können?
Meinst du, dass du eine komische Funktion benutzen musst um an den externen RAM ranzukommen und deshalb dieses Byte keine Adresse hat, ähnlich zu Bytes auf der Festplatte?
Dann kann vielleicht ein Wrapper helfen:struct ByteWrapper{ operator uin8(){ //zum Lesen, damit sich ein ByteWrapper wie ein uint8 verhält return byte; } ByteWrapper &operator= (uint8 b){ //damit du ein ByteWrapper wie ein normales uint8 beschreiben kannst byte = b; writeByte(adresse, byte); return *this; } ByteWrapper(unsigned int adresse){ byte = readByte(adresse); } private: uint8 byte; unsigned int adresse; //im externen RAM }; struct ExternerRam{ ByteWrapper operator[] (unsigned int adresse){ return ByteWrapper(adresse); } }; //zu benutzen: ExternerRam eram; void tuwas(uint8); tuwas(eram[42]); //ließt den externen RAM eram[5] = 17; //schreibt in den externen RAMEs gibt da noch das Problem, dass die letzte Zeile von Adresse 5 liest, was Quatsch ist. Das kriegt man aber auch noch irgendwie weg.
Ich hoffe mal meine Glaskugel lag nicht völlig falsch.
-
sry, dass ich mich erst jetzt melde, ich hatte das ganze schon ad acta gelegt. Aber ja, deine Glaskugel hat vollkommen recht. Da der avr-g++ leider nur 16bit Pointer verwendet ist er nicht in der Lage die externen 512kB anzusprechen.
Also komme ich nur via Inline Assambler an den externen RAM.Nen Wrapper zu verwenden ist da natürlich ne super Idee. Wäre ich alleine nie drauf gekommen.
Nur leider musste ich mein Projekt auf Grund von Platzmangel ein wenig umstellen, so das ich von solchem Luxus zurzeit nur noch träumen kann.Aber trotzdem danke für den Tipp.
-
Neo87 schrieb:
manni66 schrieb:
Warum legst du test1 mit new an? Dann muss es (*test1)[5] heissen.
Und natürlich macht es in meinen einfachen Beispiel keinen Sinn test1 mit new anzulegen. Aber später schon ;)..
Ähm, nur um was klar zu stellen:
Es macht nie Sinn etwas mit new[] anzulegen.
-
Nathan schrieb:
Es macht nie Sinn etwas mit new[] anzulegen.
Es macht in einem µC auch nie Sinn, new[] indirekt (z.B. durch std::vector) zu verwenden.
-
mükro schrieb:
Nathan schrieb:
Es macht nie Sinn etwas mit new[] anzulegen.
Es macht in einem µC auch nie Sinn, new[] indirekt (z.B. durch std::vector) zu verwenden.
natürlich macht kapselung keinen sinn! wo sind wir denn hier? bei c++?????
-
Nathan schrieb:
Es macht nie Sinn etwas mit new[] anzulegen.
Ja, nee ist klar!

-
knivil schrieb:
Nathan schrieb:
Es macht nie Sinn etwas mit new[] anzulegen.
Ja, nee ist klar!

dann nenn mir einen einzigen fall, in welchem new[] einem stl-container vorzuziehen ist
-
Beim Backend eines selbstgeschriebenen Allokators.

-
Schreib mal ein Beispiel wo man bereits einen Konstruktoraufruf braucht und nicht nur rohen Speicher benötigt.
-
Skym0sh0 schrieb:
Beim Backend eines selbstgeschriebenen Allokators.

Dort tust du aber nicht new[] verwenden, sondern operator new()
PS:
ich gebe Nathan recht: new[] braucht man nicht.(und jede Regel hat eine Ausnahme - aber um ehrlich zu sein, ich habe new[] noch nie in production Code verwendet).
-
Wer hat denn hier von new[] gesprochen?
Ich habe doch ledigtlich ein Objekt mit new angelegt. Dieses Objekt enthält nichts weiter als eine Speicherbereich auf meinem externen RAM(da ich diesen nur per inline-Assambler ansprechen kann). Jetzt wollte ich doch ledigtlich auf die einzeilnen Elemente per objekt[index] zugreifen, statt per objekt->readbyte(index).
-
knivil schrieb:
Nathan schrieb:
Es macht nie Sinn etwas mit new[] anzulegen.
Ja, nee ist klar!

So pauschal meinte er das nicht. Es geht um Code, in dem Bausteine um
new[]zu umgehen bereits unmittelbar vorhanden sind. Einen STL-Container in einem Allokator zu verwenden ist sinnfrei, da dieser den allozierten Speicher nicht besitzt. Aber sobald STL-Container definiert sind, also Konstrukte die (im Sinne von RAII) den Speicher besitzen, ist rohe Speicherallozierung ein Tabu.Dort tust du aber nicht new[] verwenden, sondern operator new()
Shade, dieser Scherzkeks.

Es ist nämlich ::operator new(). ~Zumindest beim Standardallokator.~
-
Sone schrieb:
[Sonntagspredigt]
Wie immer ignorieren wir fleissig mindestens einen nebensächlichen Fakt. Hier um einen Microcontroller mit 512kb(!) RAM handelt. Auf Microcontrollern verwendet man besser keine C++-Standardbibliothek (wobei sie oft auch gar nicht vorhanden ist. Muss sie auch nicht)
-
facepalm schrieb:
Sone schrieb:
[Sonntagspredigt]
Wie immer ignorieren wir fleissig mindestens einen nebensächlichen Fakt. Hier um einen Microcontroller mit 512kb(!) RAM handelt. Auf Microcontrollern verwendet man besser keine C++-Standardbibliothek (wobei sie oft auch gar nicht vorhanden ist. Muss sie auch nicht)
Habe ich gesagt, dass man immer die STL verwenden soll? Ich habe gesagt, man soll nie
new[]roh verwenden! Auf einem Mikrokontroller wird man auch irgendwie RAII nehmen - wenn man das nicht tut, dann kann man gleich zu C wechseln.P.S.: Mein Mikrokontroller hat 2kB RAM. 512 sind ziemlich viel. Man sieht, du hast Erfahrung mit solchen Zahlen (!).

-
facepalm schrieb:
Sone schrieb:
[Sonntagspredigt]
Wie immer ignorieren wir fleissig mindestens einen nebensächlichen Fakt. Hier um einen Microcontroller mit 512kb(!) RAM handelt.
Nicht ganz
der eigentliche Mikrocontroller hat nur 16kb RAM, ich habe aber 512kb externen SRAM am EBI hängen!
Wie schon geschrieben kann der AVR-G++ den aber nicht verwalten, dar er nur mit 16bit Pointern arbeitet. Ich muss mich also um die 512kb von Hand kümmern und kann dort nur "Werte" ablgegen und keine Objekte erzeugen (Jedenfalls wüsste ich nicht wie?).
Deswegen meine ExtRAM-Klasse, diese legt im internen RAM ein Objekt an welches die Speicheradresse zum externen RAM beinhaltet. Dabei organiesiere ich meinen externen RAM wie einen Heap. Ich kann also Speicher reservieren und wieder freigeben. Ich wollte jetzt ledigtlich darauf wie auf ein Array, per [index], zugreifen.P.S. Und man kann C++ sehr wohl sinnvoll auf einem Mikrocontroller einsetzten. Gerade bei größeren Projekten wie meinem. Touchscreen, Bluetooth, 96 LEDs mit 12bit-PWM, 4x32Mbit-Flash, diverse Sensoren.
Gerade bei der GUI möchte ich nicht auf den Komfort verzeichten mal eben per new UIButton mir einen Button zu erzeugen
-
Gerade bei der GUI möchte ich nicht auf den Komfort verzeichten mal eben per new UIButton mir einen Button zu erzeugen
Ja, aber ich bete dafür, dass du Smart-Pointer verwendest.
-
Sone schrieb:
Ja, aber ich bete dafür, dass du Smart-Pointer verwendest.
Nein, warum sollte ich?