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
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();
}
}
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;)
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:
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).
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.
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.
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).
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.
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.
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
structTMenuItem
3
{structTRectR;/* die Koordinaten relativ zum Owner */
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.
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
externvoidString_Out(char*P,wordwo);
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 ;)
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?
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.
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!