von Java nach C++



  • Soller schrieb:

    Wo man mit Java mit try-catch-finaly herumfrickeln darf, weil der tolle GC zwar den Speicher aufräumt den Speicher aufräumt, sonst aber nichts.
    Lässt man unter C++ einfach die Destruktoren für sich arbeiten ( Stichwort RAII)

    PrintWriter file;
    try {
      file = new PrintWriter("Hallo.txt");
      file.println("Hallo Welt!");
    } catch(Exception e) {
    } finally {
      file.close();
    }
    

    Viel kürzer gehts in C++

    std::ofstream file("Hallo.txt");
     file << "Hallo Welt!\n";
    

    Ab Java 7 gibt es ein "try with resources", in dem einen das Schließen der Resourcen auch abgenommen wird.

    Dein Beispiel sollte da dann ungefähr so aussehen:

    try (PrintWriter file = new PrintWriter("Hallo.txt")){
       file.println("Hallo Welt!");
    }
    


  • cooky451 schrieb:

    @Soller Das wird doch erst richtig lustig wenn man 3 Dateien auf einmal öffnet. 😉
    https://ideone.com/qF5lnZ

    Ja, ne ist klar.

    public class JavaApplication1 {
    
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            try(PrintWriter file1 = new PrintWriter("file1.txt");
                PrintWriter file2 = new PrintWriter("file2.txt");
                PrintWriter file3 = new PrintWriter("file3.txt")    ) {
            } catch (Exception ex) {            
            }
        }
    }
    


  • Und man braucht dann kein close() mehr?



  • cooky451 schrieb:

    Und man braucht dann kein close() mehr?

    Yup, und wie Gregor schon verlinkt hat:

    http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html schrieb:

    The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.



  • Ab Java 7 gibt es ein "try with resources", in dem einen das Schließen der Resourcen auch abgenommen wird

    Richtig!
    Aber Java kann es erst seit Version 7, währen RAII jeder popelige C++ Compiler der letzten 30 Jahre beherrscht.



  • Wenn so ein C++ vs. Java Flamewar auftaucht, schaue ich manchmal im Language Shootout, wie es inzwischen bei der dortigen willkürlichen Wahl von Microbenchmarks aussieht:

    http://benchmarksgame.alioth.debian.org/u64q/benchmark.php?test=all&lang=gpp&lang2=java&data=u64q

    Um es kurz zusammenzufassen:

    1. Bei den benötigten Codezeilen scheinen sich die beiden Sprachen nicht besonders stark zu unterscheiden.

    2. C++ Programme sind typischerweise etwas schneller als Javaprogramme, in der Testmenge an Programmen auf der Seite geht das von einem Faktor 1.0 bis zu einem Faktor 2,4.

    3. Javaprogramme benötigen deutlich mehr Speicher. Das ist vielleicht der größte Nachteil von Java.



  • Zeus schrieb:

    cooky451 schrieb:

    @Soller Das wird doch erst richtig lustig wenn man 3 Dateien auf einmal öffnet. 😉
    https://ideone.com/qF5lnZ

    Ja, ne ist klar.

    public class JavaApplication1 {
    
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            try(PrintWriter file1 = new PrintWriter("file1.txt");
                PrintWriter file2 = new PrintWriter("file2.txt");
                PrintWriter file3 = new PrintWriter("file3.txt")    ) {
            } catch (Exception ex) {            
            }
        }
    }
    

    Hallo, warum verwendest du das "@" in "@param"?
    Diesen Comment-Style habe ich schon öfters gesehen. Wie heißt das genau?



  • -Nachfrage- schrieb:

    Hallo, warum verwendest du das "@" in "@param"?
    Diesen Comment-Style habe ich schon öfters gesehen. Wie heißt das genau?

    Das sind Javadoc-Kommentare. Javadoc ist ein Werkzeug, das Dir aus solchen Kommentaren eine hübsche html-Doku baut. ...ähnlich wie zum Beispiel Doxygen.



  • Gregor schrieb:

    -Nachfrage- schrieb:

    Hallo, warum verwendest du das "@" in "@param"?
    Diesen Comment-Style habe ich schon öfters gesehen. Wie heißt das genau?

    Das sind Javadoc-Kommentare. Javadoc ist ein Werkzeug, das Dir aus solchen Kommentaren eine hübsche html-Doku baut. ...ähnlich wie zum Beispiel Doxygen.

    Ok, meinst du, es ist sinnvoll, schon von anfang an so seinen Quelltext zu kommentieren, damit man später mit Doxygen eine Doku bauen kann?



  • -Nachfrage- schrieb:

    Ok, meinst du, es ist sinnvoll, schon von anfang an so seinen Quelltext zu kommentieren, damit man später mit Doxygen eine Doku bauen kann?

    Dokumentieren von Anfang an ist immer sinnvoll. Tools zur Erstellung einer HTML-Dokumentation wie Doxygen oder JavaDoc bauen zusätzlich noch Konstrukte, welche schnellere Übersichten für Strukturen und Objekte liefern. Solche "Helferlein" schaffen eher bei größeren oder komplexen Projekten einen Mehrwert.



  • Ja, aber ich muss ja dann in den Kommentaren diese Tokens von Doxygen verwenden.

    Ich meinte: Ist es sinnvoll, seinen Quelltext SO (mit Doxygen-Tokens) zu kommentieren?



  • -Nachfrage- schrieb:

    Ok, meinst du, es ist sinnvoll, schon von anfang an so seinen Quelltext zu kommentieren, damit man später mit Doxygen eine Doku bauen kann?

    Das, was hier im Beispiel gezeigt wurde, ist vermutlich automatisch von irgendeiner IDE generiert worden. Ich halte es generell für eine gute Idee, seinen eigenen Quellcode vernünftig zu dokumentieren. ...und zwar relativ früh, weil man es später immer unwahrscheinlicher macht. Tags für Dokumentationswerkzeuge zu nutzen kann auch sehr sinnvoll sein, vor allem, wenn Du viele Klassen und so weiter hast und die Zusammenhänge irgendwann vielleicht nicht mehr kennst.

    Ich persönlich dokumentiere sehr unterschiedlich stark. Größtenteils mit Kommentaren im Rahmen von solcher Dokumentationstools, aber teilweise auch innerhalb der Methoden direkt im Quelltext. ...eine recht ausführlich dokumentierte Quellcode-Datei von mir wäre zum Beispiel folgende ( ⚠ schreckliches, schlechtes Englisch ⚠ ):

    /*
     * LineCaster.java
     *
     * Created on 8. März 2005, 01:25
     */
    
    package jaradap.model.algorithm;
    
    import jaradap.model.algorithm.multiPointProcessor.RaycastProcessor;
    import jaradap.model.data.BasicRaster;
    import jaradap.model.data.SingleChannelStandardRaster;
    import math.linearAlgebra.Vector;
    
    /**
     * This class represents Objects which can analyze lines in a given raster. The analysis
     * projects a line into a single value which is given by a RaycastProcessor, the raster and the line. 
     *
     * @author Gregor
     */
    public class LineCaster
    {
       private final RaycastProcessor pointProcessor;
       private final SingleChannelStandardRaster raster;
       private final int dimension;
    
       /** 
        * Creates a new LineCaster with the given parameters.
        *
        * @param pointProcessor This is the RaycastProcessor that will be used to analyze the lines 
        *                       in the method castLine.
        * @param raster This is the raster in that this LineCaster analyzes lines.
        */
       public LineCaster(final RaycastProcessor pointProcessor, final SingleChannelStandardRaster raster)
       {
          this.pointProcessor = pointProcessor;
          this.raster = raster;
          dimension = raster.getDimensions();
       }
    
       /**
        * This method analyzes the line specified by the parameters startPoint and endPoint. 
        * The pointProcessor of this LineCaster is used to compute the resulting value, while the 
        * raster of this LineCaster is the environment for the analysis.
        *
        * @param startPoint This is the start point of the line.
        * @param endPoint This is the end point of the line.
        * @return The value of the pointProcessor after processing all points of the line inside the raster
        *         will be returned. If the line has no points inside the raster, 0 will be returned.
        */
       public float castLine(final Vector startPoint, final Vector endPoint)
       {
          // Check parameters.
          if (startPoint.getDimension() != dimension)
             throw new IllegalArgumentException("startPoint has wrong dimension.");
          if (endPoint.getDimension() != dimension)
             throw new IllegalArgumentException("endPoint has wrong dimension.");
    
          // Clip line: 
          // Resulting line is given by rasterStartPoint and rasterEndPoint.
          final int[] rasterStartPoint = new int[dimension];
          final int[] rasterEndPoint = new int[dimension];
          if(!setFirstPointInRaster(rasterStartPoint,startPoint,endPoint)) return 0.0f;
          if(!setFirstPointInRaster(rasterEndPoint,endPoint,startPoint)) return 0.0f;
    
          // Init helper variables.
          int maxDiffIndex = 0;
          final int[] intDifferences = new int[dimension];
          final int[] relativePosition = new int[dimension];
          final int[] position = new int[dimension];
          final int[] increments = new int[dimension];
          for(int i = 0 ; i < dimension ; ++i)
          {
             intDifferences[i] = rasterEndPoint[i] - rasterStartPoint[i];
             increments[i] = (intDifferences[i] > 0) ? 1 : -1;
             intDifferences[i] = Math.abs(intDifferences[i]);
             if (intDifferences[i] > intDifferences[maxDiffIndex]) maxDiffIndex = i;
             relativePosition[i] = intDifferences[i] >> 1;
             position[i] = rasterStartPoint[i];
          }
          final int maxDifference = intDifferences[maxDiffIndex];
          final int maxIncrement = increments[maxDiffIndex];
    
          // Process line: 
          // 1. Reset pointProcessor.
          // 2. Process Bresenham-Line-Algorithm
          // 3. Return value of pointProcessor
          pointProcessor.reset();
          for(;position[maxDiffIndex] != rasterEndPoint[maxDiffIndex] ; position[maxDiffIndex] += maxIncrement)
          {
             if (pointProcessor.addPoint(raster,position)) return pointProcessor.getValue();
             for(int i = 0 ; i < dimension ; ++i)
             {
                if (i == maxDiffIndex) continue;
                relativePosition[i] += intDifferences[i];
                if (relativePosition[i] < maxDifference) continue;
                position[i] += increments[i];
                relativePosition[i] -= maxDifference;
             }
          }
          pointProcessor.addPoint(raster,position);
          return pointProcessor.getValue();
       }
    
       private final boolean setFirstPointInRaster(final int[] target, final Vector firstLinePoint,
                                                   final Vector lastLinePoint)
       {
          // Compute the distance of the line's start- and endpoint in each direction.
          final double[] distances = new double[dimension];
          double fraction = 0.0;
          for (int i = 0 ; i < dimension ; ++i)
          {
             distances[i] = (float)(lastLinePoint.getComponent(i) - firstLinePoint.getComponent(i));
          }
    
          // Compute the fraction that represents the point where the line enters the raster.
          for (int i = 0 ; i < dimension ; ++i)
          {
             double newFraction = 0.0;
             final double component = firstLinePoint.getComponent(i);
             final double difference = distances[i];
             final double maxValue = raster.getSize(i) - 1;
             if (component < 0.0)
             {
                if (difference <= 0.0) return false;
                newFraction = component / difference;
             }
             else if (component > maxValue)
             {
                if (difference >= 0.0) return false;
                newFraction = (component - maxValue) / difference;
             }
             if (newFraction < fraction) fraction = newFraction;
          }
    
          // Use the fraction to compute the first point of the line that lies within the raster
          // and check if the point really lies within the raster.
          // The point may not lie within the raster if there is no point of the line in the raster.
          for (int i = 0 ; i < dimension ; ++i)
          {
             target[i] = Math.round((float)(firstLinePoint.getComponent(i) - fraction * distances[i]));
             if (target[i] < 0) return false;
             if (target[i] > raster.getSize(i) - 1) return false;
          }
          return true;
       }
    }
    

    ...aber es kann auch vorkommen, dass ich Dinge gar nicht kommentiere, so wie das da zum Beispiel:

    /*
     * MedianFilter.java
     *
     * Created on 20. März 2005, 17:37
     */
    
    package jaradap.model.algorithm;
    
    import controller.*;
    import controller.descriptor.*;
    import jaradap.model.algorithm.edgeHandler.EdgeHandler;
    import jaradap.model.algorithm.edgeHandler.NearestElementEdgeHandler;
    import jaradap.model.algorithm.edgeHandler.RemapRaxelEdgeHandler;
    import jaradap.model.algorithm.hierarchical.LocalNeighborhoodTransformer;
    import jaradap.model.algorithm.multiPointProcessor.MedianPointProcessor;
    import jaradap.model.algorithm.neighborhood.*;
    import jaradap.model.data.SingleChannelStandardRaster;
    
    /**
     *
     * @author Gregor Michalicek
     */
    @MenuStructure({"Process","Median Filter..."})
    @Name("Median Filter")
    public class MedianFilter implements DataProcessor<SingleChannelStandardRaster,SingleChannelStandardRaster>
    {
       private final LocalNeighborhood neighborhood;
       private final EdgeHandler edgeHandler;
    
       /** Creates a new instance of MedianFilter */
       @Name("Default Construction")
       public MedianFilter
          (
             final @Name("Radius") @FloatBounds(defaultValue = 1.0f, max = 10.0f) float radius,
             final @Name("Distance Type") @DefaultClass(EuclideanDistance.class) Distance distance,
             final @Name("Edge Handler") @DefaultClass(NearestElementEdgeHandler.class) EdgeHandler edgeHandler
          )
       {
          if (radius < 0) throw new IllegalArgumentException("radius is negative.");
          if (distance == null) throw new NullPointerException("distance is null.");
          if (edgeHandler == null) throw new NullPointerException("edgeHandler is null.");
          neighborhood = new LocalNeighborhood(radius, distance);
          this.edgeHandler = edgeHandler;
       }
    
       public SingleChannelStandardRaster processData(final SingleChannelStandardRaster inData)
       {
          if (inData == null) throw new NullPointerException("inData is null.");
          final SingleChannelStandardRaster outRaster = ControllerMethods.createCopy(inData);
          final LocalNeighborhoodTransformer neighborhoodTransformer = 
             new LocalNeighborhoodTransformer(neighborhood,new MedianPointProcessor(),outRaster,edgeHandler);
          neighborhoodTransformer.processRaster(inData);
          return outRaster;
       }
    
    }
    


  • Zeus schrieb:

    Yup, und wie Gregor schon verlinkt hat:

    Hmm, und wenn man jetzt zwischen dem Öffnen der verschiedenen Dateien etwas lesen will, wie sieht das dann aus?



  • Also ich dokumentiere zu wenig. Aber wenn ich dokumentiere, dann dokumentiere ich das, was mir am wenigsten nachvollziehbar erscheint. Eine Klasse sollte immer eine Erklärung erhalten, Parameter erhalten bei mir aber in aller Regel wenig Erklärung, denn die sollten bei dem Methodennamen (evtl. plus Erklärung dazu) in Zusammenhang mit der Klasse selbsterklärend sein - außer man hat optionale Parameter oder so ungenauen Müll (habe ich leider noch viel zu oft), dann braucht man leider Kommentare.

    Was ich aber nie habe ist so was wie

    @param startPoint This is the start point of the line.

    , weil das einfach Platz kostet und nichts hilft.

    Aber gut, wenn nachher eine HTML-Dokumentation rauskommen soll, geht es natürlich gar nicht wenn ein selbsterklärender Parameter nicht erklärt ist, gehört einfach zu einem harmonischen Gesamtbild. (die Aussage soll schon die Ironie fangen, dass selbsterklärende Parameter nicht erklärt werden müssen, gleichzeitig aber auch eingestehen, dass eine Doku mit Lücken scheiße wirkt, insgesamt also ein Zugeständnis an den Stil, wenngleich man den Code verschändelt, damit nachher eine HTML-Dokumentation schön aussieht - aber gut, das ist halt wirtschaftlich und somit trotzdem okay)



  • Javadoc ist ein riesen Vorteil finde ich.
    Es baut dir nicht nur die html Seiten, der gesamte Java Quelltext ist so kommentiert und das Javadoc kann auch direkt in deine IDE z.b. Eclipse integriert werden, dass es direkt angezeigt wird.

    die @ Dinger nennt man Annotations. Es gibt Kommentar Annotations und Code Annotations, die funktionieren so ähnlich wie Interfaces, oder können zur Laufzeit was zuweisen. In kommentaren kann man damit z.B. auf andere Kassen und Methoden verweisen, z.B. @see{Integer#toString} würde in dem Kommentar auf die toString Methode von Integer verweisen...

    Generell ist es bei Java Entwickler üblich den Code gut zu kommentieren, zumindest den Header einer Methode (jaja, ich weiß guter C Code ist selbsterklärend und benötigt keine Kommentare 😉 so sagen es zumindest immer unsere C Entwickler)



  • Von Java auf C++ umsteigen ist total einfach, auch wenn die hier so tun, also ob es das schwerste auf der Welt ist und nur die es hier geschafft haben, weil sie die Code-Kings sind.

    Du musst dir nur ein paar Sachen merken (Reihenfolge unsortiert):
    1. Verwende kein new (falls doch, schau dir Smartpointer an). Was geht kommt auf den Stack.
    2. http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization
    3. Exceptions werden fast nie verwendet (im Vergleich zu Java)
    4. http://en.wikipedia.org/wiki/Const-correctness
    5. Templates (zu 98% schreibst du sowieso keinen Templatecode, sondern wendest nur fertige Libs mit Templates an)
    6. Referenzen/Parameterübergabe: Übergib nicht ganze Klassen als Parameter, sondern const& oder & und falls es mal sein muss einen Pointer.
    7. http://de.wikipedia.org/wiki/Initialisierungsliste (Vorsicht, die gibt nicht die Initialisierungsreihenfolge vor)
    8. C++ castet jedem Müll. (Wenn du ein int übergibst, macht der Compiler auch mal ein bool daraus, wenn er eine passende Funktion findet.)
    9. Strings sind ein Graus in C++. Ich kann dir nicht wirklich einen guten empfehlen, wer std::string sagt, hat keine Ahnung von Internationalisierung.
    10. Es gibt Headerfiles: Viel Spass mit dem eigentlich unnötigen Zeugs.
    11. Verwende std::vector und ähnliche Container.
    11.1. Wenn du hier als Oberchecker akzeptiert werden willst, dann auch noch das std::algorithm Zeugs, ist aber nicht nötig, außer man will angeben.
    12. Operatorüberladung gibts auch noch und das http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)

    Damit solltest du schon ganz gut durchkommen.



  • 13. Iteratoren hab ich vergessen, die gibts in Java auch, aber in C++ verwendest du sie am besten so oft wie möglich und schreibt immer ++iter. Wenn du iter++ schreibst erkannt man sofort den Noob.

    Und wenn du spass haben willst. http://yosefk.com/c++fqa/



  • Ich habe Java auch vor C++ gelernt (und davor alles mögliche andere, wie Pascal, zig Basic-Varianten, bissel x86 Assembler...)

    Ich fand Stroustrup's Buch ideal für mich. Das war genau das richtige Tempo. Das Buch richtet sich auch nicht an totale Anfänger. Programmiererfahrung in anderen Sprachen sollte man da schon haben.

    idx schrieb:

    Ich suche daher ein gute Buch oder Tutorial was nicht bei 0 anfängt, d.h ich habe durchaus Erfahrung mit Programmierung (auch wenn die C Entwickler einen Java Entwicklern gerne belächeln)

    Stroustrup's The C++ Programming Language in der vierten Auflage.

    idx schrieb:

    Speziell solche Sachen wie Speicherverwaltung, Pointer und Effektiver Code interessieren mich.

    Wenn du Stroustrup's Buch durch hast, guck mal, ob es von "Effective C++" schon eine vierte Edition gibt, die C++11 berücksichtigt. Wenn nicht, kannst du Dir ja auch noch die 3. Edition besorgen. Ist nicht mehr die jünste, stehen aber gute Tipps drin.

    idx schrieb:

    Was gibt es so für Standard libs oder Funktionen die jeder kennen sollte?

    Steht in Stroustrup's Buch drin. Ausführlicher aber auch hier. Es gibt auch kostenlose Online-Referenzen. Auf Anhieb verstehen tut man die wahrscheinlich weniger. Da sollte man sich doch mal mit 'nem Buch schlau gemacht haben, was z.B. erklärt, wie das genau mit den Containern, Iteratoren und Algorithmen zusammenhängt, was funktionsobjekte sind, etc etc etc

    idx schrieb:

    (Bei Java z.B. dieser ganze Apache Kram - commons oder log4j und solche Sachen)

    Achso, dann hast du das Wort "Standard" vorhin anders verwendet als ich es verstanden habe. Bei "Standard" im Kontext C++ denke ich an den ISO Standard 14882. Quasi-Standardbibliotheken gibt es auch. Eine davon ist z.B. die Sammlung Boost. Dann gibt's noch Qt, Poco, Eigen, ...

    idx schrieb:

    Was für Stolperfallen gibt es?

    Steht einiges in Stroustrup's Buch sowie Scott Meyers' "Effective C++".



  • SoGehtEs schrieb:

    Und wenn du spass haben willst. http://yosefk.com/c++fqa/

    Nicht mal für eine Belustigung reicht c++fqa aus. Im Wesentlichen beschränkt sich der Nutzen von c++fqa auf Leute, die C++ nicht wirklich kennen aber doch irgendwie bashen wollen, in dem sie darauf verlinken ... à la "Ich weiß zwar nicht, wovon ich rede, aber C++ ist scheisze, weil siehe c++fqa".



  • krümelkacker schrieb:

    SoGehtEs schrieb:

    Und wenn du spass haben willst. http://yosefk.com/c++fqa/

    Nicht mal für eine Belustigung reicht c++fqa aus. Im Wesentlichen beschränkt sich der Nutzen von c++fqa auf Leute, die C++ nicht wirklich kennen aber doch irgendwie bashen wollen, in dem sie darauf verlinken ... à la "Ich weiß zwar nicht, wovon ich rede, aber C++ ist scheisze, weil siehe c++fqa".

    Wenn man keine Argumente hat, lügt man halt um seine Lieblingssprache zu verteidigen.


Anmelden zum Antworten