C auch OOP?
-
Markuss12 schrieb:
was meint ihr damit
Das OOP nur ein Konzept ist, den man unabhaenig von der Sprache einsezten kann und sollte.
-
eine klasse ist nicht das gleiche wie ein struct, wenn das wirklich genau so in deinem buch steht, solltest du es schleunigst wegwerfen und dir ein neues suchen.
(in C++ wird ein struct intern zwar auch nur als klasse gehandhabt, Verwirrung stiftend ist die Aussage, dass beides gleich sei, aber trotzdem)
-
Ich meinte damit: Wenn man kein tragfähiges Komzept zur Lösung eines Problems
hat sollte man sich um die Wahl der Programmiersprache erst recht keinen Kopf machen.Egal ob OOP oder irgendwas anderes.
-
Heinzelotto schrieb:
eine klasse ist nicht das gleiche wie ein struct, wenn das wirklich genau so in deinem buch steht, solltest du es schleunigst wegwerfen und dir ein neues suchen.
(in C++ wird ein struct intern zwar auch nur als klasse gehandhabt, Verwirrung stiftend ist die Aussage, dass beides gleich sei, aber trotzdem)
Auch wenn der OP aller Wahrscheinlichkeit nach ein Troll ist, in C++ ist
struct
gleichclass
, mal von der Default Visibility abgesehen.
-
Um mal kurz eine vernünftige Antwort zu geben; Ohne Geschwafel von "Konzepten" und "Problemen". Es stimmt soweit, dass in C++ Structs genauso wie Classes benutzt werden können. Im Umkehrschluß bedeutet das allerdings nicht im geringsten, dass man also in C mit Structs OO programmieren kann. Es gibt keine Kapselung, sprich du kannst nicht festlegen, ob die Variablen deines Structs von außen veränderbar sind oder nicht, es gibt keine Konstruktoren und Destruktoren und entsprechend keine wirklichen Memberfunktionen. In C ist OOP faktisch unmöglich da halt die essentiellen Bestandteilen nicht möglich sind. Ansonsten einfach nochma Wikipedia zu dem OOP Thema befragen. Dann wird dir auffallen, dass es dies alles so in C nicht gibt.
Achja @Scheppertreiber:
Du hättest genausogut schreiben können, dass Teiche gerne grün sind weil Katzen miauen. Hätte den selben Sinn.
Schöne Grüße
-
BlaKonzepteBla schrieb:
Um mal kurz eine vernünftige Antwort zu geben; Ohne Geschwafel von "Konzepten" und "Problemen". Es stimmt soweit, dass in C++ Structs genauso wie Classes benutzt werden können. Im Umkehrschluß bedeutet das allerdings nicht im geringsten, dass man also in C mit Structs OO programmieren kann. Es gibt keine Kapselung, sprich du kannst nicht festlegen, ob die Variablen deines Structs von außen veränderbar sind oder nicht, es gibt keine Konstruktoren und Destruktoren und entsprechend keine wirklichen Memberfunktionen. In C ist OOP faktisch unmöglich da halt die essentiellen Bestandteilen nicht möglich sind. Ansonsten einfach nochma Wikipedia zu dem OOP Thema befragen. Dann wird dir auffallen, dass es dies alles so in C nicht gibt.
Wiedermal jemand der Programmierung Allgemein nicht verstanden hat
Es geht beim programmieren nur um Konzepte. Und Sprachen sind Tools um diese Konzepte und Ideen zu implementieren. Manche Konzepte sind einfach implementierbar andere schwerer - da unterscheiden sich die Sprachen. Aber die meisten guten C APIs sind allesamt objekt orientiert. zB die WinAPI.
Als denkanstoss:
fopen ist ein Konstruktor
fclose ist ein Destruktor
fwrite ist eine Memberfunktion
ftell ist ein getter
fseek ist ein setterDas was die Leute immer verwirrt ist, ist dass OOP ja immer heisst: objekt.methode() und wenn man mal ein methode(objekt) macht, dann ists kein OOP mehr.
traurig traurig
-
BlaKonzepteBla schrieb:
In C ist OOP faktisch unmöglich da halt die essentiellen Bestandteilen nicht möglich sind.
du bist falsch. OOP ist nur ein Konzept. C++/Java/C#/D/usw. haben syntaktischen Zucker, um OOP Programmierung zu erleichtern. C hat diesen eben nicht, das heißt aber nicht, dass man es nicht machen kann. Es ist schwer, aber nicht unmöglich. Das beste Beispiel für eine effiziente [1] Bibliothek, die in C geschrieben ist und OOP arbeitet: GTK.
Es gibt keine Kapselung,
Es gibt Kapselung. Die FILE Datenstruktur von stdio.h ist ein Beispiel dafür.
ob die Variablen deines Structs von außen veränderbar sind oder nicht
doch, das geht. Es ist nicht so einfach und elegant wie in C++/Java/usw. aber es geht. GTK demonstriert das auch. (irgendwo im ANSI C Forum liegt ein Thread, wo ich ein Bsp dafür demonstriere [was ich mir aus der GTK Bib angeschaut habe])
es gibt keine Konstruktoren und Destruktoren
doch, die kannst du schreiben. Dass sie nicht automatisch gestartet werden, heißt es nicht, dass es sie nicht gibt. Das ist eine andere Geschichte.
und entsprechend keine wirklichen Memberfunktionen
doch, fread ist eine solche Memeber Funktion. Funktioniert nur mit FILE Objekten. Ansonsten siehe Shades Antwort
[1] sollte jetzt nicht diskutiert werden, ob GTK wirklich unter allen Plattformen effizient ist oder nicht
-
Hi iSaheOfMine,
ein schönes Beispiel !
Die notwendige "hippe" Schreibweise (damit's modern ist) bekommt man nur Not
noch mit Makros hin ...
-
BlaKonzepteBla schrieb:
Um mal kurz eine vernünftige Antwort zu geben; Ohne Geschwafel von "Konzepten" und "Problemen". Es stimmt soweit, dass in C++ Structs genauso wie Classes benutzt werden können. Im Umkehrschluß bedeutet das allerdings nicht im geringsten, dass man also in C mit Structs OO programmieren kann. Es gibt keine Kapselung, sprich du kannst nicht festlegen, ob die Variablen deines Structs von außen veränderbar sind oder nicht, es gibt keine Konstruktoren und Destruktoren und entsprechend keine wirklichen Memberfunktionen. In C ist OOP faktisch unmöglich da halt die essentiellen Bestandteilen nicht möglich sind. Ansonsten einfach nochma Wikipedia zu dem OOP Thema befragen. Dann wird dir auffallen, dass es dies alles so in C nicht gibt.
Achja @Scheppertreiber:
Du hättest genausogut schreiben können, dass Teiche gerne grün sind weil Katzen miauen. Hätte den selben Sinn.
Schöne Grüßedanke für diese präzise Erklärung.
-
supertux schrieb:
BlaKonzepteBla schrieb:
In C ist OOP faktisch unmöglich da halt die essentiellen Bestandteilen nicht möglich sind.
du bist falsch. OOP ist nur ein Konzept. C++/Java/C#/D/usw. haben syntaktischen Zucker, um OOP Programmierung zu erleichtern. C hat diesen eben nicht, das heißt aber nicht, dass man es nicht machen kann. Es ist schwer, aber nicht unmöglich. Das beste Beispiel für eine effiziente [1] Bibliothek, die in C geschrieben ist und OOP arbeitet: GTK.
Es gibt keine Kapselung,
Es gibt Kapselung. Die FILE Datenstruktur von stdio.h ist ein Beispiel dafür.
ob die Variablen deines Structs von außen veränderbar sind oder nicht
doch, das geht. Es ist nicht so einfach und elegant wie in C++/Java/usw. aber es geht. GTK demonstriert das auch. (irgendwo im ANSI C Forum liegt ein Thread, wo ich ein Bsp dafür demonstriere [was ich mir aus der GTK Bib angeschaut habe])
es gibt keine Konstruktoren und Destruktoren
doch, die kannst du schreiben. Dass sie nicht automatisch gestartet werden, heißt es nicht, dass es sie nicht gibt. Das ist eine andere Geschichte.
und entsprechend keine wirklichen Memberfunktionen
doch, fread ist eine solche Memeber Funktion. Funktioniert nur mit FILE Objekten. Ansonsten siehe Shades Antwort
[1] sollte jetzt nicht diskutiert werden, ob GTK wirklich unter allen Plattformen effizient ist oder nicht
wenn c auch oop kann, warum wird immer erwähnt, dass es kein OOP kann?
-
C bietet eigentlich nix womit man einfach und vernünftig OO programmieren könnte, man muss im Prinzip fast alles was man für OO brauch (Datenkapselung, Vererbung(geht sowas mit C überhaupt?), Virtuelle Methoden...) durch irgendwelche aufwendigen Konstrukte zusammenfrimeln.
-
ganzeinfach schrieb:
C bietet eigentlich nix womit man einfach und vernünftig OO programmieren könnte, man muss im Prinzip fast alles was man für OO brauch (Datenkapselung, Vererbung(geht sowas mit C überhaupt?), Virtuelle Methoden...) durch irgendwelche aufwendigen Konstrukte zusammenfrimeln.
... und nichts anderes macht der C++ Compiler. Die ersten haben aus dem C++ Quelltext
schlichten C-Code erzeugt der dann nochmal kompiliert wurde.Der Overhead ist beeindruckend.
Klar können die das heute besser, sie erzeugen direkten Object-Code. Der Overhead
bleibt.
-
ganzeinfach schrieb:
C bietet eigentlich nix womit man einfach und vernünftig OO programmieren könnte, man muss im Prinzip fast alles was man für OO brauch (Datenkapselung, Vererbung(geht sowas mit C überhaupt?), Virtuelle Methoden...) durch irgendwelche aufwendigen Konstrukte zusammenfrimeln.
fangen wir mal vorne an: datenkapselung. nichts leichter als das.
myObjectHandle createMyObject(); foo bar(myObjectHandle obj [, args]);
hübsch, oder? myObjectHandle ist ein pointer auf irgendwas, was ich nicht kenne. ich habe keine ahnung, was in myObject abgeht, sondern habe nur einen satz funktionen, mit denen ich auf die interna zugreifen kann. das und nichts anderes ist datenkapselung. das ist in diversen größen c-systemen usus. sei es nun die winapi (hXXX), die posix-api (bspw. stream-handles) oder auch das schon erwähnte gtk.
virtuelle methoden erstellt man über lookup-tables, wie sie die vtable auch nur eine ist. der codeaufwand dafür ist auch eher gering und man kann mit ein wenig mehr aufwand sogar dynamische funktionsaufrufe realisieren.
vererbung kann man ebenfalls durch handle und ein kleines zugriffssystem auf die variablen bauen. createMyDirevedObject() erzeugt dann auch einen pointer von typ myObjectHandle und mittels bspw. eines zeigerarrays für variablen und zwei zeilen code zum zugreifen ist das ganze dynamisch gelöst.
wenn man ein statisches system haben will, kann man auch ein bisschen tricksen:struct base{ int var1; }; //die variablen dürfen ihre reihenfolge in den structs nicht ändern. // c ist da wie c++. ändert man die reihenfolge, zerbricht man die abi. struct derived{ int var1; int var2; }; typedef void* myHandle; myHandle createDerived() { return (myHandle)malloc(sizeof(struct derived)); } struct base foo() { struct base bar = (*((struct base*)createDerived())); bar.var1=12; return bar; }
problem an dem ganzen: man verliert auch noch den letzten rest an typsicherheit. aber auch das kann man umgehen, in dem man bspw eine signatur an den anfang aller structs setzt und zuerst schaut, ob die konvertierung klappt. das ist auch mit minimalen aufwand verbunden und nebenbei auch die methode, die dynamic_cast in c++ nutzt.
-
... und schon verheddern wir uns hemmungslos in den Fallstricken der Verwaltung.
So ähnlich muß auch das deutsche Steuerrecht entstanden sein.
-
ghorst schrieb:
fangen wir mal vorne an: datenkapselung. nichts leichter als das.
myObjectHandle createMyObject(); foo bar(myObjectHandle obj [, args]);
hübsch, oder? myObjectHandle ist ein pointer auf irgendwas, was ich nicht kenne. ich habe keine ahnung, was in myObject abgeht, sondern habe nur einen satz funktionen, mit denen ich auf die interna zugreifen kann. das und nichts anderes ist datenkapselung. das ist in diversen größen c-systemen usus. sei es nun die winapi (hXXX), die posix-api (bspw. stream-handles) oder auch das schon erwähnte gtk.
virtuelle methoden erstellt man über lookup-tables, wie sie die vtable auch nur eine ist. der codeaufwand dafür ist auch eher gering und man kann mit ein wenig mehr aufwand sogar dynamische funktionsaufrufe realisieren.
vererbung kann man ebenfalls durch handle und ein kleines zugriffssystem auf die variablen bauen. createMyDirevedObject() erzeugt dann auch einen pointer von typ myObjectHandle und mittels bspw. eines zeigerarrays für variablen und zwei zeilen code zum zugreifen ist das ganze dynamisch gelöst.
wenn man ein statisches system haben will, kann man auch ein bisschen tricksen:struct base{ int var1; }; //die variablen dürfen ihre reihenfolge in den structs nicht ändern. // c ist da wie c++. ändert man die reihenfolge, zerbricht man die abi. struct derived{ int var1; int var2; }; typedef void* myHandle; myHandle createDerived() { return (myHandle)malloc(sizeof(struct derived)); } struct base foo() { struct base bar = (*((struct base*)createDerived())); bar.var1=12; return bar; }
problem an dem ganzen: man verliert auch noch den letzten rest an typsicherheit. aber auch das kann man umgehen, in dem man bspw eine signatur an den anfang aller structs setzt und zuerst schaut, ob die konvertierung klappt. das ist auch mit minimalen aufwand verbunden und nebenbei auch die methode, die dynamic_cast in c++ nutzt.
Das ist ja alles schön und gut, nur ist das zum einen tatsächlich eine großes Gefrickel und es hat auch nicht viel mit Kapselung zu tun. Du kannst immer und zu jedem Zeitpunkt, wenn du möchtest auf die Member der structs zugreifen. Das darf bei einer vernünftigen Kapselung auch nicht sein. Von der Nutzung und Stabilität dieses Konstrukts brauch man erst gar nicht sprechen. Okay, wenn man Funktionen die ein bestimmtes Struct als Argument brauchen nimmt und dieses Gefrickel als Kapselung was weiß ich akzeptiert, dann ist eine OOP light in C möglich. Trotzalledem ist mit C keine vernünftige OOP in Vergleich mit C/C#/Java usw. möglich
Gruß
-
in dem bsp für die verebung habe ich mir gekniffen das alles hübsch ordendlich zu verstecken, aber hier um dich zu beruhigen:
header:typedef void * myHandle; myHandle createBase(); myHandle createDerived(); void setVar1(myHandle obj,int value); int getVar1(myHandle obj); void setVar2(myHandle obj,int value); int getVar2(myHandle obj);
source-file:
struct base{ int var1; }; bi. struct derived{ int var1; int var2; }; myHandle createBase() { return malloc(sizeof(struct base)); } myHandle createDerived() { return malloc(sizeof(struct derived)); } void setVar1(myHandle obj,int value) { ((struct base*)obj)->var1=value; } void getVar1(myHandle obj) { return ((struct base*)obj)->var1; } void setVar2(myHandle obj,int value) { ((struct derived*)obj)->var2=value; } void getVar2(myHandle obj) { return ((struct derived*)obj)->var2; }
der äquivalente c++-code:
class base{ public: base(){}; int getVar1(); void setVar1(int value); private: int var1; }; class derived: public base { public: derived :base(){} int getVar2(); void setVar2(int value); private: int var2; }; void base::setVar1(int value) { var1=value; } int base::getVar1() { return var1; } void base::setVar2(int value) { var2=value; } int base::getVar2() { return var2; }
natürlich ist der c++-code schöner, da ich nicht alles aus der base-klasse im kind wiederholen muss und typsicherheit haben, aber naja, es hat niemand behauptet, dass es übermäßig schön werden würde.
-
ghorst schrieb:
natürlich ist der c++-code schöner, da ich nicht alles aus der base-klasse im kind wiederholen muss und typsicherheit haben, aber naja, es hat niemand behauptet, dass es übermäßig schön werden würde.
Musst du doch auch nicht in C?
struct base{ int var1; }; struct derived{ struct base that; int var2; };
-
dann klappt das mit dem polymorphismus nicht mehr so einfach:
struct derived *kindobj=malloc(sizeof(struct derived)); struct base *mutterobj=(struct base*)kindobj;
man muss dann eine echte dynamische typumwandlung implementieren oder pro klasse alle getter/setter neuschreiben und dynamisch den richtigen typ ermitteln, anstatt einfach nur einen cast durchzuführen.
-
OOP ist mit C nicht möglich. Punkt. Was man in C, und eigentlich so gut wie mit jeder imperativen Sprache machen kann, ist OBP.
Konzepte wie Polymorphie oder Vererbung (wobei Vererbung ohne Polymorphie eigentlich witzlos ist) lassen sich nicht wirklich nachbilden. Auch solche Dinge wie RAII sind in C unmöglich.
Zwischen OBP und OOP besteht immernoch ein Unterschied. Ja, OOP ist ein Konzept, aber das Konzept muss explizit vom Sprachumfang unterstützt werden.
-
Vererbung ist nicht kein merkmal dass OOP definiert.
JavaScript zB hat keine vererbung.Und natuerlich ist es schwerer Konzepte zu implementieren wenn einem die Sprache dabei nicht hilft - aber es geht. Jede gute C API ist Objekt Orientiert.
Wir muessen uns dazu nur einmal die C Library selbst ansehen:
die string funktionen: schoenes OOD
die stdio funktionen: schoenes OOD
...WinAPI und natuerlich auch die POSIX API. Oder kennt wer gmp? Alles schoenes OO-Design.
Vererbung ist haesslich, keine Frage: aber es ist zum glueck auch nicht das um und auf der OOP
Und dennoch kann man vererbung implementieren. Wenn wir jetzt nur komfort betrachten, dann faellt C++ uebrigens auch durch was OOP betrifft: denn komfort bietet C++ ja nun wirklich kaum. Allein ein einfaches multi dispatching ist ja schon hoelle zum implementieren.
Zum glueck definiert der komfort einer sprache nicht die verwendbarkeit.