ist cout eine statische Klasse?



  • Nur weil etwas selten Sinn macht, wird es nicht in C++ eingebaut? Wo du solche Logik her nimmst ist mir aber auch schleierhaft. Ich denke es wird viel in C++ geben was eher selten gebraucht wird.

    Schnittstellen sind deswegen in anderen OOP-Sprachen drin, weil man damit Mehrfachvererbung vermeiden kann(Diamant-Problem etc.)

    Andere Programmiersprachen sind ja nicht so erfolgreich, weil C++ alles so gut macht. Eierlegende Wollmilchsäue sind immer zu meiden, wenn es spezialisierte Werkzeuge gibt, die einem das Leben einfacher machen. Und so ist es schließlich ja auch gekommen, wenn man für was C#, Java, Python, PHP etc. anstelle von C++ nehmen kann macht man dies natürlich und das nicht ohne Grund.

    Ich gebe zu von C++ noch nicht viel Ahnung zu haben. Ich sehe C++ halt als die absolute Herausforderung, weil es keine kompliziertere Programmiersprache gibt, nirgends werden einen solche Stolpersteine beim Entwickeln in den Weg gelegt. Nirgends ist die Lernkurve so krass. Das ist wie Auto fahren wo man sogar die Einspritzung manuell per Regler einstellen muss. Die einen sehen dies als den ultimativen Vorteil, die anderen wollen einfach nur so gut wie möglich von A nach B kommen.



  • An Mehrfachvererbung ist erstmal ueberhaupt nichts boese und das Diamantproblem (das in maenchen Faellen sogar erwuenscht sein kann btw) tritt nur auf, wenn man sich besonders dumm anstellt. Immer die selbe von Java/C#-Marketingspruechen gezeichnete, gequirlte Kacke. "Oh wir sind so toll, bei uns kann das Diamantproblem nicht auftreten!" - Anstatt es einfach zur Compilezeit zu verbieten, hat man gleich Mehrfachvererbung verboten. Kein Wunder, dass solche Leute nur schreckliches C++ produzieren.

    Zum Rest nehme ich nicht Stellung, dazu enthaelt mir der Post zu viel Blahblah.



  • OOOOOOOOP schrieb:

    Das ist wie Auto fahren wo man sogar die Einspritzung manuell per Regler einstellen muss. Die einen sehen dies als den ultimativen Vorteil, die anderen wollen einfach nur so gut wie möglich von A nach B kommen.

    Es gibt da ein Wort wobei ich wiedersprechen würde. Man muss in C++ die Einspritzung nicht per Regler einstellen, die ist von Hause aus auf einen sinnvollen Wert eingestellt. Es gilt als guter Stil den Regler nicht anzufassen wenn man ihn nicht unbedingt braucht.

    Auf deine Situation angewendet: Wenn du eine Klasse willst, die nur statische Funktionen hat, dann schreib sie halt. Ich habe sowas auch schon gebraucht, weil Namensräume nicht gereicht haben, weil man in Namensräumen kein private hat. Später habe ich dann festgestellt, dass anonyme Namensräume das Problem besser lösen.

    C++ hat als Grundprinzip, dass der Programmierer tun kann wie er lustig ist. Es gibt Hilfen, die verhindern sollen, dass man sich versehentlich vertut, aber wenn man will kann man praktisch alles aushebeln, was es an Sicherheitsmechanismen gibt. Mit steigender Erfahrung stellt man aber fest, dass es sich im Nachhinein als schlecht heraus stellt, wenn man es tut. Deshalb wettern die Leute hier, dass static Klassen Blödsinn sind, weil es dafür bessere Möglichkeiten gibt.



  • OOOOOOOOP schrieb:

    Nur weil etwas selten Sinn macht, wird es nicht in C++ eingebaut? Wo du solche Logik her nimmst ist mir aber auch schleierhaft. Ich denke es wird viel in C++ geben was eher selten gebraucht wird.

    selten Sinn machen != selten gebraucht werden
    Und wie schon öfters gesagt, statische Klassen sind C++ Namespaces, nur die Aufrufsyntax ist anders.

    Schnittstellen sind deswegen in anderen OOP-Sprachen drin, weil man damit Mehrfachvererbung vermeiden kann(Diamant-Problem etc.

    Es gibt auch so etwas wie Schnittstellen in C++: Klassen, die nur pure virtuelle Funktionen haben. Das SIND Schnittstellen.

    Andere Programmiersprachen sind ja nicht so erfolgreich, weil C++ alles so gut macht. Eierlegende Wollmilchsäue sind immer zu meiden, wenn es spezialisierte Werkzeuge gibt, die einem das Leben einfacher machen. Und so ist es schließlich ja auch gekommen, wenn man für was C#, Java, Python, PHP etc. anstelle von C++ nehmen kann macht man dies natürlich und das nicht ohne Grund.

    Jede Programmiersprache, die turing complete ist, ist eine Eierlegende Wollmilchsau. Und C# und Java sind imo genauso allgemein wie C++, da man damit auch so gut wie alles programmieren kann. Python und PHP sind spezialisierte Werkzeuge, aber nicht C# oder Java.
    Und das Blöde an C# und Java ist halt: Die Sprache ist auf OOP ausgelegt. Nicht-OOP zu machen ist genauso blöd wie OOP in C. Es ist möglich, aber aufwendig. In C++ kann man so programmieren wie man möchte. Das ist das tolle daran. Du willst OOP? Kein Ding: Vererbung, Interfaces und dynamische Polymorhpie. Du willst prozedural? Kein Ding: Keiner zwingt dich irgendeine Klasse zu nutzen. Du willst funktional? Kein Ding.
    Aber wirklich ausnutzen nutzt man die Sprache nur, wenn man all diese Dinge vereint. Ja, dazu muss man alle Features beherrschen. Aber wenn man es kann, macht es richtig Spaß darin zu programmieren. Dann merkt man richtig, wie gut die einzelnen Features ineinander greifen und wie toll diese komplexen Regeln doch sind.

    Ich gebe zu von C++ noch nicht viel Ahnung zu haben. Ich sehe C++ halt als die absolute Herausforderung, weil es keine kompliziertere Programmiersprache gibt, nirgends werden einen solche Stolpersteine beim Entwickeln in den Weg gelegt.

    Wenn du versuchst, wie in C zu programmieren ohne Destruktoren und Klassen aus der Standardbibliothek, dan ja.

    Nirgends ist die Lernkurve so krass.

    C++ hat ein Imageproblem. Mit einem guten Tutorial, was die Container etc. nutzt, ist die Lernkurve nicht so krass. Gut, die virtuelle Funktionsüberschreibung in Mehrfachvererbung ist kompliziert, die Name Lookup Rules in Templates mit Vererbung sind bescheuert und die Konversionregeln komplex, aber ansonsten...


  • Mod

    Klassen, die nur pure virtuelle Funktionen haben.

    Nein, Klassen die mindestens eine pur virtuelle Funktion haben. Das sind dann abstrakte Basisklassen, oder eben Schnittstellen.

    die Name Lookup Rules in Templates mit Vererbung sind bescheuert

    Wieso sind die bitte bescheuert? Wovon redest du da!? 😕


  • Mod

    @Nathan: Man kann und sollte(!) in C auch sehr gut OOP machen. Die Sprache kommt einem bloß nicht mit direkter Unterstützung direkt entgegen. C ist viel größer und besser, als einem die kleinen Beispielprogramme in Programmierhandbüchern vorgaukeln.



  • Arcoth schrieb:

    Klassen, die nur pure virtuelle Funktionen haben.

    Nein, Klassen die mindestens eine pur virtuelle Funktion haben. Das sind dann abstrakte Basisklassen, oder eben Schnittstellen.

    AFAIK haben Interfaces in Java und Co auch nur pure virtuelle Funktionen oder irre ich mich?

    die Name Lookup Rules in Templates mit Vererbung sind bescheuert

    Wieso sind die bitte bescheuert? Wovon redest du da!? 😕

    kkaw schrieb:

    Aktuelles Beispiel:

    typedef typename soundso<T>::template foo<T> blah_t;
    

    Dass man manchmal "typename" und "template" in solchen Fällen braucht, ist halt peinlich.

    Ist das schön? Und in Vererbung kommt da dann noch ein this-> bzw. BaseClass:: vor.

    SeppJ schrieb:

    @Nathan: Man kann und sollte(!) in C auch sehr gut OOP machen. Die Sprache kommt einem bloß nicht mit direkter Unterstützung direkt entgegen. C ist viel größer und besser, als einem die kleinen Beispielprogramme in Programmierhandbüchern vorgaukeln.

    Genau das meinte ich: Die Sprache kommt nicht mit direkter Unterstützung entgegen. Deshalb muss man in C Destruktoren, Vererbung, virtuelle Funktion, Kapselung etc. ziemlich umständlich implementieren. Und in Java/C# sind das eben die freien Funktionen.


  • Mod

    Ist das schön?

    Darum geht es nicht.
    Sie sind nicht nicht bescheuert, sondern eine voll funktionsfähige Methode, die Ambiguitäts-Probleme zu lösen.

    Unter bescheuert verstünde ich folgendes: Überhaupt nicht intuitiv, extrem schwer zu erlernen - Compiler implementieren es dank der vielen komplizierten Regeln meistens im Detail unterschiedlich bzw. falsch, es ließe sich leicht zu einem viel besseren System umändern, usw.
    ~Edit: Das ist doch nicht etwa eine Liste, die Templates heutzutage ausmacht, oder?~

    typename vor abhängige Namen zu schreiben ist leicht zu erlernen - jeder Anfänger tut das mittlerweile nachdem er die Regel kennt.
    Der Rest ist ebenfalls einfach eine Regel die man sich einmal merken muss, und nicht merkbar komplizierter. Es gibt auch relativ wenig Inkonsistenz oder Ausnahmen.



  • Arcoth schrieb:

    typename vor abhängige Namen zu schreiben ist leicht zu erlernen - jeder Anfänger tut das mittlerweile nachdem er die Regel kennt.

    Und dann kommt noch template dazu, und wie ist das eigentlich mit Alias Templates?
    Selbst wenn die Regeln einfach waeren - was sie nicht sind - ist es trotzdem eine Schnapsidee.


  • Mod

    Und dann kommt noch template dazu

    Trivial.

    , und wie ist das eigentlich mit Alias Templates?

    Beziehst du dich auf diesen Thread?

    Nur um das gleich klarzustellen: Ja, es ist halt nicht ganz einfach, das ist recht offensichtlich. Aber ihr übertreibt alle ein wenig, findet ihr nicht?





  • Arcoth schrieb:

    Aber ihr übertreibt alle ein wenig, findet ihr nicht?

    Nein. In der Begeisterung über gewisse Möglichkeiten tendiert man dazu, Unschönheiten zu verharmlosen. Manchmal erkennt man die Tragweite auch erst, wenn man sieht, wie es anderswo viel einfacher geht.

    C++ hat durchaus seine Probleme. Und nicht wenige. Dazu sollte man stehen 🕶



  • staticClass schrieb:

    cout kann ich ja einfach benutzen, ohne immer extra überall erst eine Instanz davon erzeugen zu müssen. Wie macht man so eine Klasse?

    cout ist eine Instanz von ofstream:
    Die Deklaration findest du in der Form: extern ostream cout;



  • <a href= schrieb:

    LLVM Coding Standards">The use of #include <iostream> in library files is hereby forbidden, because many common implementations transparently inject a static constructor into every translation unit that includes it.



  • OOOOOOOOPPPPP schrieb:

    Welchen Sinn statische Klassen machen? Na, wenn man im gesamten Projekt eh nur eine Instanz braucht, aber trotzdem Kapseln will. Einmal global instanzieren und dann noch mit Singleton wäre der schlechte Weg, der schöne ist dann einfach eine statische Klasse zu nehmen.

    Mir kommt es langsam so vor, als wenn einige C++ler hier selten über den Tellerrand schauen und OOP wirklich nur von C++ her kennen und den Rest mit einer riesen Ignoranz gegenübertreten und es als Kindersprachen etc. abtun. Es gibt schon gute Gründe für statische Klassen und dem Programmieren gegen Schnittstellen, sonst hätte viele OOP-Sprachen das gar nicht eingebaut.

    Erst mal danke für die Antwort.

    Ich bin an einer gepflegten Diskussion durchaus interessiert. Dafür möchte ich aber nicht vorgeworfen bekommen, dass ich selten über den Tellerrand schaue. Das ist nicht sachlich.

    Es kann sein, dass es Argumente für statische Klassen gibt. Und genau die habe ich angefragt.

    Dafür sollten wir erst mal feststellen, was statische Klassen sind. Das sind Klassen, die ausschließlich statische Member haben. Richtig?

    Eine Klasse ist etwas, was ich instantiieren kann. Bei so einer statischen Klasse macht das aber keinen Sinn. Daher halte ich eine statische Klasse für unlogisch. Was von der statischen Klasse übrig bleibt sind Memberfunktionen ohne Instanz. Und welche Vorteile haben diese Memberfunktionen nun gegenüber freien Funktionen in einem Namensraum?

    Ich würde mich über eine gepflegte Antwort freuen, in der ich nicht beschimpft werde, dass ich unwissend bin oder engstirnig bin.



  • Man müsste dazu noch sagen: In C++ machen "statische Klassen" durchaus Sinn, aber nicht in dem von "OOP" vorgesehenen Anwendungsfall. Weil es diesen Anwendungsfall in anderen Sprachen gar nicht gibt.

    Die sinnvollen Anwendungen fallen hauptsächlich in den Bereich der Template-(Meta-)Programmierung. Type Traits, Policies, Tag Dispatchers, etc. haben sehr selten nicht-statische Member.



  • Und welche Vorteile haben diese Memberfunktionen nun gegenüber freien Funktionen in einem Namensraum?

    Sichtbarkeit und Kapselung fallen mir da spontan ein.


  • Mod

    OOOOOOOOOP schrieb:

    Und welche Vorteile haben diese Memberfunktionen nun gegenüber freien Funktionen in einem Namensraum?

    Sichtbarkeit und Kapselung fallen mir da spontan ein.

    Dafür gibt's ja praktischerweise anonyme namespaces*. Wurde hier im Thread auch schon gesagt. Dann sieht man die Implementierungsdetails nicht einmal mehr in der Klassendefinition.

    *: Mit leichten Abstrichen kann man das auch mit static erreichen.



  • OOOOOOOOOP schrieb:

    Und welche Vorteile haben diese Memberfunktionen nun gegenüber freien Funktionen in einem Namensraum?

    Sichtbarkeit und Kapselung fallen mir da spontan ein.

    Kapselung verstehe ich. Man kann Member teilweise privat machen, so dass nur andere Member darauf zugreifen dürfen. Die Sichtbarkeit sehe ich aber eher als Nachteil.

    Alternativ kann man ja, wie SeppJ sagt, anonyme namespaces verwenden und Daten und Funktionen vor anderen komplett zu verbergen.

    Bei statischen Klassen geht genau das nicht, da die Deklaration von privaten membern auch an der öffentlichen Schnittstelle bekannt sein muss. Das ist natürlich eine Eigenschaft von C++, die an sich als Nachteil von C++ angesehen werden kann.

    Jetzt würde ich gerne noch erfahren, was der Vorteil von statischen Klassen gegenüber Funktionen im namespace mit anonymen namespaces ist.


Anmelden zum Antworten