Ansi C Operator überladen?



  • DEvent schrieb:

    @rüdiger:
    Wieso ist den in Java und C# primitiven Typen wie int, float, double, usw. immernoch enthalten? Wieso gibt es Wrapper-Klassen für diese Typen? Wieso hat man nicht gleich die primitiven Typen als Objekte konzepiert, die ebenfalls von Object abgeleitet sind?

    Das soll jetzt was beweisen? Gerade in Java und C# sind die Builtin-Typen doch nicht hardwarenahe oder atomar.



  • DEvent schrieb:

    Primitive Typen sind aber in dem Sinn des Wortes atomar, da man sie nicht weiter zerlegen kann. Ein Objekt kannst du in seine Methoden und Attribute zerlegen, einen primitive Typen nicht.

    Naja, Threads sehen das leicht anderes und sowieso geht folgendes:

    union Foo{
      int a;
      char b[sizeof(int)];
    };
    

    Obwohl int primitive ist kann es noch weiter zerlegt werden. :p

    Den Zusammenhang mit Operatoren ergibt sich mir jedoch nicht. Erwartet irgend jemand ernsthaft von:

    Matrix<2, 2> a, b;
    a += b;
    

    dass += sich auf genau eine Prozessorbefehl abbilden lässt?



  • man Vektorbefehle

    SCNR



  • Technisch gesehen hat C# keine Datentypen, dass sind alles Datentypen aus der Runtime.



  • DEvent schrieb:

    @rüdiger:
    Wieso ist den in Java und C# primitiven Typen wie int, float, double, usw. immernoch enthalten? Wieso gibt es Wrapper-Klassen für diese Typen? Wieso hat man nicht gleich die primitiven Typen als Objekte konzepiert, die ebenfalls von Object abgeleitet sind?

    Wieder mal C# und Java über ein Kamm gescherrt oder? Nur Java kennt diese primitiven Datentypen mit Wrapperklassen. C# hat diese nicht, sondern da sind die Datentypen von Object abgeleitet. Wobei Zeus Kommentar natürlich richtig ist, das sind CLR Datentypen und nicht C# Datentypen. Wobei die C# Spec schon die CLR bedingt, von daher sinds doch die Datentypen von C# 🙂



  • pale dog schrieb:

    Mr. N schrieb:

    Du bist auf das wichtigste übrigens nicht eingegangen:

    Mr. N schrieb:

    Doch, man sieht sofort, dass das ein potenzieller Funktionsaufruf ist, wenn das Objekt von keinem Primitivtypen ist. Und den Typen muss man ja eh kennen.

    ja, muss man auch.
    man muss sein innenleben kennen, damit man damit nicht auf die nase fällt....

    Nein - muss man nicht ! Ein vernünftig designter operator ist selbsterklärend.
    Bei einer Funktion habe ich viel öfter die Notwendigkeit, mir anzusehen, was sie wirklich macht, weil es einfach viel mehrdeutiger ist, was z.B. clear(), erase(), ... machen könnte.

    pale dog schrieb:

    ich würde mir das ding ganz genau ansehen wollen....

    Warum ? Das mag vielleicht ein persönliche Vorliebe von Dir zu sein - nötig ist es nicht (mehr als bei normalen Funktionen).

    Gruß,

    Simon2.



  • Simon2 schrieb:

    pale dog schrieb:

    Mr. N schrieb:

    Du bist auf das wichtigste übrigens nicht eingegangen:

    Mr. N schrieb:

    Doch, man sieht sofort, dass das ein potenzieller Funktionsaufruf ist, wenn das Objekt von keinem Primitivtypen ist. Und den Typen muss man ja eh kennen.

    ja, muss man auch.
    man muss sein innenleben kennen, damit man damit nicht auf die nase fällt....

    Nein - muss man nicht ! Ein vernünftig designter operator ist selbsterklärend.
    Bei einer Funktion habe ich viel öfter die Notwendigkeit, mir anzusehen, was sie wirklich macht, weil es einfach viel mehrdeutiger ist, was z.B. clear(), erase(), ... machen könnte.

    pale dog schrieb:

    ich würde mir das ding ganz genau ansehen wollen....

    Warum ? Das mag vielleicht ein persönliche Vorliebe von Dir zu sein - nötig ist es nicht (mehr als bei normalen Funktionen).

    ich wollte mich künftig eigentlich raushalten aus der diskussion, aber - jetzt muss ich doch noch mal antworten 😉
    [] ist ungleich [] (siehe mein posting, das du teilweise zitiert hast)
    das eine ist ein simpler array-zugriff, das andere ist ein überladener operator.
    ersteres ist in wenigen µS von jedem 8-bitter erledigt, das andere stellt hohe anforderungen an die maschine.
    vielleicht kannst du's nicht nachvollziehen, weil du ohne zu zucken >600MB fette libraries benutzt (boost), oder ein .NET framework oder was-weiss-ich...
    aber diese beiden [], die im quelltext gleich aussehen, sind definitiv unterschiedlich
    🙂



  • pale dog schrieb:

    ich wollte mich künftig eigentlich raushalten aus der diskussion, aber - jetzt muss ich doch noch mal antworten 😉
    [] ist ungleich [] (siehe mein posting, das du teilweise zitiert hast)
    das eine ist ein simpler array-zugriff, das andere ist ein überladener operator.
    ersteres ist in wenigen µS von jedem 8-bitter erledigt, das andere stellt hohe anforderungen an die maschine.

    Achtung, schockierende Neuigkeiten für dich. In C (oder vermutlich auch Java) ist / ungleich / und + ungleich + und das ganz ohne Operator-Überladung. Skandal!

    (Ganz zu schweigen davon, dass der überladene op[] per definition nicht langsam sein muss, in den meisten Fällen dürfte ja wieder ein array-zugriff in µS rauskommen. Wenn der überladene op[] komplex ist, dann wäre dies auch eine Methode at() und man kommt ja eh nicht drum rum diese dann aufzurufen)



  • pale dog schrieb:

    Simon2 schrieb:

    pale dog schrieb:

    Mr. N schrieb:

    Du bist auf das wichtigste übrigens nicht eingegangen:

    Mr. N schrieb:

    Doch, man sieht sofort, dass das ein potenzieller Funktionsaufruf ist, wenn das Objekt von keinem Primitivtypen ist. Und den Typen muss man ja eh kennen.

    ja, muss man auch.
    man muss sein innenleben kennen, damit man damit nicht auf die nase fällt....

    Nein - muss man nicht ! Ein vernünftig designter operator ist selbsterklärend.
    Bei einer Funktion habe ich viel öfter die Notwendigkeit, mir anzusehen, was sie wirklich macht, weil es einfach viel mehrdeutiger ist, was z.B. clear(), erase(), ... machen könnte.

    pale dog schrieb:

    ich würde mir das ding ganz genau ansehen wollen....

    Warum ? Das mag vielleicht ein persönliche Vorliebe von Dir zu sein - nötig ist es nicht (mehr als bei normalen Funktionen).

    ich wollte mich künftig eigentlich raushalten aus der diskussion, aber - jetzt muss ich doch noch mal antworten 😉
    [] ist ungleich [] (siehe mein posting, das du teilweise zitiert hast)
    das eine ist ein simpler array-zugriff, das andere ist ein überladener operator.
    ersteres ist in wenigen µS von jedem 8-bitter erledigt, das andere stellt hohe anforderungen an die maschine.

    Und der Vorteil der Operator-Überladung ist, daß dir das im Grunde egal sein kann (aber diesen Punkt scheinst du noch nicht kapiert zu haben). Beides stellt technisch gesehen einen Index-Zugriff dar. Punkt.

    vielleicht kannst du's nicht nachvollziehen, weil du ohne zu zucken >600MB fette libraries benutzt (boost), oder ein .NET framework oder was-weiss-ich...

    Wenn es dir um Performance geht, kannst du ja drangehen und die verwendeten Operatoren durchoptimieren. Aber technisch macht es keinen Unterschied, ob du den Index-Zugriff auf eine Array-Klasse nun als "normale" Methode at() oder als operator[] realisierst (und aus Sicht eines C++ Programmierers ist letzteres konsequenter - C-style Arrays werden schließlich auch nicht über Methoden indiziert).

    PS: Und Boost als "Gesamtwerk" ist vielleicht 600MB groß - für eine konkrete Anwendung mußt du aber nur einzelne Teilbibliotheken verwenden, die dann deutlich kompakter sind. (und du ersparst dir damit den Aufwand, entsprechende Aufgaben nochmal neu zu lösen ;))



  • CStoll schrieb:

    Und der Vorteil der Operator-Überladung ist, daß dir das im Grunde egal sein kann

    es kann mir nicht egal sein und es ist mir nicht egal.
    ich setze nun mal andere prioritäten. 😉

    CStoll schrieb:

    (aber diesen Punkt scheinst du noch nicht kapiert zu haben).

    doch, hab' ich. mit überladenen op's werden benutzern von objekten bekannte syntaxelemente in die hand gegeben, die ihnen das handling mit diesen objekten erleichern.
    seiteneffekte, nebenwirkungen u.ä. sind (mit aufgesetzten C++ scheuklappen) 'egal' 🙄
    frei nach dem motto: 'es ist egal wie der hase läuft, hauptsache er läuft' 🙂



  • Wenn du Probleme mit C++ Sprachmitteln hast, kannst du gerne in deiner C-Welt bleiben. Andernfalls solltest du wenigstens versuchen, die Vorteile von C++ zu sehen.

    Ich für meinen Teil finde es auf jeden Fall konsequenter, wenn ich meine eigenen Zahlenklassen in einer natürlichen Syntax verrechnen kann oder auf Elemente eines Arrays per op[] zugreife als wenn ich dafür umständlich verschachtelte Funktionsaufrufe verwenden müsste (bei int/double bzw. C-style Arrays klappt das schließlich auch).

    PS: Klar - jedes Sprachmittel kann man verwenden, um die Sprache aus den Angeln zu heben (das geht sogar mit C-Mitteln). Aber das ist noch lange kein Grund dafür, es zu verbieten. Und wenn doch, wo ziehst du die Grenze der "Zulässigkeit"?



  • pale dog schrieb:

    ...
    [] ist ungleich [] (siehe mein posting, das du teilweise zitiert hast)
    das eine ist ein simpler array-zugriff, das andere ist ein überladener operator.
    ersteres ist in wenigen µS von jedem 8-bitter erledigt, das andere stellt hohe anforderungen an die maschine....

    Wieso denn das ? Ich kann doch einen operator[]() schreiben, der per asm unter Ausnutzung der konkreten Klassenstruktur und Rechnerarchitektur schneller arbeitet als der globale vom Compiler bereitgestellte ?
    Oder ich kann ihn und seine Kollegen (new, *, ->, ...) so umbiegen, dass ich identische Objekte nur einmal im Speicher habe und damit einer 1024-Array identischer Objekte nur soviel Platz im Speicher belegt, wie ein einziges, oder, oder, oder, ....

    Die Sprache bietet hier eine Flexibilität, die man zu seinem Vorteil nutzen kann - seien es nun Performance- oder Entwicklungsaspekte - ich verstehe immer noch nicht, warum Du das ablehnst.

    Gruß,

    Simon2.



  • Simon2 schrieb:

    pale dog schrieb:

    ...
    [] ist ungleich [] (siehe mein posting, das du teilweise zitiert hast)
    das eine ist ein simpler array-zugriff, das andere ist ein überladener operator.
    ersteres ist in wenigen µS von jedem 8-bitter erledigt, das andere stellt hohe anforderungen an die maschine....

    Wieso denn das ? Ich kann doch einen operator[]() schreiben, der per asm unter Ausnutzung der konkreten Klassenstruktur und Rechnerarchitektur schneller arbeitet als der globale vom Compiler bereitgestellte ?

    ich bezog mich auf meinen super-langsamen [] operator, der nur als beispiel dienen sollte.
    ...und wenn ich etwas wirklich schnelles will, dann bastel ich mir keinen operator, sondern ein #define makro mit inline-asm 😉

    Simon2 schrieb:

    Oder ich kann ihn und seine Kollegen (new, *, ->, ...) so umbiegen, dass ich identische Objekte nur einmal im Speicher habe und damit einer 1024-Array identischer Objekte nur soviel Platz im Speicher belegt, wie ein einziges

    komisches beispiel 😕
    wenn ich ein objekt brauche, dann hab' ich doch sowieso nur eins. warum 1024 und wieso sollte ich dafür operatoren umbiegen.

    Simon2 schrieb:

    Die Sprache bietet hier eine Flexibilität, die man zu seinem Vorteil nutzen kann...

    ....bei erhöhter komplexität, die einem zum nachteil gereicht.
    🙂

    btw: sorry, ich wollte eigentlich aussteigen aus der diskussion.
    jetzt scheint's aber nicht mehr um overloaded-ops zu gehen sondern um C++ allgemein?
    na, mal sehen was noch kommt.



  • pale dog schrieb:

    Simon2 schrieb:

    pale dog schrieb:

    ...
    [] ist ungleich [] (siehe mein posting, das du teilweise zitiert hast)
    das eine ist ein simpler array-zugriff, das andere ist ein überladener operator.
    ersteres ist in wenigen µS von jedem 8-bitter erledigt, das andere stellt hohe anforderungen an die maschine....

    Wieso denn das ? Ich kann doch einen operator[]() schreiben, der per asm unter Ausnutzung der konkreten Klassenstruktur und Rechnerarchitektur schneller arbeitet als der globale vom Compiler bereitgestellte ?

    ich bezog mich auf meinen super-langsamen [] operator, der nur als beispiel dienen sollte.
    ...und wenn ich etwas wirklich schnelles will, dann bastel ich mir keinen operator, sondern ein #define makro mit inline-asm 😉

    #define gehört zu den Sachen, die ein C++ Programmierer nur mit der Kneifzange anfassen würde. Und wenn du wirklich einen super-langsamen op[] zusammenschusterst, ist das dein Problem - niemand zwingt dich dazu.
    (und wenn du etwas optimieren willst, kannst du das mit einem "normalen" operator[] genausogut wie mit deinem "#define makro mit inline-asm")

    Simon2 schrieb:

    Die Sprache bietet hier eine Flexibilität, die man zu seinem Vorteil nutzen kann...

    ....bei erhöhter komplexität, die einem zum nachteil gereicht.
    🙂

    Was ist an den Operatoren komplexer? (abgesehen von der Tatsache, daß du prinzipiell etwas gegen sie hast?)



  • pale dog schrieb:

    Simon2 schrieb:

    pale dog schrieb:

    ...
    [] ist ungleich [] (siehe mein posting, das du teilweise zitiert hast)
    das eine ist ein simpler array-zugriff, das andere ist ein überladener operator.
    ersteres ist in wenigen µS von jedem 8-bitter erledigt, das andere stellt hohe anforderungen an die maschine....

    Wieso denn das ? Ich kann doch einen operator[]() schreiben, der per asm unter Ausnutzung der konkreten Klassenstruktur und Rechnerarchitektur schneller arbeitet als der globale vom Compiler bereitgestellte ?

    ich bezog mich auf meinen super-langsamen [] operator, der nur als beispiel dienen sollte....

    Mag sein, aber an meinem Beispiel siehst Du, dass es auch sinnvolle Fälle gibt. Ich brauche für die Sinnhaftigkeit von "operator overloading" auch nicht die Nichtexistenz von Fällen, in denen man es nicht sinnvoll einsetzt, sondern mir reicht die Existenz von Beispielen des sinnvollen Einsatzes. Deswegen tut ein Gegenbeispiel hier nichts zur Sache.

    pale dog schrieb:

    ...und wenn ich etwas wirklich schnelles will, dann bastel ich mir keinen operator, sondern ein #define makro mit inline-asm ;)...

    Und warum nicht direkt die Sprachmittel nehmen, die C++ dafür anbietet, sondern obskure, typunsichere, schlecht wartbare, schwer kollisionsgefährdete, ... Textersetzung ?

    Ich habe den Eindruck, dass Dir als Szenario auch immer nur die Einzelprogrammierersicht vorschwebt und Du es mit Kapselung "nicht so sehr hast".
    Wenn Du mir eine Klasse PaleDogArray anbötest und zum Indexzugriff ein Makro, wäre ich jedenfalls verwirrter, als wenn sie einen operator[]() mitbrächte...
    ... spätestens, wenn das Makro noch namentlich mit Anderem von mir kollidierte (immerhin folgen Makros keinen namespaces) oder ich für jeden Zugriff ein PALE_DOG_ARRAY_SPECIAL_INDEX_MAKRO aufrufen muss, macht es mir den maximal möglichen Geschwindigkeitsgewinn eines Funktionsaufrufs (kann auch mit etwas Geschick per inline wegoptimiert werden) nicht mehr wett ... und ich schaue mich nach etwas Anderem um.

    Und nun das Beste: Du kannst Deine Klasse schon jetzt so schreiben, obwohl es "operator overloading" gibt - aber man kann es eben auch anders machen !

    "operator overloading" sei Dank ! 😃

    Gruß,

    Simon2.



  • pale dog schrieb:

    CStoll schrieb:

    Und der Vorteil der Operator-Überladung ist, daß dir das im Grunde egal sein kann

    es kann mir nicht egal sein und es ist mir nicht egal.
    ich setze nun mal andere prioritäten. 😉
    ...

    Das hat nicht unbedingt etwas mit Prioritäten zu tun, sondern mit der Komplexität der Programme.
    C++ ist (genau wie C seinerzeit) entworfen worden, um steigende Komplexität der Anforderungen besser handhaben zu können. Dahinter steckt die Erfahrung, dass bei zunehmender Komplexität der Anforderungen die resultierende steigende Programmkomplexität es nicht mehr erlaubt, dass jeder Programmierer Alles vom GUI-Button bis zur ASM-Instruktion kennt. Deswegen hat man eine Sprache entworfen, die eine saubere und sichere Schichtung erlaubt (coolerweise unterstützt C++ AUCH den anderen Ansatz, aber der steht ja hier nicht zur Debatte).
    Das erlaubt und verlangt von Programmierer halt die jeweilige Kenntnis der genutzten tieferen Schicht .... die in diesem Fall eben nicht mehr die Plattforminfrastruktur (ASM, OS, ...) ist, sondern eben flexibel.

    • Nachteil: Es reicht nicht mehr, sich einmal ASM, OS, ... "draufzuschaffen", sondern man muss alle möglichen "Infrastrukturen" kennen; Pattern, Sprachkonstrukte, Konventionen, ... helfen dabei zwar, aber es verlangt größere Flexibilität vom Programierer.
    • Vorteil: Man kann eben schneller auf beliebigen Plattformen (ASM/OS ist nur eine davon) und wandelnden technischen und fachlichen Anforderungen arbeiten .

    Man muss diesen Abstraktionsschritt nicht mitgehen - dann wird man eben Systemprogrammierer -, aber er wird immer stärker gefordert und Systemprogrammierer werden immer stärker von fertige Infrastrukturkomponenten abgelöst. So braucht heute kaum noch jemand wirklich ASM-Erfahrung, immer weiter entwickelte Betriebssyteme übernehmen viele Aufgaben, die früher Systemprogrammierer mit jeweiligen "Selbststricklösungen" erfüllt haben, Remoteprotokolle wie CORBA, RMIIOP, ... machen Netzwerkprogrammierer arbeitslos, ....

    ... und für eine saubere Schichtung bietet C++ mit operator overloading ein großartiges Mittel.

    Gruß,

    Simon2.



  • Simon2 schrieb:

    pale dog schrieb:

    CStoll schrieb:

    Und der Vorteil der Operator-Überladung ist, daß dir das im Grunde egal sein kann

    es kann mir nicht egal sein und es ist mir nicht egal.
    ich setze nun mal andere prioritäten. 😉
    ...

    Das hat nicht unbedingt etwas mit Prioritäten zu tun, sondern mit der Komplexität der Programme.

    komplexität bezwingt man aber nicht mit zusätzlicher komplexität. 😉

    Simon2 schrieb:

    Systemprogrammierer werden immer stärker von fertige Infrastrukturkomponenten abgelöst. So braucht heute kaum noch jemand wirklich ASM-Erfahrung, immer weiter entwickelte Betriebssyteme übernehmen viele Aufgaben, die früher Systemprogrammierer mit jeweiligen "Selbststricklösungen" erfüllt haben, Remoteprotokolle wie CORBA, RMIIOP, ... machen Netzwerkprogrammierer arbeitslos,

    es gibt genug systeme (und es kommen ständig neue auf den markt) für die all dies noch nicht existiert, oder die einfach zu wenig ressourcen haben, um für sie komplette betriebssysteme zu portieren usw., also arbeitslos wird so schnell kein lowlevel-coder.
    ...und natürlich sollte man nicht selbst nachfrickeln was es schon fertig gibt, sondern bewährtes einsetzen. da bin ich ganz deiner meinung.

    btw: nicht dass du denkst, ich würde OOP komplett verteufeln. ich mag eine bestimmte OO-sprache inclusive plattform recht gern (die kennt übrigens keine overloaded-ops) und manchmal programmiere ich sogar noch mit MFC 🙂



  • pale dog schrieb:

    komplexität bezwingt man aber nicht mit zusätzlicher komplexität. 😉

    Womit sonst? Orthogonalität? Das ist jetzt ja nicht die Stärke von C.



  • Mr. N schrieb:

    pale dog schrieb:

    komplexität bezwingt man aber nicht mit zusätzlicher komplexität. 😉

    Womit sonst?

    modularisierung, schichtenmodelle usw.
    etwa das, was Simon2 angesprochen hat, auch wenn er auf etwas anderes hinaus wollte.

    Mr. N schrieb:

    Orthogonalität? Das ist jetzt ja nicht die Stärke von C.

    muss ja auch nicht. 😉
    C ist ein nur ein ziemlich 'straightes' werkzeug, es zwingt dir keine konzepte auf.
    klar, C's ausstattung ist spartanisch, aber für seinen zweck (system- treiber- kernel- netzwerk- programmierung) ist alles da was man braucht und man hat zugriff auf unmengen an source codes und libraries (google - filetype:c).
    ich hab' letztens erst einen freien basic-interpreter in C aus'm netz gezogen, leicht umgebaut und jetzt läuft er als scriptsprache auf einem embedded system 🙂

    wir sollten jetzt aber keinen flamewar C++ gegen C anfangen, das wäre ja so, als wenn der grosse bruder das kleine geschwisterchen verprügeln würde 😉



  • pale dog schrieb:

    Mr. N schrieb:

    pale dog schrieb:

    komplexität bezwingt man aber nicht mit zusätzlicher komplexität. 😉

    Womit sonst?

    modularisierung, schichtenmodelle usw.

    Ist das keine Komplexität? Wieso ist dann so etwas simples und intuitives wie Operatorüberladung komplex?

    Nebenbei, zum Thema "Schichtenmodell"... Das ist dann vermutlich das Zeug, was meine Kollegen gerade abschaffen, nachdem Kollege H das Team gewechselt hat. Irgendein bekannter Softwarezeug-Schreiberling hat gesagt: Schichten sind toll um Diagramme zu zeichnen (mit denen ich irgendwie allerdings nie was anfangen konnte), aber eben nicht flexibel genug für die Anforderungen der Realität.

    pale dog schrieb:

    Mr. N schrieb:

    Orthogonalität? Das ist jetzt ja nicht die Stärke von C.

    muss ja auch nicht. 😉
    C ist ein nur ein ziemlich 'straightes' werkzeug, es zwingt dir keine konzepte auf.

    Das ist auch die große Stärke von C++ 👍.

    pale dog schrieb:

    klar, C's ausstattung ist spartanisch, aber für seinen zweck (system- treiber- kernel- netzwerk- programmierung) ist alles da was man braucht und man hat zugriff auf unmengen an source codes und libraries (google - filetype:c).

    Und man hat den großen Vorteil, dass Linus Torvalds es akzeptiert 🤡.

    pale dog schrieb:

    wir sollten jetzt aber keinen flamewar C++ gegen C anfangen, das wäre ja so, als wenn der grosse bruder das kleine geschwisterchen verprügeln würde 😉

    Du willst also lieber Java verteidigen?


Anmelden zum Antworten