Erst C oder gleich C++ ???



  • u_ser-l schrieb:

    asc schrieb:

    Ich habe nie C gelernt,

    doch, hast Du. Und zwar implizit durch Mitlernen im Rahmen von C++

    Wenn man von C++ alles herausnimmt, was von C stammt, kann man nicht einmal

    int main(){; }
    

    Nach der Definition lernt auch jeder Java und C# Entwickler C.

    Und wieder: Ich habe nie C gelernt. Den auch wenn ich C++ Syntaxelemente gelernt habe die in C ihren Ursprung haben, kann ich kein C programmieren. Und der C# Entwickler wird ebenso for, while, int... lernen und kann ebenso kein C-Programmieren. Einige Sprachelemente mögen gleich sein, dennoch kann man damit nicht C programmieren. Für die Programmieren müsste man auch - zumindest maginale - Kenntnisse der Bibliotheken haben. Ich bekomme auf Anhieb noch nicht einmal die Syntax von malloc, free, prinft hin.

    u_ser-l schrieb:

    ...und Zeiger durch Referenzen ersetzt...

    Zeiger sind ebenso Sprachbestandteil von C wie auch C++. Damit ist C++ aber noch immer kein C (auch wenn einige meinen das sie mit C-Code und der C-Programmierweise automatisch C++ Programmierer sind, wenn sie einen C++ Compiler verwenden).

    cu André



  • audacia schrieb:

    Einheitlichen Exception-Typen, unproblematischeres Dispatching. Überhaupt Einheitlichkeit. Ein gewisser Zwang dahingehend, Exceptions mit sinnvollen Fehlermeldungen zu werfen (weil die leichteste Variante, eine Exception zu werfen, dann nicht mehr throw 1; , sondern throw std::runtime_error ("array index out of bounds"); ist). Und weniger Typinformation für Basistypen in der Executable, deutlich geringeren Aufwand auf der RTL-Seite.

    Beantworte einfach die Frage und erzähl keine Marketingmärchen:
    Warum darf ich nicht objekt und zeiger werfen sondern nur eins von beiden.
    auf grund der value semantik muss man dann wohl objekte by value werfen, was aber n bisschen blöd ist wenn man exception chaining machen will.

    oder darf ich zeiger werfen und objekte?

    restriktionen, restriktionen,....
    und das mit weniger typinformationen kapiere ich nicht.

    du weisst wie exceptions implementiert sind, oder?

    Um deine Frage erneut gegen dich selbst zu wenden: wozu braucht man throw 1; ?

    langweilig, hab ich schon beantwortet: nämlich indem ich eine verwendung für T* gezeigt habe.

    Shade Of Mine schrieb:

    aber es geht auch nicht um perfektion sondern darum ob es funktioniert. und c++ funktioniert.

    Achso, sobald wir also über ein paar konkrete ("undurchdachte") Schwachstellen reden, gehts nur noch darum, daß es funktioniert 🤡
    Machst du es dir nicht ein bißchen einfach?

    Perfekte Features existieren nicht. name() kann man verwenden und es funktioniert. die form von name() ist auch standardisiert, nämlich als ID was aus sicht eines reflection system sehr viel sinn macht.

    dass ein reflection system nun name() eine passende form geben kann ist dabei recht praktisch. im c++ standard kann man hier nicht viel sinnvoll definieren. da ist jede definition gleich gut - schränkt aber reflection systeme uU ein.

    deshalb ist es besser nicht einzuschränken und die form von name() als ID zu definieren.

    Shade Of Mine schrieb:

    wenn deine implementation es schlecht definiert, jo mei.

    ?

    und deshalb wird die diskussion langweilig...
    ID heisst, dass deine implementierung name() frei definieren kann. wenn deine implementierung dies eben so tut dass es dir nicht passt, dann lebe damit oder nimm eine andere. die idee ist, sobald jemand eine sinnvolle verwendung für name() gefunden hat, können die compiler es implementieren und es gibt keine limitierungen.

    aktuell bringt dir aber eine standardisierte name() variante nichts, ausser dass es nett aussieht. also wozu limitieren was erlaubt ist?

    uU ist es sinnvoll per compiler switch zB name() als den name mangled namen zu definieren oder als ein pretty print, etc.

    Shade Of Mine schrieb:

    exceptions, value semantik und new

    Nicht auch std::type_info?

    nein, weil du type_info schon verstanden hast, nur du willst dass es mehr macht. das ist legitim. ich will ja auch dass java first class functions hat. aber das ist jetzt nicht wirklich etwas undurchdachtes in java.

    Interessanterweise ist genau das der Hintergrund meiner (und Barrys) Argumentation. Irgendwie willst du es nur nicht verstehen. Denn der Artikel ist ja Käse.

    ich verstehe nicht wo das problem liegt.
    du kannst problemlos mit shared_ptr arbeiten.
    du kannst problemlos _kopien_ ziehen. und du kannst problemlos referenzen ziehen.

    das sind features die du bei den meisten closure implementierungen nicht hast.

    ergo: wieder mehr features auf der value semantik seite.



  • Shade Of Mine schrieb:

    oder darf ich zeiger werfen und objekte?

    Nur Objekte. Du darfst sie auch kopieren.

    Shade Of Mine schrieb:

    du weisst wie exceptions implementiert sind, oder?

    Davon kannst du ausgehen.

    Shade Of Mine schrieb:

    langweilig, hab ich schon beantwortet: nämlich indem ich eine verwendung für T* gezeigt habe.

    Achso, weil das in MFC üblich ist, soll das erlaubt sein?

    Shade Of Mine schrieb:

    deshalb ist es besser nicht einzuschränken und die form von name() als ID zu definieren.

    Könnte ich zustimmen, wenn wir über std::type_info::mangled_name() redeten.
    Hier ist es tatsächlich so, wie du sagst: daß ich mir vor allem ein Feature mehr wünsche.

    Shade Of Mine schrieb:

    aktuell bringt dir aber eine standardisierte name() variante nichts, ausser dass es nett aussieht. also wozu limitieren was erlaubt ist?

    Ich kann mir da ein paar nette Anwendungsfälle für z.B. Serialisierung vorstellen.

    Shade Of Mine schrieb:

    ergo: wieder mehr features auf der value semantik seite.

    Ja, _noch_ mehr Features. Mit C++ ist tatsächlich fast alles umsetzbar.
    Ob man das aber zur Maxime erklären sollte, finde ich fraglich.



  • audacia schrieb:

    Shade Of Mine schrieb:

    oder darf ich zeiger werfen und objekte?

    Nur Objekte. Du darfst sie auch kopieren.

    Und damit ist exception chaining nicht mehr möglich.
    sehr clever.

    Shade Of Mine schrieb:

    langweilig, hab ich schon beantwortet: nämlich indem ich eine verwendung für T* gezeigt habe.

    Achso, weil das in MFC üblich ist, soll das erlaubt sein?

    Weil du viele techniken nicht umsetzen kannst wenn du keine exceptions als zeiger werfen kannst.

    das problem dabei ist, dass shared_ptr hier nämlich nicht hilft.

    man müsste einen umständlichen weg über pimpl gehen.

    und für was?

    Shade Of Mine schrieb:

    aktuell bringt dir aber eine standardisierte name() variante nichts, ausser dass es nett aussieht. also wozu limitieren was erlaubt ist?

    Ich kann mir da ein paar nette Anwendungsfälle für z.B. Serialisierung vorstellen.

    und das klappt super mit einer bestimmten implementierung.

    Shade Of Mine schrieb:

    ergo: wieder mehr features auf der value semantik seite.

    Ja, _noch_ mehr Features. Mit C++ ist tatsächlich fast alles umsetzbar.
    Ob man das aber zur Maxime erklären sollte, finde ich fraglich.

    Natürlich soll nicht jede Sprache alles können - aber value semantik ist etwas wichtiges: es muss sprachen mit value semantik geben.

    nicht jede sprache soll value semantik haben. referenz semantik macht auch sinn. es erleichtert viele sachen (schränkt dafür halt auch etwas ein) aber solche trade-offs sind wichtig. weil nicht immer will ich rohe power haben, sondern einfachere systeme wo ich bestimmte probleme einfacher lösen kann.



  • asc schrieb:

    Nach der Definition lernt auch jeder Java und C# Entwickler C.

    wußte gar nicht, daß java und C# Zeigerarithmetik haben.

    Aber egal.

    Ein C++ Programmierer, der kein C kann, kann kein C++, sondern nur eine Teilsprache von C++.

    Weil nämlich:

    <sprechplatte play>
    C++ ist eine Spracherweiterung von C.
    <sprechplatte stop>
    

    Jetzt haben wir es aber alle verstanden. ciao.

    Grüße



  • Shade Of Mine schrieb:

    Und damit ist exception chaining nicht mehr möglich.

    Interessanterweise implementiere ich in der Unit, die ich in obigem Artikel bespreche, Exception-Chaining für gewöhnliche C++-Exceptions (std::exception-Derivate). Ohne manuelle Kopien und mit gewöhnlichen auf dem Stack angelegten Objekten. Und wenn man ein paar sinnvolle Regelungen zur Destruktionsreihenfolge bei Chained Exceptions eingeführt hätte (kann sogar sein, daß es die gibt, aber das müßte ich nachlesen), wäre das auch mit der Beschränkung auf stackallozierte std::exception-Derivate problemlos in Standard-C++ machbar.

    Außerdem ist doch gerade Exception-Chaining ein Argument für einheitliche Exceptions. Du kannst jede innere Exception wrappen, ohne ihren Typen zu kennen. Da du sie auf das polymorphe std::exception& reduzieren kannst, ist es den Handlern der äußeren Exception möglich, spezielle innere Exceptions, von denen deine äußere Exceptions gar nichts weiß, mittels Polymorphie zuzugreifen und auszuwerten.

    Shade Of Mine schrieb:

    und das klappt super mit einer bestimmten implementierung.

    Jap. Und wenn es dann noch ein standardisiertes std::type_info::[pretty_]name() gäbe, könnte ich meine mit C++Builder unter Windows serialisierten Objekte mit GCC unter Linux weiterverwenden. Ein veritabler Mehrwert.
    (Allerdings hast du, wie ich bereits sagte, recht darin, daß das nicht undurchdacht ist. Es wäre nur eher ein äußerst sinnvolles zusätzliches Zusatzfeature gewesen. Aber das war ja auch nicht mein Kernpunkt bzgl. std::type_info.)

    Shade Of Mine schrieb:

    Natürlich soll nicht jede Sprache alles können - aber value semantik ist etwas wichtiges: es muss sprachen mit value semantik geben.

    Auch da stimme ich zu. Aber oben erwähntes Designproblem halte ich genauso für unpragmatisch radikal wie "alles ist ein Objekt".

    Man hätte auch in C++, ohne die heutigen Möglichkeiten einzuschränken, durchaus sauber zwischen Werte- und Referenzsemantik trennen können. Daß es nicht so kam, hängt aber vornehmlich mit der evolutionären Entstehung der Sprache zusammen ("C mit Klassen"), daher listete ich das auch nicht unter "undurchdacht".



  • u_ser-l schrieb:

    asc schrieb:

    Nach der Definition lernt auch jeder Java und C# Entwickler C.

    wußte gar nicht, daß java und C# Zeigerarithmetik haben.

    Aha, also sobald Zeiger in einer Sprache sind, ist es C? Sehr interessante Theorie.



  • gähn.

    Wenn es C enthält, enthält es auch Zeigerarithmetik.

    Enthält es keine Zeigerarithmetik, enthält es auch nicht C.

    Das ist übrigens keine "Theorie", sondern banale Tautologie (hä? Banana was ? 😮 )



  • audacia schrieb:

    Shade Of Mine schrieb:

    Und damit ist exception chaining nicht mehr möglich.

    Interessanterweise implementiere ich in der Unit, die ich in obigem Artikel bespreche, Exception-Chaining für gewöhnliche C++-Exceptions (std::exception-Derivate).

    Ich vermute ueber eine art pimpl? habe ich aber bereits erwaehnt dass das moeglich ist.

    aber ich sehe immernoch keinen grund warum es ein design fehler ist, dass ich alles werfen darf.

    ein vorteil ist, dass ich exception chaining haben kann ohne wrapper zu brauchen. oder aber ich werfe exception ohne allokationen zu haben - da ich eine exception pre-allocaten kann und dann werfe wenn ich muss.

    massig moeglichkeiten.

    Außerdem ist doch gerade Exception-Chaining ein Argument für einheitliche Exceptions. Du kannst jede innere Exception wrappen, ohne ihren Typen zu kennen. Da du sie auf das polymorphe std::exception& reduzieren kannst, ist es den Handlern der äußeren Exception möglich, spezielle innere Exceptions, von denen deine äußere Exceptions gar nichts weiß, mittels Polymorphie zuzugreifen und auszuwerten.

    kann ich problemlos haben wenn ich will.

    Man hätte auch in C++, ohne die heutigen Möglichkeiten einzuschränken, durchaus sauber zwischen Werte- und Referenzsemantik trennen können. Daß es nicht so kam, hängt aber vornehmlich mit der evolutionären Entstehung der Sprache zusammen ("C mit Klassen"), daher listete ich das auch nicht unter "undurchdacht".

    genauso wie java, dass keine value semantik anbietet?
    ich meine, es gibt ja nichtmal call by reference...

    ist das auch undurchdacht?



  • Shade Of Mine schrieb:

    Ich vermute ueber eine art pimpl? habe ich aber bereits erwaehnt dass das moeglich ist.

    Ja, aber wenn es nur von std::exception abgeleitete Exceptions gäbe, wäre das nicht nötig gewesen:

    typedef std::exception* PCppException; // mittels $HPPEMIT
    
    class PASCALIMPLEMENTATION ECppException : public Sysutils::Exception
    {
    private:
    	System::AnsiString FTypeName;
    	PCppException *FException; // zeigt auf die statisch, also z.B. auf dem
    	                           // Stack allozierte innere Exception,
    	                           // die dann vom entsprechenden Handler
    	                           // destruiert würde
    	__fastcall ECppException(char * _TypeName, void * ExcDesc)/* overload */;
    	...
    
    public:
    	__property PCppException StdException = {read=FCppException};
    	...
    };
    

    Sofern oben erwähnte Regeln existierten, wäre das dann auch in Standard-C++ machbar. Zeig mir mal, wie du das machst unter Berücksichtigung der gegenwärtigen "Zusatzfeatures", die ich für eine Beschränkung halte.

    Shade Of Mine schrieb:

    aber ich sehe immernoch keinen grund warum es ein design fehler ist, dass ich alles werfen darf.

    Es fällt einfach unter dein "wozu braucht man das" und behindert o.g. Mechanismen.

    Shade Of Mine schrieb:

    ein vorteil ist, dass ich exception chaining haben kann ohne wrapper zu brauchen.

    Wie das?

    Shade Of Mine schrieb:

    oder aber ich werfe exception ohne allokationen zu haben - da ich eine exception pre-allocaten kann und dann werfe wenn ich muss.

    Das geht genauso mit std::exception-Typen.

    Shade Of Mine schrieb:

    kann ich problemlos haben wenn ich will.

    Dann zeig mal her. Das glaube ich nämlich nicht.

    Shade Of Mine schrieb:

    genauso wie java, dass keine value semantik anbietet?
    ich meine, es gibt ja nichtmal call by reference...

    ist das auch undurchdacht?

    Lies genauer. Ich sagte ja, daß es nicht undurchdacht, sondern eine evolutionäre Fehlbildung ist.

    Bei Java wird das nicht undurchdacht, sondern gewollt gewesen sein. Aber ich weiß nicht, weshalb du andauernd den Vergleich mit Java forcierst. Sieh dir doch mal z.B. in Delphi die Trennung von Records (für die es z.B. Operatorenüberladungen gibt) und Klassen (die immer polymorph sind und sämtlich von TObject ableiten) an. In .NET ist das IIRC ähnlich. Das hätte man für C++ noch ein wenig ausbauen können, hätte dann mit structs die Wertesemantik wie heute, in Klassen aber z.B. standardmäßig keinen Kopierkonstruktor, standardmäßig Heap-Allokation, immer eine VTable etc.


Anmelden zum Antworten