Seite 2 von 2 « Erste 12
Ergebnis 21 bis 36 von 36

Fragen zu C++ (aus Softwarefragen und -probleme)

  1. #21 Zitieren
    Tieftöner Avatar von Lookbehind
    Registriert seit
    Dec 2007
    Beiträge
    15.176
    Zitat Zitat von jabu Beitrag anzeigen
    Funktioniert leider nicht, denn bei C++ sind die Typen nicht nullable. Vielleicht schaffe ich es heute abend noch, etwas zu posten.
    Macht in diesem Fall nix, einfach mit nem negativen Wert initialisieren. Da es sich um einen Flächeninhalt handelt, kann der eigentlich nicht negativ werden. In der geter-Methode prüfst du dann statt null auf <0 und weißt so, ob du neu berechnen muss, oder nicht.
    Lookbehind ist offline

  2. #22 Zitieren
    Pretty Pink Pony Princess  Avatar von Multithread
    Registriert seit
    Jun 2010
    Ort
    Crystal Empire
    Beiträge
    11.228
    Zitat Zitat von jabu Beitrag anzeigen
    Funktioniert leider nicht, denn bei C++ sind die Typen nicht nullable. Vielleicht schaffe ich es heute abend noch, etwas zu posten.
    In dem Fall, würde Ich den Code wie nachfolgend verwenden:

    Code:
    public class Rechteck{
      private int area;
      private bool isAreaCalculated=false;
      public int getArea()
      {
        if(!isAreaCalculated){
          area=width*length);
          isAreaCalculated=true;
        }
        return area;
      }
    
      public void CLear(){
        isAreaCalculated=false;
      }
    
      public void setSize(int inlenght, int inWidth){
        //Felder setzen
    
        Clear();
      }
    }
    Gleiches Prinzip wie oben, nur umständlicher und wohl auch einiges hässlicher.
    Dafür Kanst du den 'getter' Code 1:1 Kopieren wenn du mehr davon brauchst und es funktioniert, egal was für einen Rückgabetyp und Wertbereich der getter hat

    Die Idee von Lookbehind finde Ich in dem Fall auch sehr schön. Möglich wäre da auch noch etwas wie Int.MaxValue oä. welche normalerweise ausserhalb liegen und keine Kollision verursachen sollten.
    [Bild: AMD_Threadripper.png] Bei Hardware gibt es keine eigene Meinung, bei Hardware zählen nur die Fakten.


    Probleme mit der Haarpracht? Starres Haar ohne Glanz? TressFX schafft Abhilfe. Ja, TressFX verhilft auch Ihnen zu schönem und Geschmeidigen Haar.
    [Bild: i6tfHoa3ooSEraFH63.png]
    Multithread ist offline

  3. #23 Zitieren

    Metasyntaktische Variable
    Avatar von foobar
    Registriert seit
    Sep 2004
    Ort
    Direkt hinter dir! Buh!
    Beiträge
    23.996
    Zitat Zitat von Lookbehind Beitrag anzeigen
    Macht in diesem Fall nix, einfach mit nem negativen Wert initialisieren. Da es sich um einen Flächeninhalt handelt, kann der eigentlich nicht negativ werden. In der geter-Methode prüfst du dann statt null auf <0 und weißt so, ob du neu berechnen muss, oder nicht.
    Kann nach hinten losgehen. So, wie es aktuell gecodet ist, kann der Inhalt sehr wohl negativ sein. In dem bisher geposteten Code wird nirgendwo geprüft, ob die Dimensionen negativ sind. Wer das Rechteck bspw. mit den Werten (5, -4) initialisiert, kriegt am Ende auch eine Fläche von -20.

    Ob das Sinn macht, hängt wieder mal von der Fragestellung ab. Entweder man sagt, dass bereits die Maße nicht negativ sein dürfen. Ungültige Werte zu verhindern, ist ja u.a. der Sinn von Setter-Methoden. Oder man sagt, dass die Dimensionen durchaus negativ sein können. Da kommt wieder die Frage nach der Position, denn von einem beliebig gewählten Koordinatenpunkt kann ich natürlich auch in die negative Richtung gehen, um mein Rechteck zu zeichnen. Dann sollte man spätestens bei der Flächenberechnung den Betrag nehmen. Eventuell kann es mathematisch aber auch manchmal sinnvoll sein, negative Flächeninhalte zuzulassen.

    Klar, bei einem rein didaktischen Beispiel ohne praktische Relevanz braucht man sich nicht verrückt zu machen. Allgemein wäre ich mit sowas aber vorsichtig.
    foobar ist offline

  4. #24 Zitieren
    Legende Avatar von jabu
    Registriert seit
    Jul 2011
    Beiträge
    7.322
    Zitat Zitat von Lookbehind Beitrag anzeigen
    Macht in diesem Fall nix, einfach mit nem negativen Wert initialisieren. Da es sich um einen Flächeninhalt handelt, kann der eigentlich nicht negativ werden. In der geter-Methode prüfst du dann statt null auf <0 und weißt so, ob du neu berechnen muss, oder nicht.
    Vielleicht, wenn nicht stört, was foobar dazu sagte. Ich würde den Gedanken, so reizvoll er auch sein mag, vorsichtshalber zurückstellen wollen, um den Code nicht vorschnell an so ein Verhalten anzunageln. Für den Hinterkopf ist das natürlich nicht schlecht. Eine andere Möglichkeit folgt weiter unten im Text.

    Meine Meinung (allgemein gesprochen):
    Ich halte nichts von ungültigen oder umständlich abzufragenden Zuständen von Objekten. So etwas würde ich nur wegen verdammt wichtiger Gründe machen. Einer dafür wäre, dass rechenintensive oder ressourcenlastige Prozesse ausgeführt werden müssen, die es zu minimieren oder an einen geeigneten Zeitpunkt zu verschieben gilt (wobei es auch dafür meistens einfach benutzbare Lösungen gibt). Ein anderer wäre ein unvorhersehbares Scheitern eines Vorganges, wo Exceptions ausnahmsweise nicht das Mittel der Wahl sind. Optionale Flags sind eine andere (zusätzliche) Ebene.

    Dagegen halte ich sehr viel von
    • intuitiv korrekt benutzbaren Schnittstellen
    • erwartbarem Verhalten (bzgl. Laufzeit, Seiteneffekte etc.)
    • Vermeidung von Noise im Code
    • fast allem, was Whiz-zarD schrieb
    • . . .

    Man muss sich doch nur für eine dieser im Gebrauch idiotensicheren Varianten entscheiden, je nach erwünschtem Verhalten:
    1. Möglichst zustandsarm, einfach und übersichtlich:
      Berechnung immer bei der Abfrage. Das eignet sich hier, wie Whiz-zarD schon ausführte, wegen der unerheblichen Laufzeit (wenn nicht in kurzer Zeit viele Objekte abgefragt werden müsssen) besonders gut.
    2. Möglichst schnelles und vorhersehbares Laufzeitverhalten bei der Abfrage:
      Sofortige Berechnung beim Initialisieren sowie jeweils beim erneuten Setzen der Werte. Meistens ist das erwünscht, denn beim Abfragen der Werte steht fest, dass keine Zeit mehr für Berechnungen aufgewendet werden muss. Und ein cleverer Compiler oder eine clevere CPU dürfte hier einiges herausholen können, denn es gibt keine Branches.
    3. Möglichst Berechnungen vermeiden, wenn die Ergebnisse nicht gebraucht werden:
      Damit wären wir bei der ersten Fassung, die uns der TE gezeigt hat. Bei langwierigen (Berechnungen oder ressourcenhungrigen) Vorgängen, deren Notwendigkeit vorher nicht feststeht, kann das durchaus fruchtbar sein.

    Nun müsste man wissen, was der Dozent will. Sonst müssten wird bereits hier drei verschiedene Wege beschreiten.

    Aber ich sehe nicht bei einem einzigen dieser drei Wege die Notwendigkeit, von intuitiv korrekter Benutzbarkeit abzurücken. Ich sehe nicht, warum ein Shape in irgendeiner Weise uninitialisierte oder unplausible Werte ausgeben sollte (die nicht konsequent reflektieren, was man eingegeben hat). Und wenn es diese wirren Zustände nicht gibt, dann muss das Objekt auch nicht rücksetzbar sein.

    Vielleicht kann es irgendetwas signalisieren (siehe "perimeter not definable"), aber die Benutzung wäre rein optional. Bei Gleitkommazahlen gibt es eine Konstante für Not a Number, was sich verwenden ließe, damit solches dem User wenigstens auffällt, wenn er den Fall nicht abfängt und vielleicht sogar damit weiterrechnet. Ich würde das aber nicht prioritär verwenden, sondern als Notbehelf, wenn alles andere versagt hat. Eine weitere Variable (Typ mit garantierter Anzahl an Bits nehmen) kostet doch nicht viel (hängt vom Alignment ab). Die könnte ein Statuswort beinhalten, aus dem man mit einer Maske Flags ausliest. Aber das ist jetzt nicht an der Reihe.

    Zu konkreten Hinweisen und zum Code komme ich jeweils später.
    jabu ist offline Geändert von jabu (04.06.2018 um 23:22 Uhr)

  5. #25 Zitieren
    Legende Avatar von jabu
    Registriert seit
    Jul 2011
    Beiträge
    7.322
    1. Verwendete Programmiersprache

    Welches C++ soll verwendet werden?
    Es besteht (von wenigen Details abgesehen) Abwärtskompatibilität.
    Im Wesentlichen unterscheidet man zwischen
    • ISO/IEC 9899:1999 (kurz: C++98)
    • ISO/IEC 14882:2003 (kurz: C++03)
    • ISO/IEC 14882:2011 (kurz: C++11)
    • ISO/IEC 14882:2014 (kurz: C++14)
    • ISO/IEC 14882:2017 (kurz: C++17)

    - Alles vor C++98 spielt praktisch keine Rolle mehr.
    - Von C++98 kann heutzutage abgeraten werden, denn es fehlen viele sinnvolle Features, welche sicheres Programmieren befördern.
    - C++03 kann als ein korrigiertes und gereiftes C++98 angesehen werden. Im Jahr 2006 wurde es technisch überarbeitet (was sich auf die Performance auswirken soll). Die meisten Codeschnipsel aus Tutorials kommen mit C++03 (oder mit nur wenig mehr) aus. Es fehlen aber immer noch einige sinnvolle Features, die das Programmieren sicherer machen.
    - C++11 kann als eine neue Programmiersprache angesehen werden. Der Umfang ist gewaltig angewachsen (u.a. funktionales Paradigma).
    - C++14 enthält kleine Ergänzungen zu C++11, welche manches Konzept erst flexibel verwendbar machen.
    - C++17 hat ähnliche Ergänzungen wie C++14 hinzugefügt. Zudem sind mehr Features als bei C++14 hinzugekommen.

    Der größte Bruch ist zwischen C++03 und C++11 erfolgt. Wenn du mich fragst, was ich zum Lernen empfehlen würde, dann würde ich zur aktuellen Variante raten, also zu C++17. Aber die Gründe dafür sind andere als noch bei C++11. Während bei C++11 bahnbrechende Features hinzugekommen sind, von denen man einiges in didaktische Konzepte integrieren möchte, um bei Einsteigern Frust zu vermeiden und die Lernkurve steiler verlaufen zu lassen, geht es bei C++14 und C++17 mehr darum, Lücken zu schließen, damit die mit C++11 eingeführten Konzepte schön ineinandergreifen. Es geht dabei also vor allem um eine Generalisierung bereits vorhandener Konzepte.

    Für den Einstieg ist diese Form von Vollendung nicht unbedingt nötig, zumal es sich überwiegend um Ecken handelt, mit denen Einsteiger eher selten in Berührung kommen. Das kann sich ändern, wenn Literatur C++17 voraussetzt und neue Ansätze verfolgt, aber bisher ist das Feld dünn gesät. Für die neueren Versionen spricht vor allem, dass sie wegen der geschlossenen Lücken eher der Intuition entsprechen. Man fragt sich nicht mehr so oft, warum dieses oder jenes, was einzeln geht, nicht mehr geht, sobald man es miteinander kombiniert.

    Mittlerweile kann i. d. R. C++11 für neue Projekte mit dem PC als Zielplattform als der kleinste gemeinsame Nenner angesehen werden. Trotzdem sollte man sich dafür möglichst aktuelle Compiler besorgen. Aber wenn man mit anderen zusammenarbeitet, z. B. beim Lernen oder bei Teamarbeit, müsste man sich auf eine Version von C++ einigen, denn nicht unter allen Umständen hat jeder einen Compiler zur Hand, der den aktuellen Standard vollumfänglich und korrekt umsetzt (noch vor enigen Jahren konnte kein Compiler das, und der von Microsoft hinkte teils ein Jahrzehnt hinterher; nun ist Microsoft mit an der Spitze, weil man einsehen musste, dass das maximal gepushte C# eben doch nicht für alles taugt), was leicht dazu führen kann, dass der Code nicht bei jedem übersetzbar ist, möglicherweise auch nicht beim Dozenten.

    Immerhin ist die Situation bezüglich Feature Completeness bei den gängigsten Compilern noch nie so gut wie heute gewesen. Einen groben Überblick verschafft diese Seite. Das gibt wenig Anlass zur Sorge. Dennoch würde ich mich nicht felsenfest darauf verlassen wollen, dass überall alles, was behauptet wird, auch tatsächlich standardkonform funktioniert. Ich kompiliere, wenn es darauf ankommt, mit GCC, Clang und MSVC. Das hilft auch dabei, Fehler zu entdecken, welche ein allzu toleranter Compiler hat durchgehen lassen.

    Auch das Setzen der Compileroptionen ist ein Thema für sich, denn irgendwie muss dem Compiler mitgeteilt werden, welchen Standard er befolgen soll, wenn er denn mehrere anbietet. Du fragst dich, ob das schon für deinen einfachen Code relevant ist? Leider ist es relevant, wie ich ziemlich schnell feststellen musste, doch dazu später.
    jabu ist offline Geändert von jabu (05.06.2018 um 03:18 Uhr)

  6. #26 Zitieren
    Ritter
    Registriert seit
    Feb 2003
    Beiträge
    1.554
    Ich denke, das geht viel zu sehr ins Detail. Ich denke, es sollte rein nur um Vererbung gehen. Es sind Maschinenbauer und keine Informatiker. Das Beispiel mit den Shapes und der Berechnung von Umfang und Flächeninhalt ist das bekannteste Beispiel von Robert C. Martin.

    Ja, man könnte überlegen, im Konstruktor die Werte dahingehend zu überprüfen, ob sie größer 0 sind, denn negative Zahlen machen keinen Sinn. Das stellt ja kein Beinbruch dar. Das ist im Minimalfall eine if-Anweisung im Konstruktor.
    Whiz-zarD ist offline

  7. #27 Zitieren
    Legende Avatar von jabu
    Registriert seit
    Jul 2011
    Beiträge
    7.322
    2. Verwendete Tools

    Wie im ersten Teil angedeutet, muss dem Compiler der zu befolgende Sprachstandard mitgeteilt werden. Man könnte meinen, es würde genügen, einen halbwegs aktuellen und standardkonformen Compiler zu verwenden. Doch das wäre ein Trugschluss! Weder der erste noch der zweite Code geht durch einen C++- Compiler (was die Portabilität einschränkt):

    Code:
    cin >> number;
    Shape *Memory[number];
    Das ist ein Variable Length Array (VLA), was es in keinem offiziellen C++-Standard gibt! Zudem werden hier Fehler (negative bzw. zu große Werte) nicht abgefangen, weswegen das Programm abstürzen kann, aber darum soll es hier nicht gehen. Ich beziehe mich vorsichtshalber auf das VLA, obwohl es irgendwann ersetzt werden soll.

    Code:
    area=((M_PI)/4)*diameter*diameter;
    M_PI aus math.h gehört nicht zu C++! Es gibt unter C++ (im Gegensatz zu C) keine mathematischen Konstanten. Aber man kann sie bei den mir bekannten C++-Compilern über ein Makro verfügbar machen, was eine rein optionale Möglichkeit ist (ebenso wie selbst geschriebener Code, aber im Gegensatz dazu liegt er nun an der falschen Stelle und ist im Zweifel weg).


    Warum hat dein Compiler das trotzdem übersetzt? Weil er nicht nur standardkonforme Modi anbietet, sondern auch solche mit Erweiterungen, die der C++-Standard nicht kennt. Dabei kann es sich zum Beispiel um herstellerspezifische Erweiterungen oder um solche Bestandteile aus C, welche nicht in den C++-Standard übernommen wurden, handeln. Vermutlich verwendest du einen GNU-Compiler, wenn beides einfach so geht. Wenn kein Sprachstandard angegeben wird, frisst er so ziemlich alles, was Leute mal als nützlich erachtet haben und noch nicht entfernt wurde, beginnend etwa mit dem gemeinsamen Teil der Entwicklung von C und Unix in den 1970ern, was den C-Modus angeht, wobei für den C++-Modus davon viel übernommen wird und die Doku sich darüber ausschweigt (zumindest an passender Stelle), was genau. Es wird für C++ auch einiges hinzugefügt. Es sind durchaus sinnvolle Sachen dabei. Aber die Vermischung mit uraltem Kram aus C, der nicht immer gut ist, macht diesen Modus (der wohl wegen alter Skripte zum Steuern des Übersetzungsvorganges beibehalten wird) u. U. sogar riskant.

    Abhilfe:
    Mein GNU-Compiler versteht z. B. diese hilfreichen Parameter:
    Befolgen des C++14-Standards: -std=c++14
    Warnungen bei einigen Fällen der Nichteinhaltung des gewählten Standards: -pedantic
    Einige Fälle der Nichteinhaltung des gewählten Standards als Fehler behandeln: -pedantic-errors
    Viele (nicht alle) Warnungen aktivieren: -Wall
    Zusätzliche Warnungen aktivieren: -Wextra
    Es gibt üblicherweise noch mehr Switches, siehe die Dokumentation zu deinem Compiler.

    Wenn man Code weitergibt, dann können sprachfremde Bestandteile den Unmut der Leute auf sich ziehen, wenn sie für ihre Tools aufwendige Workarounds hineinfriemeln müssten, wobei nicht gesagt ist, dass sie das wollen und schaffen.
    Als (späterer) Projektverantwortlicher (auch Maschinenbauer) möchte man nicht nach einem Wechsel der Toolchain plötzlich mit unkompilierbarem Code (in dem ganze Mannjahre stecken) dastehen und das dem Chef, Kunden oder Investor erklären müssen. Manchmal ist Jahre, nachdem der Code nicht mehr angefasst wurde, nur eine kleine Anpassung nötig, wobei man sich darauf verlässt, dass die jeweils im eigenen Haus verwendete Toolchain das schon packt ("Ist doch alles abwärtskompatibles C++", lautete die trügerische Sicherheit).
    Anderes Beispiel gefällig? Man stelle sich vor, die Firma, ein Teil davon oder nur das Projekt wird verkauft, und der Käufer kommt wegen des nachträglichen Anpassungsaufwandes mit Forderungen über zigtausend Euro auf einen zu, weil in der Dokumentation stand, das Projekt sei in C++ verfasst.
    Umgekehrt möchte man nicht der Käufer sein, der es doch hätte besser wissen müssen.
    Es genügt schon, auf eine rottige Library zu setzen, die es irgendwo umsonst gibt, um sich Probleme einzuhandeln.
    Gerade als Verantwortlicher, der selber nicht programmiert, sollte man wissen, welches Unheil Mitarbeiter ohne böse Absicht (zumeist aus Gewohnheit oder weil irgendwann mal einer damit angefangen hat), anrichten können.
    Und beim Lernen will man die Gewissheit haben, dass man sich nicht etwas angewöhnt, was gar nicht zur Sprache gehört (und daher schon beim nächsten Compiler fehlen kann)! Denn was immer wieder gut funktioniert, führt dazu, dass man die Alternativen ausblendet, sodass man ganz leicht plötzlich auf dem Schlauch stehen kann.

    Die Essenz daraus:
    Indem du den Compiler anweist, sich an den Standard zu halten und möglichst viele sinnvolle Warnungen auszugeben, vermeidest du viele Probleme (nicht nur diese!) von vornherein. Damit sparst du Zeit und Nerven. Übrigens sind heutige C++- Compiler enorm smart. Beim GNU-Compiler und einigen anderen Compilern sind sogar Hinweise zur OOP aktivierbar. Kenne deine Tools.

    Falls du es nicht wusstest: Verwende beim GNU-Compiler für C++ vorsichtshalber nicht gcc, sondern g++. Sonst weiß der Compiler ohne weitere Angaben nicht unbedingt, dass er sich als C++-Compiler betätigen soll, und der Linker könnte gegen falsche Bibliotheken (für C) linken. Implizit (über den Dateinamen) könnte es dennoch klappen, wobei aber die Kontrolle über das korrekte Linken fehlt. Hab's inzwischen ausprobiert: Mein gcc schaltet nicht implizit auf C++ um, was ich lobenswert finde. Wenn man ihm C++-Code gibt, der auch als C-Code gültig ist (leicht möglich), dann fällt der falsche Compiler (für C) natürlich nicht auf, sodass der Code unter seinen Regeln geprüft und gegen falsche Bibliotheken (für C) gelinkt wird, was beides zu subtilen Fehlern führen kann, insbesondere bei mehreren Übersetzungseinheiten, wie bei richtigen Projekten üblich.
    Nicht dass du dich wunderst, wenn es deine IDE (obwohl davon abzuraten ist), trotzdem mit gcc anstatt g++ hinbekommt: Es gibt Compiler Switches, mit denen die Sprache und die Libs explizit ausgewählt werden können. gcc und g++ sind nämlich Compiler Driver, die den Übersetzungsvorgang steuern.
    Wenn die Kommandozeile falsch zusammengesetzt ist (per IDE, Build Script oder User), dann richtet sich der Driver danach. Bei richtigen Projekten kann das durchaus leicht passieren, was vor allem beim Linken eine Rolle spielt, mit teils subtilen Konsequenzen. Also kontrolliert man das Build Log wenigstens bei jeder Änderung am Setup sowie vor Releases penibel (durch Vergleich). Es ist gut, sich das schon mal angesehen zu haben oder zumindest zu wissen, warum Kontrollen wichtig sind.
    jabu ist offline Geändert von jabu (07.06.2018 um 12:29 Uhr)

  8. #28 Zitieren
    Ehrengarde Avatar von Momo
    Registriert seit
    Feb 2011
    Beiträge
    2.142
    Eeeh...
    Also das ist ja alles ziemlich krass und sehr beachtenswert was ihr mir alles so an Tips gegeben habt, das wichtigste, und was ich zu anfang mehrmals erwähnt habe, habt ihr dabei aber vergessen: Ich habe nur sehr wenig Ahnung. Folglich bringen mir die Posts eigentlich überhaupt nichts. Ich glaube ich habe nicht einmal 5% verstanden und es ist genau so wie Whiz-zarD sagt, wir sind keine Informatiker.. auch wenn es euch schmerzen mag, dass ich die Programmiersprache so nicht ausreize. Das mit der negativen Eingabe hätte ich komplett übersehen, das ist was wo ich noch was aus dem Thread mitnehmen kann also wie gesagt bitte nicht böse sein, aber wenn ich nicht verstehe was mir vorgeschlagen wird, kann ich es auch nicht umsetzen. Auch zur Frage welche C++-version wir nutzen.. ich wusste nicht mal, dass es verschiedene gibt. In der uni haben wir Linux-Rechner, die haben ja nem g++ compiler und ansonsten nehme ich jetzt Code::blocks, das hat den auch.
    Danke trotzdem dür die Anstrengungen!
    "The most unusual day would occur when nothing unusual happened."
    Momo ist offline Geändert von Momo (07.06.2018 um 14:39 Uhr)

  9. #29 Zitieren
    Legende Avatar von jabu
    Registriert seit
    Jul 2011
    Beiträge
    7.322
    Zitat Zitat von Momo Beitrag anzeigen
    Eeeh...
    Also das ist ja alles ziemlich krass und sehr beachtenswert was ihr mir alles so an Tips gegeben habt,
    Hauptsache, du bleibst am Ball und schön, dass du dich zurückgemeldet hast.
    Es sollte von unserer Seite noch einiges kommen, zumindest kann ich das für mich sagen, soweit es meine Zeit erlaubt.

    das wichtigste, und was ich zu anfang mehrmals erwähnt habe habt ihr dabei aber vergessen: Ich habe nur sehr wenig Ahnung. Folglich bringen mir die Posts eigentlich überhaupt nichts.
    Keine Sorge, das ist nicht vergessen! Bei Programmiersprachen ist dieses Gefühl, das Dickicht würde sich niemals lüften, ganz normal. Anscheinend hat dich dein Dozent gleich ins kalte Wasser geworfen. Dann musst du dich so lange freischwimmen, bis sich alles fügt. Die Lernkurve hat immer wieder mal exponentielle Anteile, was bedeutet, dass man sich von abschnittweise flachen Anstiegen am jeweiligen Anfang nicht entmutigen lassen sollte.

    Allerdings machst du es uns nicht gerade leicht,
    • deine Kenntnisse einzuschätzen, denn du hast uns nicht verraten, welcher Code von dir stammt. Deine Markierungen bedeuten nicht notwendigerweise, dass du beim Rest nicht involviert warst.
    • den Weg einzuschätzen, den euer Dozent mit euch gehen will, weil du uns leider nicht gesagt hast, welcher
      Code von ihm vorgegeben wurde und was er als Anforderung bzw. Aufgabe formuliert hat.

    Solange du das nicht klar herausgearbeitest hast, musst du leider damit rechnen, dass wir nicht zielgerichtet helfen können, sondern raten und in die Breite gehen müssen, um möglichst viele Varianten abzudecken. Das macht das Erstellen von Antworten schwierig und zeitraubend, weswegen mögliche Lösungen nur angedeutet werden können. Es gibt nämlich nicht die eine Lösung, sondern gefühlt unendlich viele, deren Sinn sich erst daraus ergibt, inwiefern sie den (bisher unbekannten) Anforderungen genügen. Der beste Code ist immer noch derjenige, welcher gar nichts tun muss und sich daran hält. Das klingt lustig, stimmt aber. Bei undefinierten Anforderungen müsste es also für ein leeres Blatt die volle Punktzahl geben, wenn es im Leben immer logisch korrekt zuginge.

    Wer um diese Schwierigkeiten weiß und sich nicht beim Abarbeiten der Eventualitäten verheddern will, schreibt einfach erst mal etwas, was ihm dazu einfällt. Und andere schreiben gar nichts, weil ihnen die Zeit zu kostbar ist. Gute Leute sind meistens beschäftigt, und die besten haben selten Zeit. Deswegen solltest du es ihnen so leicht wie möglich machen.

    Das alles ist selbstverständlich nur konstruktiv gemeint!

    Ich glaube ich habe nicht einmal 5% verstanden und es ist genau so wie Whiz-zarD sagt, wir sind keine Informatiker..
    Deswegen müsstest du dir wohl Grundlagen aneignen.

    auch wenn es euch schmerzen mag, dass ich die Programmiersprache so nicht ausreize.
    Um ein Ausreizen sollte es natürlich nicht gehen, sondern darum, dass du von Anfang an korrekten Code schreibst, damit du nicht mit ziellosem Herumexperimentieren (noch mehr) Zeit verlierst.

    Das mit der negativen Eingabe hätte ich komplett übersehen, das ist was wo ich noch was aus dem Thread mitnehmen kann
    Die Sache mit dem (nicht zu C++ gehörenden) Variable Length Array (VLA) ist weitaus schlimmer:
    Leider genügt es nicht, nur gegen negative Werte zu prüfen, denn bis zum maximalen positiven Wert darf der Stack mitnichten anwachsen. Der Speicher für den Stack wird bereits vor dem Programmstart vom Betriebssystem alloziiert. Er hat also eine feste Größe, und die ist ziemlich klein.
    Bei Ausführung des Programms schwillt der belegte Teil des Stacks mit den Funktionen (wobei die lokalen Variablen bzw. Objekte einen großen Teil ausmachen) auf und ab. Was noch frei ist, dürfte theoretisch das VLA belegen.
    Aber du weißt nicht, wieviel noch frei ist, und seine Größe ist unbekannt, und nach dem VLA werden weitere Daten auf den Stack gepusht, für die auch noch Platz frei sein muss. Insgesamt wird es also irgendwann zu viel, weshalb es zu einem Pufferüberlauf kommt, wenn das VLA nicht vom Programmierer auf einen kleinen Wert, den auch ein Array mit fester Größe haben darf (musst du schätzen), begrenzt wird. Aber dann braucht man das VLA nicht mehr, was die wesentliche Erkenntnis ist, die es in der Regel überflüssig macht. Wenn ein verdammt guter Grund dafür vorliegt, trotzdem eines zu verwenden, dann ist das natürlich etwas anderes.

    Das Ausreizen der Stackreserven ist ein riskantes Unterfangen, zumal der Stack in der Regel mickrig ist (bei vielen Windows-Programmen 1 MB) und die Reserve leicht dahinschwindet, wenn dem Programm etwas hinzugefügt wird. Du bräuchtest eine verdammt gute Abschätzung darüber, was du dir erlauben kannst. Und wenn du dem Programm etwas hinzufügst, stimmt die u. U. nicht mehr. So viele Daten auf dem Stack meidet man normalerweise, damit es nicht zu einem Stack Overflow kommt. Meistens stimmt auch das Performance-Argument nicht (was ein Thema für sich wäre).

    Auf die Gefahr hin, mich teilweise zu wiederholen:
    VLAs sind nicht nur in mehrerlei Hinsicht unsicher und meistens überflüssig wie ein Kropf, sondern auch zum Typsystem von C++ inkompatibel. VLAs sind kein Bestandteil von C++. Ein standardkonformer Compiler (ist doch nur eine Einstellung) hilft dir, indem solche Bugs von vornherein nicht durch den Compiler gehen.

    Verwende, solange du das VLA noch drin hast, wenigstens eine dieser drei Kombinationen:
    -std=c++11 -pedantic -Wall -Wextra
    -std=c++14 -pedantic -Wall -Wextra
    -std=c++17 -pedantic -Wall -Wextra
    Und wenn du es los bist, füge jeweils -pedantic-errors hinzu. Falls du das mal vorübergehend weglassen musst, bleiben dir immerhin noch die Warnungen, dass das VLA (und was weiß der Henker noch) kein C++ ist.

    Der Code hat noch weitere Macken. Aber ich weiß nicht, was dich davon interessiert. Hast du denn schon das Speicherleck ("memory leak") gefunden?

    also wie gesagt bitte nicht böse sein, aber wenn ich nicht verstehe was mir vorgeschlagen wird, kann ich es auch nicht umsetzen.
    Wir können gerne konkret an deinem Code arbeiten, wozu übrigens Teil 1 u. 2 zur Vorbereitung gedacht sind. Die Reihenfolge ist also nicht zufällig gewählt. Mit den Einstellungen für Standardkonformität (per Compiler Switches) ginge dein Code natürlich nicht mehr durch den Compiler. Dann müsste an den entsprechenden Stellen nachgearbeitet werden (was erstrebenswert wäre, denn sonst profitierst du nicht von den anderen strengen Prüfungen). Mit der dynamischen Speicherverwaltung für die Zeiger auf die Objekte (was du erwähntest) wärest du das illegale VLA los. Ich würde trotzdem erst mal ergründen, wie es zu dem Speicherleck kommt.

    Auch zur Frage welche C++-version wir nutzen.. ich wusste nicht mal, dass es verschiedene gibt.
    Jetzt weißt du es, was gut ist.

    In der uni haben wir Linux-Rechner, die haben ja nem g++ compiler und ansonsten nehme ich jetzt Code::blocks, das hat den auch.
    CB lässt sich für viele verschiedene Compiler konfigurieren. Es gibt eine Variante mit Compiler und eine ohne. Die Einstellungen werden vererbt, und zwar in dieser Reihenfolge (von oben nach unten), zu finden hier:
    1. Für alle Projekte: Settings -> Compiler
    2. Für ein bestimmtes Projekt: Kontextmenü des Projektnamen, dann Build options-> Projektname
    3. Für die Build-Konfiguration (unter CB: "Build target"): Wie zuvor, dann Debug oder Release
      Bei Debug wird der Compiler angewiesen, Informationen für einen sog. Debugger zu speichern, mit dem sich das Programm zur Fehlerbehebung schrittweise ausführen und analysieren lässt. Ein damit erstelltes Kompilat ist langsam und aufgebläht und kann Informationen der Umgebung (Pfade etc.) beinhalten (Datenschutzproblem!), weswegen man es nicht (z. B. an Kunden) weitergibt.
      Bei Release wird schlankerer und performanterer Code erstellt. Über die vorkonfigurierten Switches können hier auch Optimierungen vorgesehen sein. Sie machen den Code schneller und vertragen sich nicht mit den für Debug üblichen Einstellungen.
      Die IDE bastelt die für die jeweiligen Konfigurationen benötigten Kommandozeilen mit den passenden Compiler Switches für dich zusammen.
      Wenn es bei den beiden vordefinierten Build-Konfigurationen bleibt, dann kompilierst du immer entweder unter Debug oder Release.

    CB bietet auf allen dieser drei Ebenen vordefinierte Compiler Switches an, was ziemlich bequem ist. Aber man kann auch eigene hinzufügen. Unter "2. Verwendete Tools -> Abhilfe" habe ich einige nützliche Switches angeführt. Ich würde sie für ein bestimmtes Projekt oder für alle Projekte nutzen. Welche Switches CB tatsächlich an den Compiler übergibt, zeigt dir das Build log.

    Welches Betriebssystem verwendest du denn (wegen der Tools und gewisser Unterschiede bei den Libs, die der Linker einbindet)?
    jabu ist offline

  10. #30 Zitieren
    Ehrengarde Avatar von Momo
    Registriert seit
    Feb 2011
    Beiträge
    2.142
    damit dass der dozent uns ins kalte wasser geworfen hat hast du recht, er hat uns zu allererst schlechten code vorgesetzt und dann mit uns versucht zu erarbeiten was man besser machen könnte. naja und danach hatte er eigentlich erwartet, dass wir dann selber nen weg finden das problem anzugehen, aber wir haben uns halt trotzdem weitestgehend an dem orientiert was wir nach dem erstmaligen verbessern hatten.. und dann haben wir das uns untereinander kopiert und hatten letztendlich alle fast den selben code. das hat der jetzt nicht unbedingt gewollt, aber er konnte ja auch nichts dagegen sagen, es hat ja dann jeder auf dieser basis weitergeschrieben. wir sollen NICHT das perfekte programm schreiben, er will uns nur ermutigen, ein wenig in der sprache herumzuexperimentieren und die funktionen wenn wir fremden code sehen zu verstehen. an vielen stellen gehen wir auch den kompromiss ein, dass der mensch vor dem computer sinnvoll mit dem programm umgeht und zum beispiel statt zahlen keine buchstaben eingibt undso. oder dass wir keine so große zahl eingeben, dass es irgendwann umschlägt auf die kleinste zahl im definierten typ. das würde alles viel zu weit gehen. ich habe das fach nur dieses semester und ich habe auch noch andere fächer in denen ich zum teil viel viel mehr zu tun habe für die belege, da ist das hier wirklich nicht so hoch angesetzt in meinen priotitäten. ich studiere ja auch nicht maschinenbau um danach C++ programmierer zu werden. wir haben das fach, damit wenn uns informatiker was erklären wir denen halbwegs folgen können, genauso wie wir elektrotechnik, elektronik, steuerungs- und regelungstechnik in grundzügen erstmal hatten, damit wir ein grundlegendes verständnis haben wenn die fachleute die das direkt studiert haben sich mit uns verständigen müssen. klar, ich lern das nicht nur für die uni, aber im moment und für ein semester lohnt sich der aufwand einfach nicht.
    ich schau mir natürlich an was du so geschrieben hast, aber ich bezweifle dass ich die zeit habe das noch sinnvoll zu realisieren.. das semester geht noch 4 wochen. wir müssen bis in 3 wochen einen bagger konstruiert haben, mitsamt bewegungssimulation, dann haben wir noch eine andere konstruktionsaufgabe in einem anderen fach die so umfangreich ist, dass wir das in 4ergruppen bearbeiten sollen, und in informatik sollen wir auch noch ein anderes programm schreiben. also 4 der acht fächer haben prüfungsbelege und die normalen prüfungen fangen auch in 4 wochen an. vielleicht lässt sicht so abschätzen, dass ich an der stelle wo der dozent am wenigsten verlangt (also hier) ein bisschen am aufwand spare.. nennt mich ruhig faul oder so, aber ich finde dass stress sehr ungesund ist und tue mein bestes, meinen einsatz dort wo es wichtiger ist zu bringen, und das ist nicht OOP.
    der ursprüngliche, aber !absichtlich fehlerbehaftete! code war der:
    Code:
    #include <iostream>
    
    using namespace std;
    
    // Aggregat
    class Shape
    {
      protected:
        int base;  //Attribut
        int height;
      public:
        int getArea();  // Methode
        Shape(int base, int height); // Constructor
        ~Shape();  // Destructor
    };
    
    // Derived class
    class Rectangle: public Shape {
       public:
          Rectangle(int base, int height);
          int getArea();
    };
    
    int Shape::getArea()
    {
        return 0;
    }
    
    Shape::Shape(int base, int height)
    {
      Shape::base = base;
      Shape::height = height;
    }
    
    Shape::~Shape()
    {
    
    }
    
    Rectangle::Rectangle(int base, int height)
    :Shape(base, height)
    {
    
    }
    
    Rectangle::getArea()
    {
        return (base * height);
    }
    
    int main()
    {
        Rectangle S1(8,3);
    
        cout << "Area: " << (S1.getArea()) << endl;
    
        return 0;
    }
    ich benutze jetzt nur noch meinen eigenen rechner auf dem windows ist und eben codeblocks. ich komme damit ganzgut klar, bei dem linux musste man alles immer außerhalb des codeprogramms durch den compiler geben, und konnte in dem kommandofenster ja nur mit tastatureingaben navigieren und das war mir einfach zu sinnlos zeitraubend und fehleranfällig da ich das ja nie machen muss sonst.
    "The most unusual day would occur when nothing unusual happened."
    Momo ist offline Geändert von Momo (08.06.2018 um 09:30 Uhr)

  11. #31 Zitieren
    Legende Avatar von jabu
    Registriert seit
    Jul 2011
    Beiträge
    7.322
    Was du jetzt gezeigt und gesagt hast, nährt meine Glaskugel schon deutlich besser. Allerdings fehlt noch, was der Dozent explizit gefordert hat! Denn Anforderungen, die nicht gestellt wurden, muss der Code nicht erfüllen.
    Doch, es ist gut, sich so dumm zu stellen, auch wenn man dem Kram schon ansieht, was gemeint sein könnte. Schätzen ist nicht Wissen. main() funktioniert doch, könnte man ketzerisch sagen. Der Dozent wird doch wohl etwas gezeigt haben, was nicht geht, was eine Anforderung implizieren sollte.

    Dass der erste (für deine momentanen Ansprüche viel zu komplizierte) Code von deinen Kommilitonen kopiert ist, konnte doch niemand wissen. Der gaukelt nämlich vor, dass du schon etwas tiefer in C++ drinsteckst oder dich dorthin vorarbeiten sollst, weswegen folgerichtig etwas mehr vorausgesetzt wurde.

    Demnach befrage ich meine jetzt hoffentlich besser funktionierende Glaskugel, was an dem Code stören könnte. Ich teile das mal in kleine Häppchen auf und fange zum Aufwärmen mit einer Sache an, die noch nichts mit OOP zu tun hat:

    Der Ganzzahlentyp int dürfte, wie du längst weißt, zu ungenau sein und zu leicht überlaufen. Ihr hattet float verwendet, was für dieses simple Beispiel in Ordnung ist. Aber nimm, wenn du schon die Wahl hast, mindestens double. Denn für die Genauigkeit gilt:
    double >= float
    float ist oftmals zu ungenau, was nichts mit Pedanterie zu tun hat. Ein Ingenieur muss sowieso um die Gefahren der Gleitkommazahlen wissen, weswegen folgende Quellen nicht schaden sollten:
    https://www.heise.de/ct/hotline/Java...ch-310780.html
    http://www.mpdvc.de/artikel/FloatingPoint.htm
    http://scienceblogs.de/von_bits_und_...echnen-teil-1/
    http://scienceblogs.de/von_bits_und_...echnen-teil-2/
    Also ist jeder Gleitkommazahlentyp eine potenziell tückische Fehlerquelle, was verheerende Konsequenzen für Mensch und Material haben kann (Amoklauf einer Maschine, Brückeneinsturz, Flugzeugabsturz etc.). Zwar versucht man, in sicherheitskritischen Bereichen ohne Gleitkommazahlen auszukommen, aber manche Berechnungen (Simulation, Navigation etc.) sind ohne sie regelmäßig nicht genügend performant hinzubekommen. Dann muss man um die Tücken wissen. Weil double auf den gängigen PC-CPUs nur selten eine schlechtere Performance als float mit sich bringt und weil diese Unterschiede, wenn sie denn auftreten, meistens vernachlässigbar sind, sollte man sich besser gleich double angewöhnen. Und wenn du float = 1.234 hinschreibst, dann ist 1.234 sowieso vom Typ double und wird implizit zu float gecastet. Wenn du -Wconversion zu deinen Switches hinzunimmst, dann solltest du wegen des Genauigkeitsverlustes eine Warnung bekommen. Wenn wirklich float gemeint ist, kannst du, um dieses auszudrücken, 1.234f schreiben. 1 ist übrigens vom Typ int, 1.f sowie 1.0f vom typ float (1f ist ein Fehler), und 1. sowie 1.0 vom Typ double. Wenn du double verwendest, verwende es, soweit nichts dagegen spricht, durchgängig.

    Zu Code::Blocks:
    Das kann man in deinem Fall auf Windows empfehlen, weil es gut MinGW und dessen Derivate unterstützt. MinGW heißt die Portierung des GNU-Compilers von Linux auf Windows. Deswegen sollte dein Umstellungsaufwand ziemlich gering sein (es gibt teils kleine Unterschiede bei den Switches für den Linker). Bei anderen Compilern wäre die Kommandozeile anders zusammenzusetzen, die Meldungen wären anders etc. Ich wüsste für Windows keine andere IDE (und ich kenne einige), bei der die Einstiegshürden so klein sind und womit man trotzdem sinnvoll arbeiten kann.
    jabu ist offline

  12. #32 Zitieren
    Ritter
    Registriert seit
    Feb 2003
    Beiträge
    1.554
    Zitat Zitat von jabu Beitrag anzeigen
    Was du jetzt gezeigt und gesagt hast, nährt meine Glaskugel schon deutlich besser. Allerdings fehlt noch, was der Dozent explizit gefordert hat! Denn Anforderungen, die nicht gestellt wurden, muss der Code nicht erfüllen.
    Alter...
    Es ging um Vererbung und um nichts weiter.
    Das Beispiel ist das klassische Beispiel von Robert C. Martin, was er immer hervorkramt, wenn es um Vererbung und Clean Code geht.

    Zitat Zitat von jabu Beitrag anzeigen
    Der Ganzzahlentyp int dürfte, wie du längst weißt, zu ungenau sein und zu leicht überlaufen.
    Ja, darüber könnte man reden. Da aber in diesem Beispiel nur multipliziert wird, ist die Genauigkeit hinfällig, da hier nur Ganzzahlen als Ergebnis ermittelt werden können.

    Zitat Zitat von jabu Beitrag anzeigen
    Ihr hattet float verwendet, was für dieses simple Beispiel in Ordnung ist. Aber nimm, wenn du schon die Wahl hast, mindestens double. Denn für die Genauigkeit gilt:
    double >= float
    Es kommt doch immer darauf an, wie hoch die Genauigkeit sein muss. Wenn keine allzu hohe Genauigkeit benötigt wird, kann weiterhin float verwendet werden. Einige Algorithmen in Grafikkarten arbeiten sogar extrem ungenau, weil es eben auf die Performance ankommt und nicht auf die Genauigkeit.

    Zitat Zitat von jabu Beitrag anzeigen
    Ein Ingenieur muss sowieso um die Gefahren der Gleitkommazahlen wissen, weswegen folgende Quellen nicht schaden sollten
    Nein, muss er nicht... Die Entwickler müssen es. Für ein Ingenieur ist es ein Nice-To-Know.
    Ich habe noch nie ein Ingenieur sagen hören: "Ich habe jetzt meinen Taschenrechner/meine Software ausgetauscht. Der/Die hat jetzt eine höhere Genauigkeit."

    Also ist jeder Gleitkommazahlentyp eine potenziell tückische Fehlerquelle, was verheerende Konsequenzen für Mensch und Material haben kann (Amoklauf einer Maschine, Brückeneinsturz, Flugzeugabsturz etc.). Zwar versucht man, in sicherheitskritischen Bereichen ohne Gleitkommazahlen auszukommen, aber manche Berechnungen (Simulation, Navigation etc.) sind ohne sie regelmäßig nicht genügend performant hinzubekommen.
    Es ist ein Maschinenbau-Studium und nicht ein Studium über Raketenwissenschaft, wo die 10 Regeln für sicherheitskritischen Code der NASA eingehalten werden müssen...

    Ich habe ursprünglich selber mal als Mechatroniker gearbeitet und habe selbst SPS-Anlagen programmiert. Glaube mir mal, so gut wie kein SPS-Programmierer ist in der Lage, den Unterschied zwischen float und double zu erkennen. SPS-Programmierer programmieren auch hauptsächlich mit Kontakt- und Funktionsplänen. Das erinnert alles an Scratch, was eine Programmiersprache für Kinder ist. Siemens hatte zum Anfang ihrer STEP 7 nur die Anweisungsliste zur Verfügung gestellt, was einer echten Programmierung näher kam und die STEP 7 wurde beinahe ein Flopp, weil kein SPS-Programmierer damit umgehen konnte, obwohl die Anweisungsliste auch in der alten STEP 5 zur Verfügung stand.

    Dass zur Praxis, wie die echte Welt einer industriellen Anlage aussieht...
    Zu Code::Blocks:
    Das kann man in deinem Fall auf Windows empfehlen, weil es gut MinGW und dessen Derivate unterstützt. MinGW heißt die Portierung des GNU-Compilers von Linux auf Windows. Deswegen sollte dein Umstellungsaufwand ziemlich gering sein (es gibt teils kleine Unterschiede bei den Switches für den Linker). Bei anderen Compilern wäre die Kommandozeile anders zusammenzusetzen, die Meldungen wären anders etc. Ich wüsste für Windows keine andere IDE (und ich kenne einige), bei der die Einstiegshürden so klein sind und womit man trotzdem sinnvoll arbeiten kann.
    Ich denke mal, dass interessiert ihn ein Scheißdreck, ob da nun MinGW oder ein anderer Kompiler läuft. Genauso gut hätten sie auch Visual C++ oder gleich C# nehmen können. Es geht nur um die Grundlagen der Objektorientierung. Keine Ahnung, warum du dich hier so groß tust.
    Whiz-zarD ist offline Geändert von Whiz-zarD (10.06.2018 um 10:46 Uhr)

  13. #33 Zitieren
    Ehrengarde Avatar von Momo
    Registriert seit
    Feb 2011
    Beiträge
    2.142
    ach komm, nimm es ihm doch bitte nicht übel! es tut mir eher leid, dass er sich für mich so reinhängt, obwohl das gar nicht nötig wäre(und auch nicht so viel bringt... ' ).. es gibt jetzt eine offizielle aufgabenstellung, die kann ich ja nochmal posten:
    OOP MB4

    Aufgabe 1

    Schreiben Sie ein Programm unter Ausnutzung der folgenden Eigenschaften objektorientierter
    Programmierung:
    Vererbung,
    Polymorphie,
    Kapselung,
    virtuelle Basisklassen

    dass eine vorgegebene Anzahl von verschiedenen Formen in einem Vektor speichert und wieder
    ausgeben kann. Die virtuelle Basisklasse aller Formen Shape stellt die Funktion zur Berechnung des
    Flächeninhaltes und des Umfanges zur Verfügung. Außerdem steuert Shape, dass der Flächeninhalt und
    der Umfang nur einmal berechnet und dann vorgehalten werden. Folgende Formen sollen als
    spezialisierte Kindklassen implementiert werden: Kreis, Rechteck, Dreieck. Das Programm soll in C++
    geschrieben werden.
    Sie erhalten einen Upload-Link, um Ihr Programm zur Bewertung zu stellen. Außerdem wird es einen
    kurzen schriftlichen Test zu den grundlegenden Begriffen geben und Sie erhalten die Möglichkeit,
    Fragen zu Ihrem Sourcecode zu beantworten.
    "The most unusual day would occur when nothing unusual happened."
    Momo ist offline

  14. #34 Zitieren
    Legende Avatar von jabu
    Registriert seit
    Jul 2011
    Beiträge
    7.322
    Zitat Zitat von Whiz-zarD Beitrag anzeigen
    Alter...
    ^Das muss doch nicht sein.

    Edit: Die näheren Ausführungen habe ich wegen des Nebenthemas in einen Spoiler gepackt:
    Spoiler:(zum lesen bitte Text markieren)

    Es ging um Vererbung und um nichts weiter.
    Und die soll keine Implikationen (z. B. für sinnvolle Typen) haben?

    Zitat Zitat von Whiz-zarD Beitrag anzeigen
    Zitat Zitat von jabu Beitrag anzeigen
    Der Ganzzahlentyp int dürfte, wie du längst weißt, zu ungenau sein und zu leicht überlaufen.
    Ja, darüber könnte man reden. Da aber in diesem Beispiel nur multipliziert wird, ist die Genauigkeit hinfällig, da hier nur Ganzzahlen als Ergebnis ermittelt werden können.
    int ist jetzt schon unglücklich, weil er entweder nur mit sehr groben Klötzchen arbeiten könnte oder (mit einem Multiplikator, z. B. 1000) schon bei kleinen Seitenlängen (wegen 10002) im (für int undefinierten) Überlauf landen würde. Das bewog mich nur sekundär, aber immerhin.

    Die Typen lassen sich nicht, wenn es mal nötig wird, mixen (für Rechteck anders als für Kreis etc.). Es gibt unter C++ nämlich keine Auflösung für Overloads zur Laufzeit. Double Dispatch, falls du jetzt daran denken solltest, muss anders gelöst werden. Und doch, ich weiß, dass Double Dispatch nach einem Designfehler riecht (aber nicht bedeutet, dass es tatsächlich einer ist).

    Und Rückgabewerte lassen sich gar nicht variieren:
    Weil der Code des Dozenten int Shape::getArea() verwendet, ist die Methode auf int festgenagelt. Wenn sich dort etwas beißt, geht das (mit gutem Grund) nicht durch den Compiler. Ein Cast ist insofern sinnlos, dass es besser ist, durchgängig mit dem Gleitkommatyp zu arbeiten.

    Ich habe mir also schon etwas dabei gedacht (hier steht nicht alles), wenn ich dazu rate, die Typen mitzubedenken. Es ist doch ein Klacks, das eben zu tun, jedenfalls ein kleinerer, als das nachher an vielen Stellen tun zu müssen. Und es ist im Sinne der OOP, frühzeitig darüber nachzudenken, was Shape natürlicherweise auszeichnet, wozu eben auch sinnvolle Zahlenmengen gehören.

    Das Beispiel ist das klassische Beispiel von Robert C. Martin, was er immer hervorkramt, wenn es um Vererbung und Clean Code geht.
    Ich hatte das beim letzten Mal zurückgestellt, also nun doch:
    Ich habe nicht alle seine Bücher gelesen, aber eines seiner vermutlich wichtigsten, nämlich "Clean Code". Darin wird Shape in einem speziellen Kontext benutzt (von dem hier nicht die Rede ist), nämlich um prozedurale Programmierung mit Polymorphie gegen objektorientierte Programmierung mit Polymorphie abzuwägen, was in einer Gegenüberstellung der Vor- und Nachteile mündet. Eine inhaltliche Verbindung zur Sache des TEs ist nur insofern erkennbar, dass Shape verwendet wird, was jeder kann. So findest du es auch bei Bjarne Stroustrup, dem Erfinder von C++, wobei der Kontext anders ist. Daher ist vieles legitim. Shape schert sich nicht darum, was klassisch ist und wer es zuerst gebracht hat. Empirie und "Religion" trennen sich hier.

    Es kommt doch immer darauf an, wie hoch die Genauigkeit sein muss. Wenn keine allzu hohe Genauigkeit benötigt wird, kann weiterhin float verwendet werden.
    Klar, dagegen habe ich doch nichts. Solange keiner was über System und Anforderungen sagt, darf ich abwägen, was ich schlussendlich getan habe. Wenn ich dazu komme, dass ich heutzutage double eher empfehlen kann, dann muss ich das begründen können, was ich (u. a. mit den Links) getan habe. Irgendwas muss er doch nehmen.

    Wenn ich eher float empfehle, ist es falsch, weil... Und wenn ich eher double empfehle, ist es falsch, weil...
    Und so kannst du immer etwas finden, um der Rechthaberei Willen:
    Einige Algorithmen in Grafikkarten arbeiten sogar extrem ungenau, weil es eben auf die Performance ankommt und nicht auf die Genauigkeit.
    Richtig, aber was meinst du, was ich mir von dir hätte anhören lassen müssen, wenn ich wegen Performance float vorgeschlagen hätte. Dann hättest du doch den Spieß umgedreht.

    Ich habe genügend Timing-Code gesehen, der völlig im Arsch war, sogar bis zur Unspielbarkeit eines Games (Arx Fatalis: Geruckel, Held stirbt immer wieder plötzlich etc.). Natürlich hätte man das korrekter und komplexer lösen können, aber schon ein dummes double hätte dazu geführt, dass die allermeisten Leute ihren Spaß gehabt hätten und dass das Game längst nicht so krasse Abwertungen bekommen hätte. float war aus damaligen guten Gründen allgegenwärtig und wurde dann leider nicht mehr hinterfragt.

    Ich habe aus meiner Warte sorgfältig abgewogen (unter Einbeziehung des Störeffektes, dass man etwas daraus lernen könnte (nicht muss)), weiter nichts. Dass mir das nun derart unter die Füße gerieben wird, hatte ich doch nicht erwartet.

    Nein, muss er nicht... Die Entwickler müssen es. Für ein Ingenieur ist es ein Nice-To-Know.
    Ich habe noch nie ein Ingenieur sagen hören: "Ich habe jetzt meinen Taschenrechner/meine Software ausgetauscht. Der/Die hat jetzt eine höhere Genauigkeit."
    Könnte es sein, dass du Ings unterschätzt und ihre Taschenrechner vielleicht auch?

    Ich habe hier einen typischen Ing-Taschenrechner liegen, nämlich einen uralten TI-92 (Batterien leer, weswegen ich jetzt nicht experimentieren kann und hierauf verweise (zur Antwort mit dem grünen Haken scrollen)). float stinkt dagegen gewaltig ab (und double müsste immer noch unterlegen sein, wenn das alles stimmt, was er schrieb, aber da würde ich erst selber nachgucken wollen, bevor ich das behaupte).

    Es ist ein Maschinenbau-Studium und nicht ein Studium über Raketenwissenschaft, [...]
    Das bestreite ich doch gar nicht, und die Historie ist auch interessant. Vielleicht kennst du aber auch die andere Seite bei unseren Mittelständlern, wo die Ings die Finger überall drin haben, weil geiz geil ist oder weil das Geld wirklich knapp ist oder weil es sich nicht lohnt, extra einen Informatiker einzustellen. Und manchmal soll es sogar Sinn machen, einen Ing damit zu beschäftigen.

    Ich denke mal, dass interessiert ihn ein Scheißdreck, ob da nun MinGW oder ein anderer Kompiler läuft. Genauso gut hätten sie auch Visual C++ oder gleich C# nehmen können. Es geht nur um die Grundlagen der Objektorientierung. Keine Ahnung, warum du dich hier so groß tust.
    Er hat aber nun mal C++ nehmen müssen (was drastische Implikationen für seinen Lernerfolg hat, die es bei Java oder C# so nicht gibt):
    Wenn er MinGW nimmt, dann geht dort (wenn man nichts weiter unternimmt) derselbe defekte Code durch wie der von seinen Kommilitonen (oder wo jetzt der Return Value bei seinem Dozenten fehlt). Also haben alle dieselbe Ausgangsbasis und können darüber kommunizieren. Dieses zu wissen und diese Option überhaupt zu haben, ist vorteilhaft. Andererseits wäre er mit einem standardkonformen Compiler (echtes C++) auf die Fresse geflogen, was bei seinen ersten Gehversuchen nicht gut gewesen wäre, aber was dann später viel besser gewesen wäre, weil ihn der Compiler über seine smarten Messages viel besser hingewiesen hätte. Das Coden ist dann eben mit den entsprechenden Switches sehr viel leichter für ihn. Man gibt Mist ein und bekommt eine aussagekräftige Ansage. Und die sind jetzt bei MinGW von der Ausdrucksweise her dieselben wie in der Hochschule, was gut ist, weil eine Umstellung schwerfällt. Also verwendet er am besten zu Hause mindestens die Switches, die ich ihm genannt habe (um für sich bestmöglichen Support zu erhalten (Messages sind fast ein Handbuch!)), und in der Hochschule an der Kommandozeile muss er es nicht so eng nehmen. Ich schreibe das nicht, weil ich mich groß tun wollte, sondern weil ich Erfahrungen mit diversen Toolchains und ihren Tücken und Vorzügen habe und ihm die Knieschussgefahr zu minimieren und die Erfolgschancen zu maximieren helfen wollte. Aber gut, dass es ihn vielleicht nicht interessiert, könnte stimmen. Ich wäre froh gewesen, wenn mir damals jemand diese Dinge gesagt hätte. Was ihr beide vermutlich immer noch nicht versteht: Mit den Tipps ist der Aufwand kleiner, nicht größer. Weil weniger Konfusion herrscht, verläuft die Lernkurve dann flüssiger und steiler. Das muss man mir nicht glauben. Was strenge ich mich eigentlich so an.


    Edit vom 12.06.2018:

    Noch speziell zu Code::Blocks, weil ich mich in dem von dir zitierten Abschnitt mehr auf die IDE als auf den Compiler bezog:
    Es ist wegen der (seiner) ganz normalen Überforderung von Anfängern, anders als du meintest, nicht egal, welche IDE er verwendet, denn unter C++ ist es im Rahmen des Üblichen, dass man
    • IDE und Compiler separat installieren muss
    • man die Pfade zu den Tools (Compiler, Linker etc.) selber festlegen muss
    • man, je nach Compiler, die Suchpfade (Header, Libs etc.) selber festlegen muss
    • man die Compiler Switches selber setzen muss
    • man die Linker Switches selber setzen muss
    • man dazu^ auch die Libs angeben (und erst mal wissen) muss

    Um das zu ersparen, wird Code::Blocks in einem speziellen Paket Anfängern für einen leichten Start unter die Nase gerieben. Dieses enthält ein sehr speziell angepasstes MinGW, nämlich tdm-gcc, wobei die IDE dafür eine Vorkonfiguration hat. Unter anderem sind hierbei die Defaults der Switches angepasst, sodass implizit statisch gelinkt wird, damit sich ein Anfänger nachher nicht wundert, dass er das Programm nicht ausführen kann, weil ihm DLLs fehlen.
    Ohne die Leistung des Erschaffers von tdm-gcc, einer aufopferungsvollen Einzelperson, hätte er das alles nicht. Und die vordefinierten Checkboxes für die wichtigsten Compiler Switches von Code::Blocks sind auch ziemlich einmalig (abgesehen von Visual Studio).
    Als ich vor ein paar Jahren zuletzt CodeLite (die IDE gefiel mir) einrichtete, musste ich leider irgendwann nach vielen verplemperten Stunden feststellen, dass die Pfadkomposition unter Windows defekt ist und dass die Vererbung der Projekteinstellungen sehr unübersichtlich und leider zu speziell gelöst ist. Als ich noch letztes oder vorletztes Jahr KDevelop verwendete, musste ich eine ziemliche Untauglichkeit wegen ähnlicher Gründe feststellen. Code::Blocks ist zwar in der Projektkonfiguration teils unübersichtlich, aber im Gegensatz zu fast allen anderen frei verfügbaren IDEs stimmt wenigstens die Logik dahinter einigermaßen, sodass man beim Einrichten nicht in eine Sackgasse gerät. Die meisten IDEs sind entweder nicht offen konfigurierbar (führen unter Windows, wo man zum Einbinden eines GNU-Compilers bedeutend mehr Flexibilität als unter Linux braucht, in Sackgassen und sind ziemlich oft fehlerhaft), oder sie sind so offen, dass man sich seine eigenen Build-Skripte schreiben muss, was einen Anfänger überfordert.
    Eclipse ist nicht schlecht, aber einem Anfänger sind das Plugin-System, die Workspaces, die Kommandozeilenkomposition, das auf studentischer Hardware anzunehmende lange Starten, häufige Laggen und langsame Erstellen wegen des enormen Ressourcenbedarfs (Java...), nicht unbedingt zuzumuten, es sei denn, er hat viel Zeit und tolles Gerät. Code::Blocks hingegen macht einmal "Schwupps" und fertig, was auch Visual Studio nicht leisten kann. Man kann schnell etwas anderen zeigen und schnell nach Fehlern weiterarbeiten.
    Damit sind wir bei Visual Studio, was eine gute IDE ist (mit Einschränkungen bei der Wahl der Tools). Sie müsste doch auch für Anfänger bestens geeignet sein, denkt der Profi, der die stundenlange Download- und Installationsorgie auf das nötigste Minimum abzuschmelzen weiß, ohne dass nachher die benötigten SDKs fehlen. Und er weiß auch, wie er das ressourcenlastige Überanalysieren so weit abgeschmolzen bekommt, dass die IDE auf studentischer Hardware benutzbar wird. Er weiß auch, wie er die vorkompilierten Header deaktiviert (die bei kleinen sowie klug organisierten Projekten Zeit kosten!), und was das überhaupt ist. Er weiß, wie man die ständigen Aktualisierungsorgien zeitsparend managt etc. Vermutlich hat er auch schnelle Hardware, auf der der Start nicht bei einem 5400-RPM-HDD eine knappe Minute zzgl. weiteren Initialisierungsorgien dauert, bevor er auf das Laden des Projektes warten darf. Und falls nicht, stört ihn das auch nicht, weil er sein Projekt immer offen hat. Und die Flut an Steuerelementen, die einen Anfänger irritieren, schreckt ihn nicht ab.
    Visual Studio wäre jetzt trotzdem immerhin meine zweite Wahl gewesen, weil Intellisense, obwohl es manchmal hängt, einen gut an die Hand nimmt und dabei, wenn es gerade nicht hängt, mit der Kompilierung übereinstimmt, was bei den Codeanalysen der anderen IDEs leider nicht durchgängig funktioniert. Beispielsweise werden bei Code::Blocks die C++-Header nur unter Umständen erfolgreich geparst, also eher nicht, sodass die Codevervollständigung dann nur beim eigenen Code funktioniert, wo sie verzichtbar wäre. Weil der TE nur wenig aus den C++-Headern explizit verwenden muss, ist das nicht so schlimm (ansonsten nervt es, denn so eine Gedächtnisstütze kann man schon gebrauchen). Aber VS ist schon wegen der Unterschiede zur GNU-Toolchain nicht die erste Wahl für ihn.
    Es sollte also (unter Würdigung alle Umstände) besser sein, wenn der TE nicht mit anderen IDEs herumexperimentiert (während man es Leuten, die tiefer einsteigen wollen, sogar empfehlen kann), weil ihn das ansonsten sehr viel Zeit und Nerven kosten würde.

    Puh, das ist jetzt viel gewesen. Aber wenn einer sagt, dass ich Unsinn schreibe, dann belege ich gerne meinen Unsinn. Ich sauge mir das doch nicht aus den Fingern, sondern es stehen entsprechende Erfahrungen mit den IDEs dahinter.

    Zitat Zitat von Momo Beitrag anzeigen
    ach komm, nimm es ihm doch bitte nicht übel! es tut mir eher leid, dass er sich für mich so reinhängt, obwohl das gar nicht nötig wäre(und auch nicht so viel bringt... ' ).. es gibt jetzt eine offizielle aufgabenstellung, die kann ich ja nochmal posten:
    Da ist sie ja endlich!
    Na ja, jetzt bin ich erst mal ziemlich fertig, und heute muss ich arbeiten. Mal sehen, was noch geht. Ansonsten hast du ja noch Whiz-zarD (der anscheinend in OOP fit ist).
    jabu ist offline Geändert von jabu (12.06.2018 um 17:00 Uhr) Grund: Erklärung, warum die Wahl der IDE bei einem Anfänger nicht egal ist, hinzugefügt

  15. #35 Zitieren
    Auserwählter
    Registriert seit
    Jul 2017
    Beiträge
    6.514
    @Momo
    Das ganze ist ein recht einfaches Problem, welches ja im Prinzip nur zeigen soll, dass Du grundsätzliches von C++ verstanden hast oder überhaupt über objektorientiertes Programmieren.

    Ich weiß nicht, was Du vor hast. Willst Du nur die Arbeit erledigt haben und dann ist auch gut mit der Programmierung, kann man sich hier viel sparen.

    Hast Du vor, ein wenig mehr zu machen, dann hätte ich ein paar Tipps.

    jabu geht sehr weit. Ich denke zu weit für den Anfang. Man will ja nicht gleich in tausend Sachen einlesen, wenn man das ganze nur für den Hausgebrauch nutzen will.

    Das Schlimmste von allen ist die Fehlersuche.
    Macht ein Programm nicht das, was man meint, was es machen soll, geht die Suche los. Dieses wird IMMER passieren. Es kann auch durch gründlichstes Arbeiten nicht vermieden werden. Das Problem wird natürlich bei großen Programmen größer.

    Man kann aber die Suche erleichtern. Und zwar, wenn man ein paar einfache Dinge befolgt. Vor allem in unserem Bereich, also mehr oder weniger Hausgebrauch und kleinere Programme.

    Lass eine Methode nur das machen, was sie machen soll. Gerade zu beginn neigt man dazu, irgendwie alles reinzuschmeißen. Man kann auch mit Objektorientierten Sprachen herrlichen Spaghetticode schreiben, den man selbst nach einer Woche nicht mehr versteht.

    Getter und Setterfunktionen sind Pflicht. Es nervt zwar manchmal etwas und es gibt viele Methoden in der Klasse und man könnte viel schneller direkt auf Objektvariablen zugreifen. Aber, wieder die Fehlersuche, man hat die Kontrolle. Gerade bei den Setterfunktionen kann man z.B. bestens überprüfen, ob der Wert passt.

    Also: je gezielter die Aufgabe, desto besser.

    Speicherfehler, Überläufe, falsche Zahlenwerte zeigen, dass man ständig die Werte der Variablen im Auge haben muss. Ich mache das immer so, dass ich eine Methode habe, die nur überprüft, ob die Werte in Ordnung sind. Ich weiß nicht, ob es in C++ Enums gibt, in Java nehme ich hierzu Enums, die dann auch direkt aufzeigen, was für ein Fehler vorliegt. Da kann man dann nötigenfalls schnell eine Fehlerausgabemethode schreiben, die direkt zeigt, wo der Fehler liegt und was den Fehler verursacht (jedenfalls so gut es halt geht). Es ist ein wenig mehr Aufwand, das Programm zu schreiben. Das stimmt. Aber die Suche nach den unvermeidbaren Fehlern wird diese Zeit vielfach zurück holen. Aber dabei nicht vergessen: Auch die Fehlerfindehilfen sind programmiert, am Ende kann auch da der Fehler liegen.

    Passende Namen sind oftmals besser, als lange Kommentare. Zur Lesbarkeit insgesamt kann man dein Beispiel zu beginn nehmen und das, was später draus geworden ist. Da hat sich schon einiges getan.

    Also: Lesbarkeit und Verfolgbarkeit sind mein Crede. Nicht nur für Dritte, sondern auch für sich selbst. Wie gesagt, der nächste Fehler kommt bestimmt und bei der Suche danach kann viel Zeit verloren gehen. Zeit, die man sich hätte sparen können, wenn man schon vorher Hilfen eingebaut hat, die Fehlerquellen aufzeigen.
    Stiller Leser ist offline

  16. #36 Zitieren
    Legende Avatar von jabu
    Registriert seit
    Jul 2011
    Beiträge
    7.322
    @Stiller Leser: Schöne Tipps (und ja, es gibt auch in C++ überaus nützliche enums)!

    Zitat Zitat von Stiller Leser Beitrag anzeigen
    jabu geht sehr weit. Ich denke zu weit für den Anfang. Man will ja nicht gleich in tausend Sachen einlesen, wenn man das ganze nur für den Hausgebrauch nutzen will.
    Das kann täuschen, wenn man es nur überfliegt. Es sind im Wesentlichen fünf Punkte (zzgl. der Andeutung, das verbotene VLA und das Memory Leak zu entfernen).

    Manchmal muss ich detaillierter schreiben, als mir lieb ist, weil mir das sonst als "unbegründet" angekreidet würde (wenn jemand meine Fehler fixen würde, wäre das hingegen hilfreich), denn irgendein Desinteressierter, der etwas auszusetzen hat, findet sich in einem Forum immer wieder. Die erste Stufe ist: "Du schreibst Unsinn!", die zweite "Das kannst du nicht begründen!" und die dritte - nachdem du alles haarklein begründet hast: "Was soll diese Wall of Text?" Es ist also immer falsch. Also suche ich mir eines heraus.

    Es sind nur ganz wenige Punkte (die lediglich detailliert dargelegt sind, damit er die Gründe verstehen kann, und natürlich muss er sich die Details nicht alle merken, aber er braucht erst mal einen Anlaufpunkt zum Nachschlagen, damit er auch weiß, wie die Dinge einzuordnen sind.). Vier sind bloß Vorbereitungshandlungen, wobei er nur für drei davon etwas tun muss.

    Ich habe meine fünf Punkte mal zusammengefasst:
    1. Vergewissere dich der C++-Sprachversion, nimm C++11 (evtl. C++14), wegen der Kompatibilität und des Verhaltens bei Fehlern.
    2. Verwende die Compilerswitches welche das^ sicherstellen. Denn standardmäßig ist ein fehlertoleranter GNU-Dialekt anstatt C++ aktiv, was dazu führen würde, dass man auf Fehlerhaftem aufbaut und sich darin verstrickt (z. B. anstatt gleich std::vector zu nehmen, s. u.), und sinnvolle Meldungen des Compilers blieben aus.
    3. Verwende die Compilerswitches für die wichtigsten Warnungen (besser wären fast alle). Damit kann man sich besser auf das eigentliche Problem (die OOP) konzentrieren, weil einen die Warnungen immer wieder auf den rechten Weg stupsen.
      Der Clou: Man kann oftmals eine Analysefunktion freischalten, welche die Best Practices aus Effective C++ von Scott Meyers verwenden. Damit bekommt man seine Klassen leichter korrekt implementiert!
    4. Unterschiedliche Compiler geben unterschiedliche Warnungen aus. Bleibe daher bei einem.
    5. Ich habe für die Berechnungen double (er könnte auch float nehmen) anstatt int vorgeschlagen, weil mit Pi, Wurzeln etc. zu rechnen war. Die Genauigkeit war ein nötiges Unterthema, weil ich ohne Begründung Haue bekomme (mit anscheinend auch).

    Zitat Zitat von Stiller Leser Beitrag anzeigen
    Das Schlimmste von allen ist die Fehlersuche.
    Macht ein Programm nicht das, was man meint, was es machen soll, geht die Suche los. Dieses wird IMMER passieren. Es kann auch durch gründlichstes Arbeiten nicht vermieden werden. Das Problem wird natürlich bei großen Programmen größer.
    So ist es. Damit er nicht irgendwann wegen sprach- und compilerspezifischer Besonderheiten die Welt nicht mehr versteht, habe ich ihm vier dieser fünf Punkte gesagt. Es ist schlicht ein Erfahrungswert, der ihn vor Schaden bewahren soll, damit er sich voll auf das eigentliche Problem konzentrieren kann.

    Nachdem der TE endlich die Aufgabenstellung gezeigt hat, erscheint mir daraus dieser Abschnitt gewissermaßen verdächtig:
    Zitat Zitat von Momo Beitrag anzeigen
    [...] Die virtuelle Basisklasse aller Formen Shape stellt die Funktion zur Berechnung des
    Flächeninhaltes und des Umfanges zur Verfügung. Außerdem steuert Shape, dass der Flächeninhalt und
    der Umfang nur einmal berechnet und dann vorgehalten werden. [...]
    Dieses "Steuern" ist missverständlich, indem es nach einer expliziten aktiven Maßnahme klingt. Ich vermute, dass die Kommilitonen deswegen auf diese umständliche Lösung mit der Berechnung bei Erstverwendung (anstatt bei Initialisierung) gekommen sind, natürlich unter der Voraussetzung, dass zumindest einer die Aufgabenstellung bereits kannte. Hätte der TE sie gleich mitgeteilt, so hätten wir uns und ihm das lange Rätselraten ersparen können. Das "nur einmal" scheint mir hilfreich zu sein. Weil dort nicht steht, wann das erfolgen soll, dürfte es erlaubt sein, gleich vollständig zu initialisieren, was üblich und ratsam ist (keine undefinierten Zustände, denn die wären eine potenzielle Fehlerquelle).

    Hiermit wird bestätigt, dass ich doch richtig geschätzt hatte, dass es nicht nur um die nackte OOP gehen soll:
    Zitat Zitat von Momo Beitrag anzeigen
    [...] Schreiben Sie ein Programm unter Ausnutzung der folgenden Eigenschaften objektorientierter
    Programmierung [...]
    Er soll es also nutzbar machen, was mit nackter OOP nicht geht.

    Und ich hatte mit noch einer Sache Recht:
    Zitat Zitat von Momo Beitrag anzeigen
    [...] dass eine vorgegebene Anzahl von verschiedenen Formen in einem Vektor speichert und wieder
    ausgeben kann. [...]
    Das VLA, was kein C++ ist, muss also weg. Man soll einen für C++ typischen Weg gehen, indem man einen Vektor (ein dynamisches Array) nimmt. Dieses wollte ich ihm vorschlagen, aber man grätschte dazwischen, er sollte nur OOP machen.

    Einen Vektor zum Speichern zu nehmen, ist nämlich eine sehr sichere Methode für Anfänger (und sonst auch). Man wird die hässlichen Zeiger (manchmal sind sie nützlich) sowie die fehlerträchtige Heap-Allokation (wegen new) los. Der Vektor kapselt die Allokation und gibt bei Verlassen des Scopes über seinen Destruktor den Speicher wieder frei, sodass man nichts mehr damit zu tun hat.

    Und siehe da, er muss das VLA und das Memory Leak entfernen (hatte das nicht aus Langeweile schon mal angedeutet)!

    Diese Form der Kritik an mir (er solle nur OOP lernen, weswegen ich solche Hinweise unterlassen sollte) führt sich selbst ad absurdum, weil die Lektion (deren Anteilnahme ich beim TE befördern wollte) ist, dass man besser potenziell unsichere Allokationen unter Ausnutzung von RAII kapseln lässt, was einen Vorteil von OOP demonstriert. Den Artikel zu RAII (der wie in der Aufgabenstellung gefordert, std::vector verwendet) kann ich dem TE wärmstens empfehlen.

    Ich bin sicher kein OOP-Guru, aber ich lag mit allen meinen Vermutungen richtig (nur eine Feststellung zu meiner Verteidigung, weil ich so überheblich angegangen wurde). Es ging bei mir im Wesentlichen um Tipps für nachhaltig leichtes und sicheres Programmieren (die man bei Java und C# nicht braucht (vllt. einige doch)) und nicht um Ballast.
    jabu ist offline Geändert von jabu (12.06.2018 um 18:48 Uhr)

Seite 2 von 2 « Erste 12

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •