Von Java nach C++ Frank Weichert, Heinrich Müller Informatik VII Universität Dortmund http://ls7-www.cs.uni-dortmund.de Von Java nach C++, LS VII, Universität Dortmund, SS 2006 1 Übersicht • Einleitung • Literatur • Vergleich zwischen C++ und Java • Klassen in C++ • Übersetzungsprozess von C++-Programmen • Programmieren in Visual Studio • Ausgewählte C++-Konzepte Von Java nach C++, LS VII, Universität Dortmund, SS 2006 2 Einleitung „C makes it easy to shoot yourself in the foot, C++ makes it harder, but when you do, it blows away your whole leg.“ (Bjarne Stroustrup) Von Java nach C++, LS VII, Universität Dortmund, SS 2006 3 Literatur • Die C++-Programmiersprache, Bjarne Stroustrup, Addison-Wesley • Visual C++, Frank Budszuhn, Addison-Wesley Von Java nach C++, LS VII, Universität Dortmund, SS 2006 4 C++ vs. Java Von Java nach C++, LS VII, Universität Dortmund, SS 2006 5 C++ vs. Java • typisches Programm #include <iostreams.h> int main() { … return 0; } • Dateinamen beliebig, Konvention *.cpp, *.h • generierter Code - Maschinencode import java.awt.*; class Test{ public static void main(String[] argv){ … } } <Klassenname>.java - Java-Byte-Code - plattformabhängig - plattformunabhängig - *.exe - *.class Von Java nach C++, LS VII, Universität Dortmund, SS 2006 6 C++ vs. Java • bedingte Anweisungen, Schleifen, Verbundanweisungen,… identisch • Funktionen „globale“ Funktionen möglich identisch Methoden müssen in einer Klasse stehen • Felder int a[4]; int a[] = new int[4]; int a[] = {1,2,3}; int a[] = {1,2,3}; keine Überprüfung auf „Array-Grenzen“ Felder sind Objekte, Überprüfung auf „Array-Grenzen“ • Konstanten const double pi=3.14; final double pi=3.14; Von Java nach C++, LS VII, Universität Dortmund, SS 2006 7 C++ vs. Java • (Variablen-) Deklaration keine Default-Werte Default-Werte int a[4]; int a[] = new a[4]; • Speicherverwaltung durch den Programmierenden automatisch durch den Garbage Collector • Eingabe- und Ausgabeanweisungen cin >> x; cout << x; x=ioHelp.read(); System.out.println(x); • Boolescher Datentyp bool boolean Von Java nach C++, LS VII, Universität Dortmund, SS 2006 8 C++ vs. Java • Type-Casting (explizite Konvertierung) a) (Typ) Ausdruck in C++ und Java erlaubt Beispiel: int a=3; double b=(double) a / 2; b) Typ (Ausdruck) // b = 1.5 nur in C++ erlaubt Beispiel: int a=3; double b= double(a) / 2; // b = 1.5 Von Java nach C++, LS VII, Universität Dortmund, SS 2006 9 C++ vs. Java Zusätzliche Java-Funktionalität • Automatische Speicherverwaltung • Code ist (direkt) systemportabel • Strings und Felder • Applets • Multitasking durch Thread-Modell Von Java nach C++, LS VII, Universität Dortmund, SS 2006 10 C++ vs. Java Zusätzliche C++-Funktionalität (1) • Zeiger (Pointer) • Kontrolle des Memory Management • Templates • Operator-Overloading • Mehrfachvererbung • Präprozessor Von Java nach C++, LS VII, Universität Dortmund, SS 2006 11 C++ vs. Java Zusätzliche C++-Funktionalität (2) • Einschränkung des Wertebereichs in C++ per unsigned möglich z.B. int: -231 bis 231 – 1 unsigned int: 0 bis 232 – 1 • Symbolische Konstanten Präprozessorbefehl, erkennbar am „#“-Zeichen #define PI=3.14 (kein „;“ am Zeilenende) • Typdeklaration Definiert neuen Namen für einen Datentyp typedef int Index; Index a=3; Von Java nach C++, LS VII, Universität Dortmund, SS 2006 12 Ein einfaches Programm - Quellcodes Java: class BV{ public static void main(String[] argv){ System.out.println "C++ in der Bildverarbeitung!"; } } C++: #include <iostream> using namespace std; int main(int argc){ cout << "C++ in der Bildverarbeitung!"; return 0; } Von Java nach C++, LS VII, Universität Dortmund, SS 2006 13 Ein einfaches Programm - Übersetzen Java: • Dateiname: BV.java • Übersetzen: javac BV.java (Java Byte-Code) • Ausführen: java BV (Java Virtual Machine) C++: • Dateiname: BV.cpp • Übersetzen: cl /c BV.cpp cl BV.cpp • Linken: link BV.obj • Ausführen: BV Von Java nach C++, LS VII, Universität Dortmund, SS 2006 14 Klassen in C++ Von Java nach C++, LS VII, Universität Dortmund, SS 2006 15 Klassen in C++ • Klassen in C++ = Deklaration Headerdatei (.h) + Implementierung Implementationsdatei (.cpp) Studierende.h: class Studierende{ … }; Studierende.cpp: #include "Studierende.h" … Von Java nach C++, LS VII, Universität Dortmund, SS 2006 16 Klassen in C++: Aufbau der Headerdatei Studierende.h: class Studierende{ • Konstruktor public: Studierende(); • Destruktor ~Studierende(); • Methoden void setzeMatrikelnummer(int nummer); int gibMatrikelnummer(); • Attribute private: int matrikelnummer; }; Von Java nach C++, LS VII, Universität Dortmund, SS 2006 17 Klassen in C++: Aufbau der Headerdatei • Spezifizierung einer Klasse mit class • Klassen sind immer public • Konstruktoren und Destruktoren Konstruktoren: Instanziierung von Objekten Destruktoren: Löschen von instanziierten Objekten (~ vorangestellt) • Deklaration von Methoden und Variablen • (Instanz-) Variablen dürfen bei der Deklaration nicht initialisiert werden • Modifier werden nicht separat spezifiziert • Klassendefinition wird mit Semikolon beendet Von Java nach C++, LS VII, Universität Dortmund, SS 2006 18 Klassen in C++: Aufbau der Implementationsdatei • Einbinden der Headerdatei mit include • Durch den Klassennamen und dem Bereichsoperator „::“ wird die Zugehörigkeit zur Klasse gekennzeichnet Studierende.cpp: #include "Studierende.h" Studierende::Studierende(){} Studierende::~Studierende(){} void Studierende::setzeMatrikelnummer(int nummer){ matrikelnummer = nummer; } int Studierende::gibMatrikelnummer(){ return matrikelnummer; } Von Java nach C++, LS VII, Universität Dortmund, SS 2006 19 Klassen in C++: Aufbau der Implementationsdatei • Präprozessoranweisung #include "Studierende.h“ bindet Headerdatei ein. • Nennung von „Fully Qualified Names“ z.B.: Studierende::Studierende() • „ :: „ wird als Bereichsoperator (Scope Operator) bezeichnet • inline-Spezifikation möglich z.B.: inline int Studierende::gibMatrikelnummer(){ return matrikelnummer; } Von Java nach C++, LS VII, Universität Dortmund, SS 2006 20 Übersetzungsprozess von C++-Programmen Von Java nach C++, LS VII, Universität Dortmund, SS 2006 21 Übersetzen von C++-Programmen Übersetzungsprozess besteht aus drei Komponenten 1. Präprozessor: Vorverarbeitung des Quellcodes 2. Compiler: Überführt Quellcode in Objektcode 3. Linker: Fasst alle Objektdateien zu einem ausführbaren Programm zusammen Von Java nach C++, LS VII, Universität Dortmund, SS 2006 22 Übersetzen von C++-Programmen Von Java nach C++, LS VII, Universität Dortmund, SS 2006 23 Übersetzen von C++-Programmen Präprozessor • Präprozessorbefehle beginnen mit dem #-Zeichen • Sucht im Quellcode nach speziellen Befehlen, z.B. - #include einbinden von Headerdateien a) <name> Standard Libraries aus Systemverzeichnis z.B.: #include <iostream> b) “name“ „eigene Dateien“ aus Projektverzeichnis z.B.: #include "Studierende.h" -> Problem: mehrfache Deklarationen - #define führt textuelle Ersetzungen (Konstanten) aus. z.B.: #define pi 3.14 - #ifdef, #ifndef,… Konditionales Kompilieren z.B.: #ifdef DEBUG … #endif Von Java nach C++, LS VII, Universität Dortmund, SS 2006 24 Übersetzen von C++-Programmen Präprozessor -> Problem: mehrfache Deklarationen Lösung: Headerdatei um konditionalen Kopf erweitern z.B.: Studierende.h: #ifndef STUDIERENDE_H #define STUDIERENDE_H class Studierende{ … }; #endif Von Java nach C++, LS VII, Universität Dortmund, SS 2006 25 Übersetzen von C++-Programmen Compiler • Generiert aus dem vom Präprozessor vorverarbeiteten Quellcode den Objektcode. • Maschinennahe Objektcodedatei kann noch „offene Aufrufe“ enthalten und nicht ausgeführt werden. • Überprüfung auf syntaktische Korrektheit - Fehlermeldungen z.B.: error C2065: 'h': nichtdeklarierter Bezeichner - Warnungen z.B.: warning C4244: 'Initialisierung': Konvertierung von 'double' in 'int', möglicher Datenverlust • Objektcode wird nur erzeugt, sofern keine Fehler aufgetreten sind. Von Java nach C++, LS VII, Universität Dortmund, SS 2006 26 Übersetzen von C++-Programmen Linker • Generiert (vollständig) ausführbares Programm • Fasst die - Objektdateien des Projektes, - Code aus Standard Libraries und - zusätzliche Libraries zusammen • Zwei mögliche „Link-Modi“ - statisch - dynamisch Von Java nach C++, LS VII, Universität Dortmund, SS 2006 27 Programmieren in Visual Studio Von Java nach C++, LS VII, Universität Dortmund, SS 2006 28 C++-Programm mit Visual Studio • Neues Projekt anlegen: Datei -> Neu -> Projekt • Projekttyp festlegen • Projektnamen und Verzeichnis auswählen Von Java nach C++, LS VII, Universität Dortmund, SS 2006 29 C++-Programm mit Visual Studio • Initiales Arbeitsfenster der Entwicklungsumgebung Von Java nach C++, LS VII, Universität Dortmund, SS 2006 30 C++-Programm mit Visual Studio • Klasse hinzufügen (Header- und Implementationsdatei) Von Java nach C++, LS VII, Universität Dortmund, SS 2006 31 C++-Programm mit Visual Studio • Typ der Klasse auswählen, die hinzugefügt werden soll Von Java nach C++, LS VII, Universität Dortmund, SS 2006 32 C++-Programm mit Visual Studio • Klassennamen festlegen • Modifikator und Basisklasse (optional) bestimmen Von Java nach C++, LS VII, Universität Dortmund, SS 2006 33 C++-Programm mit Visual Studio Von Java nach C++, LS VII, Universität Dortmund, SS 2006 34 C++-Programm mit Visual Studio • Ausführbares Programm erstellen - Kompilieren (Strg+F7) - Programm ausführen (Strg+F5) - Programm unter Debugger ausführen (F5) Von Java nach C++, LS VII, Universität Dortmund, SS 2006 35 C++-Programm mit Visual Studio • Dateitypen von Visual-Studio Extension Bedeutung *.cpp C++-Quelldatei *.h C++-Headerdatei *.exe Ausführbares Programm *.dsp Informationen zum Projekt. Projekt kann über dspDatei geöffnet werden *.dsw Informationen zum Arbeitsbereich. Dieser sollte auch über diese Datei geöffnet werden. *.obj Nicht eingebundene Kompilate (Objekt-Dateien) *.rc Ressourcen-Skriptdatei *.res Binäre Ressourcendatei des Linkers Von Java nach C++, LS VII, Universität Dortmund, SS 2006 36 Ausgewählte C++-Konzepte • Komplexe Datentypen • Zeiger und Referenzen • Vererbung • STL Von Java nach C++, LS VII, Universität Dortmund, SS 2006 37 Komplexe Datentypen Benutzerdefinierter Datentyp mit eindeutigem Namen … typedef struct{ double x, y, z; } vector3D; … int main() { vector3D vecA = {0.4, 4, 6.2}; vector3D vecB; vecB = vecA; double a = vecA.z; // vecB = {0.4, 4, 6.2} // a = 6.2 … • Zugriff auf Elemente mit „.“-Operator • Bei Zuweisungen werden komplette Strukturen kopiert Von Java nach C++, LS VII, Universität Dortmund, SS 2006 38 Ausgewählte C++-Konzepte • Komplexe Datentypen • Zeiger und Referenzen • Vererbung • STL Von Java nach C++, LS VII, Universität Dortmund, SS 2006 39 Objekte instanziieren und löschen ProgrammStudierende.cpp: #include "Studierende.h" int main(int argc, char* argv[]){ Studierende* einStudent = new Studierende(); delete einStudent; return 0; } • Instanziierung eines Objektes vom Typ Studierende Studierende*: Variablendeklaration einStudent: „Zeiger auf Studierende“ new: Ruft Konstruktor auf und legt Objekt vom angegebenen Typ im Speicher an • delete ruft Destruktor der Klasse auf und gibt den zuvor belegten Speicher wieder frei (kein Garbage Collector wie in Java) Von Java nach C++, LS VII, Universität Dortmund, SS 2006 40 Zeiger und Referenzen Anweisung: Studierende* einStudent = new Studierende(); Repräsentierung: 0x1200 Speicher 0x0000 Studierende int matrikelnummer Studierende* einStudent = 0x1200 0xffff Klasseninstanz Von Java nach C++, LS VII, Universität Dortmund, SS 2006 Zeiger 41 Zeiger und Referenzen • Zeiger (Pointer): Variable, dessen Wert auf die Position (Speicheradresse) eines anderen Objektes zeigt. • eigener Datentyp • typisiert • durch Zeichen „*“ gekennzeichnet Beispiel: a) kein Zeiger: int a; b) mit Zeiger: int* a; Von Java nach C++, LS VII, Universität Dortmund, SS 2006 42 Zeiger und Referenzen • Adresse Speicherstelle, die für ein Objekt zur Verfügung gestellt wird. Die Adresse wird bei der ObjektInstanziierung und der damit verbundenen Bereitstellung des benötigten Speichers vergeben. • Inhalt Wert (Daten), der für ein Objekt unter einer Adresse gespeichert wird. Initiale Belegung erfolgt durch den Konstruktor. Von Java nach C++, LS VII, Universität Dortmund, SS 2006 43 Zeiger und Referenzen • Pointer: Pointer (Pointervariable) ist eine Variable in der eine Adresse gespeichert wird. Die Variable hat den identischen Typ wie die Variable, deren Adresse gespeichert wird. • Dereferenzierungsoperator „*“: Zugriff auf den Wert, der in der Pointervariablen gespeicherten Adresse steht („Wert, auf den der Pointer verweist“) • Referenzoperator „&“: Liefert für eine Variable die zugehörige Speicheradresse Von Java nach C++, LS VII, Universität Dortmund, SS 2006 44 Zeiger und Referenzen Adresse • Pointer-Deklaration Name 10012 int *iPtr; ??? 10013 iPtr 10014 • Pointer-Deklaration und Initialisierung Adresse Name 10012 int *iPtr=0; NULL 10013 iPtr 10014 Von Java nach C++, LS VII, Universität Dortmund, SS 2006 45 Zeiger und Referenzen • Deklaration eines primitiven Datentyps Adresse Name 10824 int i=423; 423 10825 i 10826 • Pointer-Initialisierung und Adressoperator Adresse 10012 int *iPtr=0; iPtr = &i; Name NULL 10825 10013 iPtr 10014 Von Java nach C++, LS VII, Universität Dortmund, SS 2006 46 Zeiger und Referenzen • Vereinfachte grafische Repräsentierung Adresse Name 10824 423 10825 i 10826 Adresse i Name 423 iPtr 10012 10825 10013 iPtr 10014 Von Java nach C++, LS VII, Universität Dortmund, SS 2006 47 Zeiger und Referenzen • Initialisierung von Pointern int a = 423; a 423 int b = 78; b 78 int *ptr_1 = &b; ptr_1 int *ptr_2 = ptr_1; ptr_2 int *ptr_3 = &a; ptr_3 Von Java nach C++, LS VII, Universität Dortmund, SS 2006 48 Zeiger und Referenzen • Pointer Aliasing: Zwei Pointer enthalten dieselbe Adresse a 423 b 78 423 *ptr_1 = *ptr_3; ptr_1 ptr_2 = ptr_3; ptr_2 ptr_3 Von Java nach C++, LS VII, Universität Dortmund, SS 2006 49 Zeiger und Referenzen • Zeigervariablen können auch auf einen weiteren Zeiger verweisen • Auch iteriete Pointer-Anwendungen sind möglich • Jeder „*“-Operator im Ausdruck entspricht einer Dereferenzierung int a = 423; int *ptr = &a; int **ptrPtr = 0; a 423 ptr ptrPtr NULL ptrPtr = &ptr; Von Java nach C++, LS VII, Universität Dortmund, SS 2006 50 Zeiger und Referenzen • Anwendungsbeispiel #include <iostream> #include "Studierende.h" using namespace std; int main(int argc, char* argv[]){ Studierende* einStudent = new Studierende(); einStudent->setzeMatrikelnummer(88456); Studierende zweiterStudent; zweiterStudent.setzeMatrikelnummer(87393); Studierende* ptr_zweiterStudent = &zweiterStudent; cout << ptr_zweiterStudent << endl; Studierende* dritterStudent = NULL; dritterStudent->setzeMatrikelnummer(89263); delete einStudent; delete dritterStudent; return 0; } Von Java nach C++, LS VII, Universität Dortmund, SS 2006 51 Zeiger und Referenzen • Zeiger einStudent, der auf Objekt vom Typ Studierende zeigt • Über Operator -> (Dereferenzieren) Methode aufrufen („es wird einem Zeiger gefolgt“) Studierende* einStudent = new Studierende(); einStudent->setzeMatrikelnummer(88456); • zweiterStudent als (statische) Instanz • Methodenaufruf für statische Instanzen über Punktoperator Studierende zweiterStudent; zweiterStudent.setzeMatrikelnummer(87393); Von Java nach C++, LS VII, Universität Dortmund, SS 2006 52 Zeiger und Referenzen • Pointer auf statische Instanz über Referenzoperator & Studierende* ptr_zweiterStudent = &zweiterStudent; cout << ptr_zweiterStudent << endl; • Zeiger für ein Objekt, der mit NULL initialisiert wird • Methodenaufruf führt zu einem Laufzeitfehler (Exception) Studierende* dritterStudent = NULL; dritterStudent->setzeMatrikelnummer(89263); Von Java nach C++, LS VII, Universität Dortmund, SS 2006 53 Ausgewählte C++-Konzepte • Komplexe Datentypen • Zeiger und Referenzen • Vererbung • STL Von Java nach C++, LS VII, Universität Dortmund, SS 2006 54 Vererbung einfache Vererbung: • Klasse Bachelor erbt von Klasse Studierende • Vererbungsoperator „:“ (entspricht extends in Java) Studierende Bachelor Studierende.h: class Studierende{ … }; Bachelor.h: #include "studierende.h" class Bachelor : public Studierende{ public: Bachelor(); ~Bachelor(); }; Von Java nach C++, LS VII, Universität Dortmund, SS 2006 55 Vererbung Mehrfachvererbung: • Klasse Bachelor erbt von Klassen Studierende und HiWi Studierende HiWi Bachelor Bachelor.h: #include "studierende.h" #include "HiWi.h" class Bachelor : public Studierende, public HiWi{ public: Bachelor(); ~Bachelor(); }; Von Java nach C++, LS VII, Universität Dortmund, SS 2006 56 Ausgewählte C++-Konzepte • Komplexe Datentypen • Zeiger und Referenzen • Vererbung • STL Von Java nach C++, LS VII, Universität Dortmund, SS 2006 57 STL Standard-Template-Library (kurz STL) • Vordefinierte Templates für viele Anwendungsbereiche • STL gliedert sich in drei Teilbereiche auf: 1.) Container: Speicherstrukturen, z.B. Bäume, Listen,… 2.) Algorithmen: Operatoren für Container-Klassen, z.B. Sortieren einer Liste 3.) Iteratoren: Traversierungsoperatoren für Container-Klassen • Einbinden der Headerdateien per include ohne Endung „.h“ Beispiel: #include<list> • Notwendigkeit des korrekten „Namespace“, geschieht durch die Anweisung „using namespace std;“ • Infos zur STL: Silicon Graphics Inc., http://www.sgi.com/tech/stl Von Java nach C++, LS VII, Universität Dortmund, SS 2006 58 STL Anwendungsbeispiel: #include <list> #include "Studierende.h" using namespace std; int main(int argc, char* argv[]){ Studierende* student1 = new Studierende(); Studierende* student2 = new Studierende(); list<Studierende*> listeStudierende; listeStudierende.push_back(student1); listeStudierende.push_back(student1); } • Einbinden der Headerdatei für die Container-Klasse list. • Instanziierung einer Liste listeStudierende, die Zeiger auf Objekte vom Typ Studierende speichern kann. • Methode push_back fügt Zeiger auf Typ Studierende der Liste an. Von Java nach C++, LS VII, Universität Dortmund, SS 2006 59