Thema: C++ Assigned in C++

Einzelnen Beitrag anzeigen

silver-moon-2000

Registriert seit: 18. Feb 2007
Ort: Schweinfurt
170 Beiträge
 
Delphi XE Professional
 
#6

AW: Assigned in C++

  Alt 28. Sep 2018, 08:19
Hallo,

vorab: Danke für Eure Antworten und die genommene Zeit. Bitte entschuldigt meine späte Reaktion.
Ich habe die Zeit genutzt, Eure Antworten zu verdauen und mich noch etwas weiter im Netz zu informieren...

-> das Problem ist, er hat keinen Computer-Compiler sondern einen 8Bit Microcontroler mit einstellig !KB!-RAM und 2stellig !KB! (Flash)Rom...
Naja, ich arbeite mit dem Mega2560, habe also ~256kB Flash zur Verfügung, an den 8kB SRAM ändert sich jedoch nichts.

Flexible HW Nutzung ist eine nicht unübliche Herausforderung, nur frage ich mich, ob es hier unbedingt der Objektorientierung Bedarf!?...
Da gibt es seit Jahrzehnten bewährt das #IFDEF HAS_XY... so wird auch wirklich nur das übersetzt und gelinkt was real vorhanden&benötigt.
Das spart dann nicht nur den RAM, sondern auch den Programmspeicher als ROM!!! [...]
[...]In C für 8-Bit reicht mir meistens eine optimierte main loop, welche die Events abarbeitet, ganz ohne den RTOS Overhead [...]
Zum Thema Objektorientierung:
Das Programm entstand ursprünglich als rein prozeduraler Ansatz und ist (sowohl software- als auch hardwaretechnisch) gewachsen, bis ich vollkommen den Überblick verloren und einfach nur irgendwie drangefrickelt hatte.
Das soll nun deutlich besser werden, daher schreibe ich das Programm komplett neu.
Hardwaretechnisch bin ich derzeit bei 5 Shields, die aufeinander "gestackt" werden und softwaremäßig bei >2500 LoC und 11 Klassen, obwohl noch nicht alles programmiert ist.

Ja, natürlich ließe sich auch rein prozeduraler Code besser und übersichtlicher strukturieren, als ich das "damals" gemacht habe, aber ich persönlich bin der Meinung, dass bei diesem Funktionsumfang die Übersichtlichkeit, Erweiterbarkeit und Wiederverwendbarkeit bei objektorientiertem Code einfach besser ist.
Mal sehen, ob am Schluss alles in den Flash passt oder ob ich mir mit dem zusätzlichen "Overhead" in den Fuß geschossen habe und doch zu prozeduralem Code wechseln muss.

Zum Thema Compilerdirektive
Die Compilerdirektive #ifdef kenne ich, doch nützt die mir hier leider nicht. Denn was per Direktive nicht einkompiliert wurde, ist ja im Code nicht vorhanden, Änderungen erfordern ein Neukompilieren...
Es kommt jedoch recht häufig vor, dass ich Hardware vom Arduino abziehe oder anstecke, ich will nicht jedes Mal den Code neu komplilieren müssen.
Da der Arduino sowieso über den PC gesteuert werden soll, will ich den "Funktionsumfang" des Arduino in meinem PC-Programm einstellen können.
Um beim obigen Beispiel zu bleiben: Wenn ich ein Einlassventil anschließe, will ich einfach im PC-Programm einen Haken "Einlassventil vorhanden" setzen.
Der Arduino soll dann automatisch eine Instanz von Valve namens inletValve erzeugen. Oder eben keine Instanz erzeugen, wenn kein Einlassventil angeschlossen ist.
Das geht natürlich nur, wenn das inletValve nicht per #ifdef "komplett auskommentiert" ist.

Weil aber, wie gesagt, vor allem der SRAM ziemlich begrenzt ist, will ich versuchen, nur die Objekte zu erzeugen, die ich brauche, bzw. nicht mehr gebrauchte zügig wieder freizugeben.

So ist es zuimdest derzeit angedacht. Wenn ich feststellen sollte, dass der Speicher vorne und hinten nicht reicht, wird mir nichts anderes übrigbleiben, als nur das unmittelbar nötige per Compilerdirektive einzubinden und dann, wenn

