Hi, wie muss ich einen Datentypen ausprägen wenn ich über das Objekt eine Funktion aufrufen möchte? Beispiel: MeinDatentyp_t Lampe; ich möchte dann im code beispielsweise schreiben können: Lampe.an(); Lampe.aus(); Lampe.init(); oder Lampe.setzeWert(255); oder oder oder das würde ich ja über einen typedef struct machen: Lampe.wert=255; Aber wie bekomme ich die Funktionen ins spiel an der stelle? Danke Gruß JJ
npn schrieb: > Was willst du damit sagen? Dass bei ihm die Taste 'k' klemmt.
:
Bearbeitet durch Moderator
Ich glaube so müsste es gehen: struct { void (*An)(void); void (*Aus)(void); }Lampe; void main (void) { Lampe.An = An(); // Eigendliche An Funktion dem Struct zuweisen Lampe.Aus = Aus(); // Selbe wie aus while(1) { Lampe.An(); Lampe.Aus(); } }
Du möchtest Methoden von Strukturen aufrufen. Das gibt es nicht. Nur Objekte haben Methoden.
Waldfee schrieb: > Ich glaube so müsste es gehen: > > struct > { > void (*An)(void); > void (*Aus)(void); > }Lampe; > > void main (void) > { > Lampe.An = An(); // Eigendliche An Funktion dem Struct zuweisen > Lampe.Aus = Aus(); // Selbe wie aus > > while(1) > { > Lampe.An(); > Lampe.Aus(); > } > > } Sorry Fehler entdeckt... void main (void) { Lampe.An = An; // Eigendliche An Funktion dem Struct zuweisen Lampe.Aus = Aus; // Selbe wie aus while(1) { Lampe.An(); Lampe.Aus(); } } void An(void) void Aus(void)
Jens schrieb: > wie muss ich einen Datentypen ausprägen wenn ich über das Objekt eine > Funktion aufrufen möchte? Es gibt keine Objekte in C. Hier gibt es lediglich Datenstrukturen, wo man mittels Pointer to Functions etwas objektähnliches zusammenschustern kann. Nach Deiner Frage zu urteilen ginge so ein C-Hack weit über Deine momentanen Fähigkeiten hinaus. Beantworte erstmal die Frage: C oder C++ ? Wenn Du Objekte meinst, meinst Du wahrscheinlich C++. Ich rate Dir die Lektüre eines guten C++-Buchs, um solche elementare Dinge wie Objekte und der darauf anzuwendenden Funktionen (Methoden) zu lernen. Ein Forum ersetzt nicht das Lernen.
Man kann es Objektorientierung in C nachbauen, es geht ist aber nicht sehr schon. Man erstellt eine Struktur mit allen Objektvariablen und Funktionspointer für die Methoden struct MyClass { int (*myMethod)( void* o , int myParam1); }; Eine Funktion die das New repräsentiert: MyClass* MyClass_new(); // für dynamisch mit malloc oder MyClass myObjekt; void MyClass_init(&myObjekt); // static ohne malloc und kann dann die Methode ober das Objekt aufrufen int ret = myObjekt.myMethod(&myObjekt, 123); Leider muss man immer den Kontext, also das Objekt, mit als Parameter angeben. Hier ist ein Beispiel wie man sowas Anwendet: https://github.com/christiankarsch/RP6-I2C-Demo/blob/master/src/lib/linux/i2c/linux_i2c.h
Das Problem: C hat keinen impliziten Self-Pointer. Dadurch brauchst Du entweder für jede Variable (Instanz) eine eigene Funktion An(). Oder musst einen Pointer auf sich selbst übergeben (Self-Pointer). Dadurch sind einzelne Funktionen (Lampe_an(&lampe1)) meist genauso gut (oder schlecht;)
Jens schrieb: > ich möchte dann im code beispielsweise schreiben können: > > Lampe.an(); > Lampe.aus(); > Lampe.init(); Ersetze einfach den '.' durch '_':
1 | Lampe_an(); |
2 | Lampe_aus(); |
3 | Lampe_init(); |
so geht's doch prima (wenn man das unbedingt haben will):
1 | #include <stdio.h> |
2 | |
3 | void an(void) |
4 | {
|
5 | printf("an\n"); |
6 | }
|
7 | |
8 | void aus(void) |
9 | {
|
10 | printf("aus\n"); |
11 | }
|
12 | |
13 | struct lampe |
14 | {
|
15 | void (*an)(void); |
16 | void (*aus)(void); |
17 | } lampe = |
18 | {
|
19 | &an, |
20 | &aus |
21 | };
|
22 | |
23 | int main(int argc, char *argv[]) |
24 | {
|
25 | lampe.an(); |
26 | lampe.aus(); |
27 | }
|
Nach einem this-Pointer hat bislang keiner gefragt.
Markus F. schrieb: > Nach einem this-Pointer hat bislang keiner gefragt. Erst wenn es zwei Lampen werden ^^
CK schrieb: > Markus F. schrieb: >> Nach einem this-Pointer hat bislang keiner gefragt. > > Erst wenn es zwei Lampen werden ^^ braucht man immer noch keinen this-pointer:
1 | ...
|
2 | struct lampe |
3 | {
|
4 | void (*an)(void); |
5 | void (*aus)(void); |
6 | } lampe[] = |
7 | {
|
8 | {
|
9 | &an1, |
10 | &aus1 |
11 | },
|
12 | {
|
13 | &an2, |
14 | &aus2 |
15 | }
|
16 | };
|
17 | |
18 | int main(int argc, char *argv[]) |
19 | {
|
20 | lampe[0].an(); |
21 | lampe[1].aus(); |
22 | }
|
Markus F. schrieb: > braucht man immer noch keinen this-pointer: Nein, das besagt das "entweder oder" in Achim S. schrieb: > Dadurch brauchst Du entweder für jede Variable (Instanz) eine eigene > Funktion An(). Oder musst einen Pointer auf sich selbst übergeben > (Self-Pointer).
Dann nimm doch einfach C++. Meist reicht es, im Makefile den gcc durch g++ zu ersetzen.
BTW: für echte HW, z.B physikalische Uarts des uC, nutze ich das exsessiv, also z.b. uart1.put(c); Der Bildprozess kopiert uart2.c ... uart5.c automatisch, entsprechende Header enthalten die spezifischen Register etc. Der Code wird dadurch sauschnell, straight und nicht viel größer als ein generischer.
Achim S. schrieb: > uart1.put(c); und was ist da jetzt soviel toller als zu schreiben writeUart(uart1, c); Nix!
Unglaublich schrieb: > und was ist da jetzt soviel toller als zu schreiben writeUart(uart1, c); > > Nix! Objekte bekommen dann erst Sinn, wenn es sich um Dinge handelt, die zur Laufzeit entstehen, Zustand/Verhalten haben und wieder verschwinden. GUI-Elemente etwa, oder Objekte in Simulationen (wo OOP ja herkommt). Bei statischen Objekten wie UARTs, die sich in Geräten normnalerweise nicht anlegen und verschwinden, ist das bloß syntaktischer Zucker.
Finde Dich mit dieser Schreibweise ab:
1 | void lampe_an(lampe_t* this) { |
2 | this->gpio->PSOR = this->bitmask; // oder so ähnlich |
3 | }
|
1 | lampe_an(&lampe1); |
2 | |
3 | fifo_push(&tx_fifo, 42); |
4 | |
5 | //etc...
|
Es schreit zwar laut "ich bin C" aber besser oder schöner oder kürzer wirds in dieser Sprache nun mal nicht werden, egal wie viele Verrenkungen Du machst. Diese Notation ist ehrlich und macht keinen Hehl daraus was sie ist, auch OOP-Ablehner verstehen sofort intuitiv was das ist und hättens vielleicht sogar selbst genauso gemacht (obwohl es streng genommen tatsächlich ein Konzept von OOP implementiert).
:
Bearbeitet durch User
Nop schrieb: > Objekte bekommen dann erst Sinn, wenn es sich um Dinge handelt, die zur > Laufzeit entstehen, Oder wenn es mehrere von der selben Sorte gibt, zum Beispiel 3 identische UARTs die sich nur im Registeroffset unterscheiden. Dann macht man sich ein struct mit nem Zeiger aufs uart und den beiden fifos und eine handvoll Funktionen die auf so ein Struct anwendbar sind und fertig ist die Klasse mit ihren Methoden und man kann 3 Instanzen davon statisch erzeugen und benutzen.
:
Bearbeitet durch User
Bernd K. schrieb: > Oder wenn es mehrere von der selben Sorte gibt, zum Beispiel 3 > identische UARTs die sich nur im Registeroffset unterscheiden. Dann übergibt man die UART-ID und erschlägt damit DRY genauso.
Nop schrieb: > Bernd K. schrieb: > >> Oder wenn es mehrere von der selben Sorte gibt, zum Beispiel 3 >> identische UARTs die sich nur im Registeroffset unterscheiden. > > Dann übergibt man die UART-ID und erschlägt damit DRY genauso. Und wo willst Du die jeweils zwei (also insgesamt 6) Fifos unterbringen und vielleicht noch irgendwelchen zusätzlichen state? In meinen Fall mach ich ne fifo-Klasse und ne UART-Klasse und jede UART-Instanz hält zwei Zeiger auf ihre beiden Fifo-Instanzen und den Zeiger auf die UART-Hardware.
:
Bearbeitet durch User
Jens schrieb: > ich möchte dann im code beispielsweise schreiben können: > > Lampe.an(); > Lampe.aus(); > Lampe.init(); Natürlich geht sowas, jedoch in C mit ein bissel Umständen. Guck zu diesem Thema in die Lernbetty. Ein Beispiel daraus:
1 | #define RCST const struct TMenuItem
|
2 | struct TMenuItem |
3 | { struct TRect R; /* die Koordinaten relativ zum Owner */ |
4 | const struct TMenuItem *davor; /* Listenverkettung: Item davor */ |
5 | const struct TMenuItem *danach; /* Listenverkettung: Item danach */ |
6 | const struct TMenuItem *Owner; /* Item, wo dieses enthalten ist */ |
7 | const struct TMenuItem *Members; /* Liste der enthaltenen Items */ |
8 | dword Flags; /* diverse Flag-Bits */ |
9 | void *Data; /* Zeiger auf fallspezifische Daten */ |
10 | void (*OnKey) (RCST* self, word *aKey); /* wertet Tastendrücke aus */ |
11 | void (*OnEvent)(RCST* self, word *aEvent); /* wertet Ereignisse aus */ |
12 | void (*Draw) (RCST* self); /* zeichnet sich und Members */ |
13 | };
|
14 | [/] |
15 | |
16 | Bemerke, daß die Quasi-Methoden hier explizit als 1. Argument den Zeiger auf "ihr" Objekt haben müssen (RCST* self), weil sie ja ansonsten nicht wissen können, wessen Methode sie gerade sind. |
17 | Benutzbar ist das dann etwa so: |
18 | [c] |
19 | extern void PanelKeyHandler (RCST *self, word *aKey); |
20 | extern void PanelEventHandler (RCST* self, word *aEvent); |
21 | extern void PanelDrawProc (RCST* self); |
22 | |
23 | RCST ADCsee_Mainmenu = |
24 | { /* l-t-r-b */ { 0, 0, 127, 159}, |
25 | /* davor */ 0, |
26 | /* danach */ 0, |
27 | /* Owner */ 0, |
28 | /* Members*/ &ADCsee_Batterie, |
29 | /* Flags */ opaque, |
30 | /* *Data */ (void*) &ADCsee_Mainmenu_focussed, |
31 | /* OnKey */ PanelKeyHandler, |
32 | /* OnEvent*/ PanelEventHandler, |
33 | /* Draw */ PanelDrawProc |
34 | };
|
35 | |
36 | ... usw. |
So etwa geht das, wenn man Objekte in C formulieren will und selbige im Flash positionieren will, um keinen RAM dafür zu verplempern und auch keine Heapverwaltung einführen zu müssen. W.S.
Unglaublich schrieb: > was ist da jetzt soviel toller als Ich habe einige offensichtliche Vorteile aufgeführt. Hinzu kommt z.B. die Möglichkeit, einen Breakpoint zu setzen und einfach dry. Bei größeren Projekten kommen weitere Vorteile hinzu, Stichwort Lesbarkeit. Da Code-Kopien aber per se böse sind, Lohnt es sich meist nicht, über den Unterschied von Copy Paste und automatisierten Kopien zu streiten. Nop schrieb: > Objekte bekommen dann erst Sinn, wenn es sich um Dinge handelt, die zur > Laufzeit entstehen, Genau. Da macht OOP Sinn. Konkrete Dinge hingegen brauchen meist konkreten Code.
Bernd K. schrieb: > Und wo willst Du die jeweils zwei (also insgesamt 6) Fifos unterbringen Das geht mit ein paar typedefs, und am Ende habe ich dann ein Array, dessen erster Index gerade die UART-ID ist.
Bernd K. schrieb: > Finde Dich mit dieser Schreibweise ab: > void lampe_an(lampe_t* this) { > this->gpio->PSOR = this->bitmask; // oder so ähnlich > } So schreibt man das nur, wenn man ganz sicher weiß, daß den Code niemals ein C++ Compiler zu sehen bekommen soll (also lieber gar nicht). Ansonsten nimmt man eher (z.B.) "self" oder man muss im Fall der Fälle alles nochmal anfassen.
typedef struct { uint8_t Helligkeit; void (*an)(void); void (*aus)(void); } lampe_t; lampe_t Glühobst, Funzel; int main(void) { Glühobst.an(); Funzel.an(); } Wie bekommt man es hin, bzw. ist es möglich das *.an() Helligkeit jeweils auf 255 setzt? Danke Gruß
Markus F. schrieb: > Ansonsten nimmt man eher (z.B.) "self" Ich würd ja einen aussagefähigen Namen nehmen, in dem Fall beispielsweise einfach "lampe". Oder noch mit ungarischen Gewürzen davor.
DS schrieb: > Wie bekommt man es hin, bzw. ist es möglich das *.an() Helligkeit > jeweils auf 255 setzt? Ohne Self-Pointer und ohne C++ nur mit einer eigenen an-funktion je Lampe. Also nichts für Anfänger.
>>Also nichts für Anfänger. wieso, bin nur neugierig, bis jetzt ist doch noch nichts schlimmes dabei :-) >>mit einer eigenen an-funktion je Lampe das ist ja schade. Gibt es in C wirklich keine Möglichkeit für die Funktion an() "herauszufinden" von wo sie aufgerufen wurde um den richtigen Speicher zu beackern? Gruß DS
DS schrieb: > Gibt es in C wirklich keine Möglichkeit für die Funktion an() > "herauszufinden" von wo sie aufgerufen wurde um den richtigen Speicher > zu beackern? Der wesentliche Unterschied zwischen einer Methode eines Objektes (C++) und einem Funktionspointer in einem struct (c) ist der, daß die aufgerufene Funktion in letzterem Falle keine Information hat, zu welchem Objekt das jetzt gehört. Bei objektorientierten Sprachen bekommt die Methode unter der Haube einen versteckten Pointer auf das Objekt, in C hingegen nicht. In C ist diese Funktion aus ihrer eigenen Sicht einfach nur eine void-void-Funktion. Der einzige Weg, wie so eine Funktion an Informationen von außerhalb gelangen kann, sind globale Variablen. Demzufolge könntest Du natürlich vor dem Aufruf eine globale Variable setzen, die in der an()-Funktion abgefragt wird, aber das wäre superhäßlich.
Nop schrieb: > Der wesentliche Unterschied zwischen einer Methode eines Objektes (C++) > und einem Funktionspointer in einem struct (c) ist der, daß die > aufgerufene Funktion in letzterem Falle keine Information hat, zu > welchem Objekt das jetzt gehört. Bei objektorientierten Sprachen bekommt > die Methode unter der Haube einen versteckten Pointer auf das Objekt, in > C hingegen nicht. Grundsätzlich hast du natürlich vollkommen recht! Allerdings ist unser Gcc C++ soweit entwickelt, dass das nicht mehr unter allen Umständen so ist. Selbst die Referenz, also der Halter einer Instanz, und damit auch this kann u.U. vollständig weg optimiert werden. Das macht C++ auf µC etwas praktikabler, weniger Speicher/Ram fressend. Erst wenn das Objekt Eigenschaften(Variablen im Bauch) hat, dann führt kein Weg mehr an this vorbei.
Arduino F. schrieb: > Selbst die Referenz, also der Halter einer > Instanz, und damit auch this kann u.U. vollständig weg optimiert werden. Das schon, aber der Punkt ist, daß überhaupt was DA ist, was ggf. auch wegoptimiert werden kann.
DS schrieb: > Gibt es in C wirklich keine Möglichkeit für die Funktion an() > "herauszufinden" von wo sie aufgerufen wurde um den richtigen Speicher > zu beackern? auch C++ "findet" das nicht raus. Der this-Zeiger wird einfach "unsichtbar" mitgegeben und ist implizit Bestandteil des Methodenaufrufs. Die ersten C++ Compiler haben (als Präprozessor) genauso funktioniert. Vom Präprozessor wurde C-Code erzeugt und das Ergebnis schlussendlich von einem C-Compiler verwurstet. Allerdings sollte man wohl fairerweise sagen, dass dieses C++ mit heutigem nicht wirklich viel gemein hatte. Man kann Objektorientierung in C noch viel weiter treiben. Ob das allerdings sinnvoll ist, ist eine andere Frage: Anfänger verwirrt man damit nur und alle anderen sollten lieber gleich C++ nehmen, das ist schliesslich dafür gemacht.
Markus F. schrieb: > Bernd K. schrieb: >> Finde Dich mit dieser Schreibweise ab: >> void lampe_an(lampe_t* this) { >> this->gpio->PSOR = this->bitmask; // oder so ähnlich >> } > > So schreibt man das nur, wenn man ganz sicher weiß, daß den Code niemals > ein C++ Compiler zu sehen bekommen soll (also lieber gar nicht). Nö, das genaue Gegenteil ist der Fall. In C++ heißt dieser Pointer ebenfalls this, also kann ich beim Portieren von C nach C++ das meiste einfach so lassen wie es ist. > oder man muss im Fall der Fälle > alles nochmal anfassen. Anfassen muss ich es eh wenn ich es nach C++ portiere aber wenn der this-Pointer zufällig in weiser Voraussicht schon this heißt muss ich weniger anfassen.
:
Bearbeitet durch User
W.S. schrieb: > Ein Beispiel daraus: Es ist ja schön für Dich, daß Du ne Menüsteuerung programmiert hast. Aber für nen Anfänger ist es nur sehr schwer, daraus Erkenntnisse für völlig andere Aufgaben abzuleiten. Beispiele sollten einfach sein und nicht hoch komplex. W.S. schrieb: > Bemerke, daß die Quasi-Methoden hier explizit als 1. Argument den Zeiger > auf "ihr" Objekt haben müssen (RCST* self), weil sie ja ansonsten nicht > wissen können, wessen Methode sie gerade sind. Dieser Satz sagt mir, daß C++ überhaupt gar nichts für mich ist. Ich hab nicht mal die allerkleinste Idee, was er bedeuten könnte. W.S. schrieb: > So etwa geht das, wenn man Objekte in C formulieren will Das mit den Objekten werde ich daher hintanstellen.
Bernd K. schrieb: > In meinen Fall mach ich ne fifo-Klasse und ne UART-Klasse und jede > UART-Instanz hält zwei Zeiger auf ihre beiden Fifo-Instanzen und den > Zeiger auf die UART-Hardware. Ja, sowas wäre mal als praktisches Beispiel gut zu gebrauchen.
Bernd K. schrieb: > Nö, das genaue Gegenteil ist der Fall. Quatsch. Wenn der C "this"-Pointer "self" heisst, geht das Ding völlig unverändert durch den C++ Compiler und der Code läuft sofort so wie er als C-Programm lief. Wenn er "this" heisst, hagelt's erstmal Fehlermeldungen ohne Ende.
Markus F. schrieb: > Quatsch. Selber Quatsch > Wenn der C "this"-Pointer "self" heisst, geht das Ding völlig > unverändert durch den C++ Compiler und der Code läuft sofort so wie er > als C-Programm lief. Warum sollte ich eine C Datei mit dem C++ Compiler kompilieren wollen? Wenn ich C++ draus machen will dann mach ich C++ draus und dann hilft es wenn ich große Brocken einfach 1:1 verwenden kann weil this schon this heißt. > Wenn er "this" heisst, hagelt's erstmal Fehlermeldungen ohne Ende. Nein, denn warum sollte ich den falschen Compiler verwenden, das ist absurd!
Nop schrieb: > Objekte bekommen dann erst Sinn, wenn es sich um Dinge handelt, die zur > Laufzeit entstehen, Zustand/Verhalten haben und wieder verschwinden. > GUI-Elemente etwa, oder Objekte in Simulationen (wo OOP ja herkommt). > > Bei statischen Objekten wie UARTs, die sich in Geräten normnalerweise > nicht anlegen und verschwinden, ist das bloß syntaktischer Zucker. Naja, nicht ganz so. Objekte haben ihren Sinn dort, wo sie aus reiner Software bestehen, die verwaltet werden müssen.Bestes Beispiel sind grafische Kringel auf'm Bildschirm, Menü-Elemente und so. Auch dann, wenn das Menü bereits zur Entwurfszeit feststeht und folglich im Flash angeordnet werden kann. Bei aller Art von Hardware hast du hingegen völlig Recht, da ist es nur ne unnötige, sinnlose und ressourcenfressende Soße über das eigentliche Ding gekippt. Bernd K. schrieb: > Oder wenn es mehrere von der selben Sorte gibt, zum Beispiel 3 > identische UARTs die sich nur im Registeroffset unterscheiden. Dann > macht man sich ein struct mit nem Zeiger aufs uart Ach nö. Du hast fast nirgendwo drei exakt gleiche UART's, denn bei genauerem Hingucken unterscheiden die sich ja doch, benötigen unterschiedliche ISR, hängen an unterschiedlichen System-Bussen usw. Deswegen mußt du schlußendlich alles, was du so schön zusammengefaßt zu haben glaubst, innen drin wieder auseinanderfummeln. Ich hab das alles schon vor Jahren durch gehabt, deswegen meine deutlich bessere Version mit dem hier schon mal geposteten gio.c, was nach oben hin für alle solche Datenströme ein einheitliches Interface bildet und nach unten hin von den tatsächlichen jeweiligen Lowlevel-Treibern getrennt ist. Etwas so von oben:
1 | extern void String_Out (char* P, word wo); |
wobei 'wo' eben ein Handle für den gewünschten Datenstrom ist. So geht das deutlich besser als mit deiner Idee und den Zeigern. W.S.
Peter D. schrieb: > Dieser Satz sagt mir, daß C++ überhaupt gar nichts für mich ist. Ich hab > nicht mal die allerkleinste Idee, was er bedeuten könnte. Das hat überhaupt nichts mit C++ zu tun! Sowas ist immer und in jeder Programmiersprache notwendig. Lerne mal lieber wieder Pascal und programmiere dir was mit Lazarus. Das hilft für's Verständnis. Also mal zu deiner Erleuchtung: Objekte haben drei Dinge: - Eigenschaften (properties) - Methoden (methods) - und ihr Innenleben, was niemanden draußen etwas angeht. Nun stelle dir mal drei instantiierte Objekte derselben Klasse vor. Zum Beispiel drei Menüeinträge. Einer ist "rauf" der nächste "runter" der dritte "hinein". Alle diese drei Objekte haben dieselben Methoden, denn sie sind ja von gleicher Klasse. Wie soll jetzt so eine Methode erkennen, als wessen Methode sie gerade aufgerufen wird? Also rauf.ZeichneDich; runter.ZeichneDich; hinein.ZeichneDich; rufen alle die gleiche Methode klassenname.ZeichneDich auf. Ganz klar, der Compiler fügt bei jedem Aufruf einer Methode zu den in der Typdeklaration angegebenen Argumenten eines hinzu: den Zeiger auf das aktuelle Objekt. Damit weiß die Methode, auf welches Objekt und dessen Properties und innere Daten es zugreifen muß. Ist doch eigentlich ganz logisch und auch leicht zu verstehen. W.S.
Bernd K. schrieb: > Nein, denn warum sollte ich den falschen Compiler verwenden, das ist > absurd! Warum ist das absurd? Jeder (na gut, 99,9% von denen, die erst nachdenken) mit einigermassen nennenswerter, existierender Codebasis wird die beim Umstieg von C auf C++ nicht einfach wegschmeissen und neu programmieren, sondern den (ja nicht ganz unabsichtlich möglichen) "weichen Migrationsweg" wählen. Da ist man dann ganz froh, wenn der Compiler sich nicht an so Kleinigkeiten wie "this" und "class" aufhängt sondern gleich zur Sache kommt, wenn der Code zum ersten mal durch die C++-Mühle gedreht wird.
Bernd K. schrieb: >> Wenn der C "this"-Pointer "self" heisst, geht das Ding völlig >> unverändert durch den C++ Compiler und der Code läuft sofort so wie er >> als C-Programm lief. > > Warum sollte ich eine C Datei mit dem C++ Compiler kompilieren wollen? > Wenn ich C++ draus machen will dann mach ich C++ draus und dann hilft es > wenn ich große Brocken einfach 1:1 verwenden kann weil this schon this > heißt. > >> Wenn er "this" heisst, hagelt's erstmal Fehlermeldungen ohne Ende. > > Nein, denn warum sollte ich den falschen Compiler verwenden, das ist > absurd! Kennst du die Suchen und Ersetzen Funktion deiner IDE schon? Du kannst die "this" wie vorgeschlagen "self" nennen, dann kompiliert dein Programm für C und C++. Wenn du aber das this nachträglich willst, gehst du in deiner IDE auf global suchen "self" ersetzen durch "this" und schon hast du wieder deinen für c++ nicht kompilierbaren "this" code. Dann kannst du die "großen Brocken" immernoch auf C++ umstellen ;)
Du hast ja vielleicht Tricks drauf. Ich vermeide lieber C++-Schlüsselworte in C-Code.
W.S. schrieb: > Objekte haben drei Dinge: > - Eigenschaften (properties) > - Methoden (methods) > - und ihr Innenleben, was niemanden draußen etwas angeht. Nur zur Übersetzung für C-onlys: Objekt = struct (class), genauer: eine Variable davon (Instanz) Methode=Funktion (in Pascal auch als Prozedur, darum ein anderer Begriff notwendig) Eigenschaft:von außen zugreifbares struct-element Innenleben: nach außen unsichtbares struct-element
MeineZweiCent schrieb: > Kennst du die Suchen und Ersetzen Funktion deiner IDE schon? Du kannst > die "this" wie vorgeschlagen "self" nennen Nein, warum sollte ich das machen? Ich habs von Anfang an absichtlich this genannt weil das der übliche Name dafür ist, denn sollte ich jemals auf die Idee kommen wollen es nach C++ portieren wollen kann das schonmal so bleiben und ich muss überhaupt nichts umbenennen. Und solange ich es nicht portiert habe bekommt es auch kein C++ Compiler jemals zu sehen, wozu auch? Sprech ich chinesisch oder warum ist das so schwer zu verstehen?
:
Bearbeitet durch User
Markus F. schrieb: > Du hast ja vielleicht Tricks drauf. > > Ich vermeide lieber C++-Schlüsselworte in C-Code. Das macht Sinn an Stellen wo sie eine andere Bedeutung haben, hier aber (bei this) bleibt die Bedeutung exakt identisch, es muß hinterher im fertig portierten Code eh this heißen, also warum erst umbenennen und dann wieder zurückumbenennen, das ist vollkommen absurd. Ich weiß auch nicht wie Du auf die fixe Idee kommst es würde auch nur den geringsten Sinn ergeben oder irgendwer würde auf die Idee kommen wollen C-Dateien durch den C++ Compiler jagen wollen wenn er doch einen C Compiler hat.
Bernd K. schrieb: > In meinen Fall mach ich ne fifo-Klasse und ne UART-Klasse und jede > UART-Instanz hält zwei Zeiger auf ihre beiden Fifo-Instanzen und den > Zeiger auf die UART-Hardware. Möchtest Du diesen Code nicht auch mal zeigen? Das wäre wenigstens mal ein praktisches Beispiel, was man nachvollziehen könnte und den Einstieg in C++ ermöglichen würde. Bisher habe ich hier immer nur Codebruchstücke gesehen, mit denen man nichts anfangen kann.
Peter D. schrieb: > Das wäre wenigstens mal ein praktisches Beispiel, was man nachvollziehen > könnte und den Einstieg in C++ ermöglichen würde. Die sind aber in purem C geschrieben, also nichts zum C++ lernen.
:
Bearbeitet durch User
Bernd K. schrieb: > Die sind aber in purem C geschrieben, also nichts zum C++ lernen. Weil Du von Klassen sprichst, dachte ich, es wäre C++.
Peter D. schrieb: > Das wäre wenigstens mal ein praktisches Beispiel, was man nachvollziehen > könnte und den Einstieg in C++ ermöglichen würde. Ich könnte dir da meinen C++ Ersatzstoff für die Arduino pinMode() und digitalxxx() Funktionen anbieten.......
Arduino F. schrieb: > Peter D. schrieb: >> Das wäre wenigstens mal ein praktisches Beispiel, was man nachvollziehen >> könnte und den Einstieg in C++ ermöglichen würde. > > Ich könnte dir da meinen C++ Ersatzstoff für die Arduino pinMode() und > digitalxxx() Funktionen anbieten....... Es wurde nicht nach abschreckenden Beispielen gefragt...
Arduino F. schrieb: > Ich könnte dir da meinen C++ Ersatzstoff für die Arduino pinMode() und > digitalxxx() Funktionen anbieten....... Ein Teil dieser Antworten würde die Bevölkerung verunsichern sorry musste sein
Achim S. schrieb: > Nur zur Übersetzung für C-onlys: > Objekt = struct (class), genauer: eine Variable davon (Instanz) > > Methode=Funktion (in Pascal auch als Prozedur, darum ein anderer Begriff > notwendig) > > Eigenschaft:von außen zugreifbares struct-element > > Innenleben: nach außen unsichtbares struct-element Du hast dich als Übersetzer blamiert. Eine Eigenschaft (property) eines Objektes ist eben NICHT mal bloß ein struct-element, auf was man von außen zugreifen kann. Es ist tatsächlich eine Eigenschaft und das ist was ganz anderes, weil der Zugriff darauf völlig anders ist als auf ein popliges Element eines ebenso popligen struct's. Im Allgemeinen kann ein lesender Zugriff auf eine Eigenschaft so ziemlich direkt erfolgen, es gibt aber Ausnahmen. Ein schreibender Zugriff hingegen erfolgt eigentlich immer über spezielle Schreibfunktionen, weil ja das Ändern einer Eigenschaft nicht einfach ein Überschreiben eines struct-elementes ist, sondern das verhalten des Objektes beeinflußt. Und Methoden sind eben auch was anderes als bloße Funktionen und Prozeduren. Ich will mich hier ja gar nicht über Abstammungen, virtuell oder nicht, Überladung, Neueinführung usw. auslassen. Und das Innenleben eines Objektes ist auch weitaus mehr als bloß nach außen unsichtbares struct-element. Wer mehr darüber wissen will, sollte sich tatsächlich darüber belesen - hier wäre das zu sehr abgeschweift. Hier geht es ja um die Frage, ob und wie man eine (eher primitive) Art von quasi-objektorientierter Programmierweise in C hinkriegen kann, also wie der TO sich dachte mit "Lampe.An();" und so. Es ist lediglich bei Hardware-Angelegenheiten so, daß der Versuch, sowas in Objektform zu bringen, fast immer herzlich unsinnig ist, weil man damit weder etwas verbessert noch klarer faßbar macht. Das Gegenteil ist der Fall, denn der Aufwand, auf Hardware-Angelegenheiten eine nach Objekt-Programmierung riechende Obefläche draufzudrücken, steht im krassen Gegensatz zum erhofften Nutzen. Hab ich ja weiter oben schon ausgeführt. Ich sag's mal plakativ: Für Software gibt's objektorientierte Programmierung Für Hardware gibt's Low Level Treiber. W.S.
C. schrieb: > Ein Teil dieser Antworten würde die Bevölkerung verunsichern Das mag sein.... Aber dennoch folgt es recht gut der eingangs genannten Syntax!
1 | // hier lampe Instanz definieren/anlegen
|
2 | |
3 | |
4 | void setup() |
5 | {
|
6 | lampe.init(); |
7 | }
|
8 | |
9 | void loop() |
10 | {
|
11 | lampe.setHigh(); // ein |
12 | // hier könnte ein delay stehen
|
13 | lampe.setLow(); // aus |
14 | // hier könnte ein delay stehen
|
15 | }
|
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.