sich die Hardware-Zusammensetzung ändert, eben auch den Code neu zu kompilieren...

Allerdings sollten wenigsten die, welche die "Shield's" programmieren mit den Grundregeln der HW nahen nunmal Address & Pointer basierten C/C++ Programmierung vertraut sein.
Leider ist dies nicht immer der Fall.
Du hast sooo Recht. Immer diese Maker & Noobs, die keine Ahnung haben, die kosten einem wirklich den letzten Nerv! Schlimm sowas!!! (diesen Satz bitte mit einer riesigen Portion Humor lesen! Schau doch auch einfach mal in meine Signatur)


Nein, im Ernst, Du HAST Recht, wer hardwarenah "bastelt", sollte sich auch mit der zugehörigen programmierung auskennen. Auf der anderen Seite ist noch kein Meister vom Himmel gefallen, daher frage ich ja hier
Ich halte mich für einen Einsteiger, dem die prozedurale und objektorientierte (und somit relativ abstrakte) Programmierung halbwegs vertraut ist. Ich gebe aber frei zu, dass ich mich abseits von Delphi weniger gut auskenne, besonders im

hardwarenahen / lowlevel Bereich

Soll heißen:

Ist dir klar, das Delphi ClassObjekte nur "Zeiger" sind und nur Delphi RecordObjekte dem von dir hier gezeigtem C++ Style der Adruino direkt vergleichbar wären?
[...]
Soweit so gut und einfach in "echtem" C++... einfach als Pointer anlegen und mit new erzeugen...
Auf der einen Seite ist mir durchaus klar, dass ein Delphi-"Klassenobjekt" eigentlich ein Pointer ist. Die Tatsache, dass bei Delphi jedoch "im Normalfall" eine direkte Zeiger-Manipulation selten vorkommt, hat dafür gesorgt, dass ich

mich wenig mit Pointern und "manueller" Speicher-Allokation beschäftigt habe.

Code:
anlegen
Valve *pinletValve;
if(hasInValve) pinletValve = new Valve(...); else pinletValve=NULL;
Die Art und Weise, wie Du - vielen Dank im Übrigen für die Erklärung - in C++ die Instanz mit Pointern über new anlegst, war mir zwar (wenn auch eingerostet) vertraut,
was mir aber nicht so klar war, war der Unterschied zwischen Pointern, Referenzen und automatischen/nicht-dynamischen Objekten und dass ich die anscheinend wild vermischt hatte.

Zitat von https://www.c-plusplus.net/forum/topic/332446/unterschied-referenz-zeiger:
eine Referenz kann nicht 0 sein, muss auf etwas vorhandenes initalisiert sein und darf nachträglich nicht geändert werden - das sind ganz ordentliche Unterschiede zu Zeigern
Zitat von http://cseweb.ucsd.edu/~kube/cls/100/Lectures/lec2/lec2-12.html:
Here x refers directly to an object, an instance of the class C (not a pointer!), created automatically on the stack, and initialized with the default constructor.
[...]
C x
[...]
Bisher dachte ich, dass ich mit
Code:
Valve inletValve
bzw. FINletValve : TValve; nur eine "leere / nicht initialisierte" Klassenvariable (mit dem Speicherverbrauch eines Pointers) anlege.
So ist es ja, wenn ich nicht vollkommen auf dem Schlauch stehe, in Delphi.

Dass in C++ automatisch der Standard-Konstruktor aufgerufen und ein Objekt erzeugt und der Speicher reserviert wird, war mir so nicht klar.
Ich dachte, dass eine Instanz erst erzeugt wird mit einem "expliziten" Constructor-Aufruf
Code:
 inletValve = Valve(...)
.

Dem ist anscheinend nicht so. Das aber erklärt so einiges, mir sind ein paar Sachen klarer geworden.
Dies sind eben die Unterschiede in den einzelnen Programmiersprachen, die mir weniger vertraut sind.

Nochmals Danke an Euch.
Tobias
Bitte nicht hauen , ich weiß es nicht besser
  Mit Zitat antworten Zitat