Präsentation herunterladen
Die Präsentation wird geladen. Bitte warten
Veröffentlicht von:Erika Lind Geändert vor über 6 Jahren
2
Crashkurs C++ Mit Hilfe von Java Fachvortrag IPhone Alexis Popovski
Serdar Korkmaz Canan Ucan Tuan Nguyen Dominic Engel
3
Crashkurs C++ Mit Hilfe von Java Fachvortrag IPhone Alexis Popovski
Serdar Korkmaz Canan Ucan Tuan Nguyen Dominic Engel
4
Installation und Grundaufbau
Gliederung Speicher Vergleich und Fazit Konstruktoren/ Destruktoren Zeiger und Referenzen Einführung Installation und Grundaufbau
5
Vergleich und Fazit Gliederung
6
Einführung
7
Entstehung Bjarne Stroustrup C als prozedurale Sprache
Klassen von SIMULA Erscheinungsjahr: 1985
8
Entstehung Bjarne Stroustrup C als prozedurale Sprache
Klassen von SIMULA Erscheinungsjahr: 1985 Bjarne Stroustrup
9
Multiparadigmensprache Entstehung
Generisch Prozedural Objektorientiert
10
Multiparadigmensprache
Generisch Objektorientiert Prozedural
11
Prozedurale Programmierung (POP) Multiparadigmensprache
Programme bestehen aus einer (endlichen) Folge von Anweisungen Zur Strukturierung werden inhaltlich zusammenhängende (Teil-)Folgen von Anweisungen in Prozeduren zusammengefasst Prozeduren: Folge imperativer Anweisungen: Zuweisungen, Tests, Schleifen, Aufrufe Unterprozeduren Prozeduren sind Funktionen, die Argumente entgegennehmen & abhängige Rückgabewerte liefern typische POP-Sprachen: Fortran, C, COBOL, Pascal
12
Prozedurale Programmierung (POP)
Programme bestehen aus einer (endlichen) Folge von Anweisungen Zur Strukturierung werden inhaltlich zusammenhängende (Teil-)Folgen von Anweisungen in Prozeduren zusammengefasst Prozeduren: Folge imperativer Anweisungen: Zuweisungen, Tests, Schleifen, Aufrufe Unterprozeduren Prozeduren sind Funktionen, die Argumente entgegennehmen & abhängige Rückgabewerte liefern typische POP-Sprachen: Fortran, C, COBOL, Pascal
13
Prozedurale Programmierung (POP) vs.
Prozedurale Programmierung (POP) vs. Objektorientierten Programmierung (OOP) Prozedurale Programmierung (POP) vs. Objektorientierte Programmierung (OOP) Prozedurale Programmierung (POP) Objektorientierte Programmierung soll Schwierigkeiten, die bei der prozeduralen Programmierung entstehen können, reduzieren Hauptmodule: Klassen und nicht Prozeduren Erstellung von Klassen und Objekten Modellierung von realen Objekten
14
Prozedurale Programmierung (POP) vs.
Objektorientierte Programmierung (OOP) Objektorientierte Programmierung soll Schwierigkeiten, die bei der prozeduralen Programmierung entstehen können, reduzieren Hauptmodule: Klassen und nicht Prozeduren Erstellung von Klassen und Objekten Modellierung von realen Objekten
15
Objektorientierte Programmierung (OOP)
Prozedurale Programmierung (POP) vs. Objektorientierte Programmierung (OOP) Kapselung Objekt kapselt seine Attribute und Methoden Vererbung Eine abgeleitete Klasse erbt alle Eigenschaften ihrer Basisklasse Polymorphie Objekte einer Instanz verändern zu Laufzeit ihr Verhalten
16
Objektorientierte Programmierung (OOP)
Kapselung Objekt kapselt seine Attribute und Methoden Vererbung Eine abgeleitete Klasse erbt alle Eigenschaften ihrer Basisklasse Polymorphie Objekte einer Instanz verändern zu Laufzeit ihr Verhalten
17
Objektorientierte Programmierung (OOP) Generische Programmierung
Verfahren zur Entwicklung wiederverwendbarer Software-Bibliotheken Funktionen werden für unterschiedliche Datentypen möglichst allgemein entworfen Implementierung erfolgt durch das Konzept generischer Typen bzw. Templates Für Template unerheblich, ob es Zahlen oder Männer vertauschen soll (Zeile 11 & 12) Selbst Typ-Parameter T (Zeile 1) muss nicht spezifiziert werden Compiler kann diesen aus Funktionsargumenten (Zeile 11 & 12) ableiten
18
Generische Programmierung
Verfahren zur Entwicklung wiederverwendbarer Software-Bibliotheken Funktionen werden für unterschiedliche Datentypen möglichst allgemein entworfen Implementierung erfolgt durch das Konzept generischer Typen bzw. Templates Für Template unerheblich, ob es Zahlen oder Männer vertauschen soll (Zeile 11 & 12) Selbst Typ-Parameter T (Zeile 1) muss nicht spezifiziert werden Compiler kann diesen aus Funktionsargumenten (Zeile 11 & 12) ableiten
19
Generische Programmierung
Wann wird C++ verwendet? Wann eignet sich Java mehr? Geeigneter für Software zur Manipulation auf Hardware-Ebene Maschinennähe: Schneller Zugriff auf RAM, Festplatte, CPU usw. -> Beliebt bei gewerblicher Softwareerstellung Systemprogramme „sichere Sprache“ Anwendungsprogramme Eigene Schnittstelle für grafische Benutzeroberfläche Grundlage für Android-Entwicklung Frage der Effizienz für hohe Effizienz nimmt C++-Programmierung erhebliche Umstände in Kauf Sofern Optimierung zweitrangig -> Java
20
Wann wird C++ verwendet? Wann eignet sich Java mehr?
Geeigneter für Software zur Manipulation auf Hardware-Ebene Maschinennähe: Schneller Zugriff auf RAM, Festplatte, CPU usw. -> Beliebt bei gewerblicher Softwareerstellung Systemprogramme „sichere Sprache“ Anwendungsprogramme Eigene Schnittstelle für grafische Benutzeroberfläche Grundlage für Android-Entwicklung Frage der Effizienz für hohe Effizienz nimmt C++-Programmierung erhebliche Umstände in Kauf Sofern Optimierung zweitrangig -> Java
21
Installation und Grundaufbau
22
Compiler - Auswahl Clang GCC MSVC (MS Visual C++)
Nicht nur ein Compiler wie bei Java Clang GCC MSVC (MS Visual C++)
23
Compiler - Auswahl Clang GCC MSVC (MS Visual C++)
Nicht nur ein Compiler wie bei Java Clang GCC MSVC (MS Visual C++)
24
Editor - Auswahl Compiler - Auswahl CLion Visual Studio XCode
Visual Studio Code
25
Editor - Auswahl CLion Visual Studio XCode Visual Studio Code
26
Aufteilung in .h und .cpp – Datein
Editor - Auswahl Aufteilung in .h und .cpp – Datein Deklaration Implementierung
27
Aufteilung in .h und .cpp – Datein
Deklaration Implementierung
28
Aufteilung in .h und .cpp – Datein
Live Demo Aufteilung in .h und .cpp – Datein Beispiele im Anhang
29
Live Demo
30
Zeiger und Referenzen
31
Zeiger und Referenzen
32
Zeiger und Referenzen Sind ungefähr das Gleiche, aber wiederum auch nicht Sehr effizient zusammen, funktionieren jeweils aber auch alleine Abstrakt gesagt, sind Zeiger und Referenzen wie Bruder und Schwester Zeiger werden mit einem Asterisk (*) gekennzeichnet Referenzen werden mit einem Empersand (&) gekennzeichnet
33
Zeiger und Referenzen string a = "hi"; void doSomething(){} 0x00AZWE3…
0x014FVC… double a = 5.5; 0x12ADG56… Load Disc 0x014FVC… int a = 5; 0x00AZWE3… Instructions 0x00BFC…
34
Zeiger und Referenzen string a = "hi"; void doSomething(){} Load Disc
int a = 5; 0x00AZWE3… Instructions 0x00BFC… Load Disc 0x014FVC… void doSomething(){} double a = 5.5; 0x12ADG56… string a = "hi";
35
Zeiger und Referenzen Straße repräsentiert einen Speicherblock, mit einem Start und einem Ende Ein Computer braucht, für alles was wir an einem Computer tun, Speicher - Denn alles, was wir an einem Computer tun, wird in den Speicher geschoben und dort ausgeführt Alles, was in den Speicher geschoben wird, bekommt eine Adresse, auf die wir mit dem Zeiger zugreifen können(um Speicher zu managen und zu manipulieren)
36
Ein Zeiger ist einfach ein Integer, der eine Speicheradresse enthält
Was ist ein Zeiger? Ganz einfach: Ein Zeiger ist einfach ein Integer, der eine Speicheradresse enthält Mehr nicht!
37
Was ist ein Zeiger? Was sind Referenzen?
Eine Art „Erweiterung“ für Zeiger Ein Verweis auf eine bereits existierende Variable Belegen keinen neuen Speicher Referenzen referenzieren auf ein bereits existierendes Objekt …und können nicht nur deklariert werden, sondern müssen sofort initialisiert werden
38
Live Demo Was sind Referenzen? Beispiele im Anhang
39
Live Demo
40
Konstruktoren/ Destruktoren
41
Konstruktor & Destruktor
class Foo { public: Foo(); // Konstruktor (ctor) ~Foo(); // Destruktor (dtor) }; Aufgaben des Konstruktors Objekt in validen initialen Zustand überführen Benötigte Ressourcen akquirieren Aufgabe des Destruktors Ressourcen ggf. wieder freigeben
42
Konstruktor & Destruktor
class Foo { public: Foo(); // Konstruktor (ctor) ~Foo(); // Destruktor (dtor) }; Aufgaben des Konstruktors Objekt in validen initialen Zustand überführen Benötigte Ressourcen akquirieren Aufgabe des Destruktors Ressourcen ggf. wieder freigeben
43
Konstruktor & Destruktor
Scope und Lebenszeit von Objekten
44
Konstruktor & Destruktor
Scope und Lebenszeit von Objekten
45
Konstruktor & Destruktor
Scope und Lebenszeit von Objekten
46
Konstruktor & Destruktor
Scope und Lebenszeit von Objekten
47
Konstruktor & Destruktor
Das RAII-Prinzip RAII — Resource Acquisition Is Initialization Resource Ownership: Objekt besitzt Ressource Konstruktor holt / alloziert Ressource Destruktor gibt Ressource wieder frei Essentiell für Exception Safety Typische Ressourcen: Speicher, Datei, Thread, Hardware, Grafikpuffer- oder Texturobjekt etc.
48
Konstruktor & Destruktor
RAII — Resource Acquisition Is Initialization Resource Ownership: Objekt besitzt Ressource Konstruktor holt / alloziert Ressource Destruktor gibt Ressource wieder frei Essentiell für Exception Safety Typische Ressourcen: Speicher, Datei, Thread, Hardware, Grafikpuffer- oder Texturobjekt etc. Das RAII-Prinzip
49
Konstruktor & Destruktor
Das RAII-Prinzip: Einfaches Beispiel mit Speicher als Ressource
50
Konstruktor & Destruktor
Das RAII-Prinzip: Einfaches Beispiel mit Speicher als Ressource
51
Speicher
52
Speicher
53
Speicher aus Sicht von Java
(dieser Platz wurde absichtlich freigelassen)
54
Speicher aus Sicht von Java
(dieser Platz wurde absichtlich freigelassen)
55
Speicher aus Sicht von Java Speicher aus Sicht von C++
Heap Stack Statischer Speicher Programmspeicher Dynamische Speicherverwaltung Funktionsaufrufe, lokale Variablen Globale Variablen Das eigentliche Programm (z.B. Anweisungen)
56
Speicher aus Sicht von C++
Heap Stack Statischer Speicher Programmspeicher Dynamische Speicherverwaltung Funktionsaufrufe, lokale Variablen Globale Variablen Das eigentliche Programm (z.B. Anweisungen)
57
Speicher aus Sicht von C++
Stack Speicher aus Sicht von C++ Für Speicher auf dem Stack muss man nichts explizit anfordern oder freigeben Automatisch LIFO- Datenstruktur: „Last In First Out“ effizient Festgelegte Größe, kann in einer IDE oder direkt am Betriebssystem verändert werden
58
Stack Für Speicher auf dem Stack muss man nichts explizit anfordern oder freigeben Automatisch LIFO- Datenstruktur: „Last In First Out“ effizient Festgelegte Größe, kann in einer IDE oder direkt am Betriebssystem verändert werden
59
Stack Beispiel Vec2 doSomething(Vec2 param) { Stack Pointer :
FP SP Call Stack Stack Pointer : Beginn des freien Speichers Frame Pointer : Start des aktuellen Stack Frames Vec2 doSomething(Vec2 param) { Vec2 lokal(1,7); . return Vec2(...); } int main() Vec2 a(2,2); Vec2 b = doSomething(a);
60
Beispiel (2,2) a Vec2 doSomething(Vec2 param) { Vec2 lokal(1,7); .
FP SP Call Stack (2,2) a Vec2 doSomething(Vec2 param) { Vec2 lokal(1,7); . return Vec2(...); } int main() Vec2 a(2,2); Vec2 b = doSomething(a);
61
Beispiel FP SP Call Stack (2,2) a Reservierung von Speicher auf dem Call Stack für ein Vec2 Objekt und Initialisierung von a (2,2) SP wird um sizeOf(Vec2) erhöht. Da Vec2 nur zwei int- Werte verwaltet hat dieser die Größe von 8 bytes, also erhöht sich der SP um 8 bytes.
62
Beispiel (2,2) a b ? Vec2 doSomething(Vec2 param) { Vec2 lokal(1,7); .
FP SP Call Stack (2,2) a b ? Vec2 doSomething(Vec2 param) { Vec2 lokal(1,7); . return Vec2(...); } int main() Vec2 a(2,2); Vec2 b = doSomething(a);
63
Beispiel FP SP Call Stack (2,2) a b ? Es wird für Vec2 b Speicher auf dem Stack reserviert aber noch nicht initialisiert Um b initialisieren zu können müssen wir die Methode doSomething(..) aufrufen SP wird wieder um die Größe von Vec2 erhöht
64
Beispiel (2,2) a b ? RV RP 0xFF… Vec2 doSomething(Vec2 param) {
FP SP (2,2) a b ? RV RP 0xFF… Vec2 doSomething(Vec2 param) { Vec2 lokal(1,7); . return Vec2(...); } int main() Vec2 a(2,2); Vec2 b = doSomething(a); Call Stack
65
Beispiel (2,2) a b ? RV RP 0xFF…
FP SP (2,2) a b ? RV RP 0xFF… Vor dem Verlassen des Scopes wird folgendes vorbereitet: RV: Speicherplatz für den return Value wird reserviert RP: Rücksprungadresse wird gemerkt FP: Frame Pointer Adresse wird gemerkt FP wird auf den neuen Scope gesetzt SP wird ebenfalls erhöht auf den nächsten freien Speicherbereich gesetzt Call Stack
66
Beispiel (2,2) a b ? RV RP 0xFF… . Vec2 doSomething(Vec2 param) {
FP SP (2,2) a b ? RV RP 0xFF… . Vec2 doSomething(Vec2 param) { Vec2 lokal(1,7); . return Vec2(...); } int main() Vec2 a(2,2); Vec2 b = doSomething(a); Call Stack
67
Beispiel (2,2) a b ? RV RP 0xFF… .
FP SP (2,2) a b ? RV RP 0xFF… . Für alle Parameter und lokale Variablen werden ebenfalls Speicher auf dem Stack reserviert (Hier für die Vereinfachung mit „…“ dargestellt) Der zurückgegebener Wert wird in RV gespeichert Call Stack
68
Beispiel (2,2) a b RV RP 0xFF… . Vec2 doSomething(Vec2 param) {
FP SP (2,2) a b RV RP 0xFF… . Vec2 doSomething(Vec2 param) { Vec2 lokal(1,7); . return Vec2(...); } int main() Vec2 a(2,2); Vec2 b = doSomething(a); Call Stack
69
Beispiel (2,2) a b RV RP 0xFF… . der Stack räumt auf
FP (2,2) a b RV RP 0xFF… . SP der Stack räumt auf beim nächsten Aufruf werden die Daten überschrieben b wird initialisiert mit RV SP und FP zeigen wieder auf die Adressen vor dem Methodenaufruf Call Stack
70
Beispiel (2,2) a b RV RP 0xFF… . der Stack räumt auf
Call Stack der Stack räumt auf beim nächsten Aufruf werden die Daten überschrieben b wird initialisiert mit RV SP und FP zeigen wieder auf die Adressen vor dem Methodenaufruf FP (2,2) a b RV RP 0xFF… . SP
71
Beispiel Fazit Stack Begrenzte Größe LIFO Datenstruktur
Wächst und schrumpft im Programmverlauf Kein explizites Freigeben des Speichers notwendig Sehr effizient
72
Fazit Stack Begrenzte Größe LIFO Datenstruktur
Wächst und schrumpft im Programmverlauf Kein explizites Freigeben des Speichers notwendig Sehr effizient
73
Fazit Stack Frage an euch
Keine Referenzen (oder Pointer) auf ein lokales Objekt aus der Funktion heraus exportieren Wenn Scope endet wird „result“ vom Stack geräumt und die übergebene Referenz zeigt auf einen ungültigen Speicher
74
Frage an euch Keine Referenzen (oder Pointer) auf ein lokales Objekt aus der Funktion heraus exportieren Wenn Scope endet wird „result“ vom Stack geräumt und die übergebene Referenz zeigt auf einen ungültigen Speicher
75
Frage an euch Heap Heap Stack Statischer Speicher
Programmspeicher Dynamische Speicherverwaltung Dynamisch allozierte Objekte : Vec2 bsp = new Vec2(2,2); Alles was mit new erzeugt wird, wird auf dem Heap gespeichert Heap ist wie ein Haufen, nicht strukturiert wie ein Stack Heap kann während Laufzeit dynamisch wachsen
76
Heap Vec2* p = new Vec2(2,2); Heap
? Vec2* p = new Vec2(2,2); Zur Laufzeit wird nach einem freien Speicherplatz auf dem Heap angefragt In unserem Beispiel von einer Bytegröße von sizeOf(Vec2) Heap reserviert Speicherplatz und liefert Adresse zurück
77
Heap Vec2* p = new Vec2(2,2); Heap
Zur Laufzeit wird nach einem freien Speicherplatz auf dem Heap angefragt In unserem Beispiel von einer Bytegröße von sizeOf(Vec2) Heap reserviert Speicherplatz und liefert Adresse zurück Konstruktor wird aufgerufen und Objekt wird initialisiert
78
Heap Heap Stack p * Vec2* p = new Vec2(2,2);
Durch Zeiger haben wir Zugriff auf Objekt auf dem Heap p speichert die zurückgegebene Adresse auf dem Stack p ist vom Typ Vec2*, also ein Zeiger auf Vec2
79
Heap Vec2* p = new Vec2[n]; Heap Stack p *
Reserviert zusammenhängenden Speicherblock für n Objekte vom Typ Vec2 (funktioniert wie ein Array) n muss nicht zur Compilezeit bekannt sein Kann nur Default-Konstruktor von Vec2 aufrufen p hat nur Speicheradresse des ersten Objekts Programmierer muss die Größe des Arrays selber verwalten, denn der Zeiger kann dies nicht Heap (0,0) Stack p *
80
Heap Vec2* p = new Vec2[n]; Heap Stack p *
(0,0) Stack p * New erfordert immer ein delete, um den Speicherplatz wieder freizugeben Mit delete[ ] p geben wir den Speicher in unserem Beispielwieder frei ABER der Zeiger existiert nach wie vor Dangling Pointer : zeigt auf bereits freigegebenen Speicher
81
Heap Vec2* p = new Vec2[n]; Heap Stack p *
(0,0) Stack p * New erfordert immer ein delete, um den Speicherplatz wieder freizugeben Mit delete[ ] p geben wir den Speicher wieder frei ABER der Zeiger existiert nach wie vor Den Zeiger auf nullptr setzen so zeigt er auf nichts
82
Heap Vec2* p = new Vec2[n]; Heap Stack p *
(0,0) Stack p * (2,3) Vergessen wir das delete haben wir einen memory leak Der Zeiger p referenziert jetzt auf ein neues Objekt auf dem Heap Der Speicher von unserem Array kann nicht mehr freigegeben werden Erst beim Programmende wird der Speicher wieder freigegeben
83
Heap Vec2* p = new Vec2[n]; Heap Stack p *
Vergessen wir das delete haben wir einen memory leak Der Zeiger p referenziert jetzt auf ein neues Objekt auf dem Heap Der Speicher von unserem Array kann nicht mehr freigegeben werden Erst beim Programmende wird der Speicher wieder freigegeben Heap (0,0) Stack p * (2,3)
84
Fazit Stack und Heap Heap Stack hat festgelegte Größe,
Heap wächst dynamisch zur Laufzeit Stack ist selbstorganisierend und effizient, Heap erfordert dass der Programmierer an die Speicherfreigabe denkt Heap erfordert in C++ immer Zeiger Zugriff langsamer
85
Fazit Stack und Heap Stack hat festgelegte Größe,
Heap wächst dynamisch zur Laufzeit Stack ist selbstorganisierend und effizient, Heap erfordert dass der Programmierer an die Speicherfreigabe denkt Heap erfordert in C++ immer Zeiger Zugriff langsamer
86
Allokation und Konstruktion
Fazit Stack und Heap Allokation und Konstruktion Malloc() und placement new Was passiert hier? Obj* o = new Obj(1,2,3); Speicher für ein Objekt vom Typ Obj wird allokiert Konstruktor von Obj(1,2,3) wird aufgerufen
87
Allokation und Konstruktion
Malloc() und placement new Was passiert hier? Obj* o = new Obj(1,2,3); Speicher für ein Objekt vom Typ Obj wird allokiert Konstruktor von Obj(1,2,3) wird aufgerufen
88
Allokation und Konstruktion
Manchmal macht es Sinn diese beiden Schritte zu trennen Speicher für ein Objekt vom Typ Obj mit malloc() allokieren: Obj* speicher = static_cast<Obj*>(malloc(sizeOf(Obj))); 2. Konstruktoraufruf mit placement new: new(speicher) Obj(1,2,3);
89
Allokation und Konstruktion
Manchmal macht es Sinn diese beiden Schritte zu trennen Speicher für ein Objekt vom Typ Obj mit malloc() allokieren: Obj* speicher = static_cast<Obj*>(malloc(sizeOf(Obj))); 2. Konstruktoraufruf mit placement new: new(speicher) Obj(1,2,3);
90
Vergleich und Fazit
91
C++ und Java Fazit ÄHNLICHKEITEN VEREINFACHUNGEN IN JAVA
Primitive Datentypen Syntax: Kontrollstrukturen Klassen, Sichtbarkeit(public, private) Multiple Konstruktoren, this, new Packages in Java/namespaces in C++ Keine Pointer – nur Referenzen Keine Funktionen – static Methoden Keine globalen Variablen – public static Variablen nutzen Keine Destruktoren – garbage collection und finalize() Keine Header-Dateien – stattdessen Interfaces Keine Operatorenüberladung – nur Methodenüberladung Keine Mehrfachvererbung – dafür mehrfache Implementierung von Interfaces möglich
92
C++ und Java Fazit ÄHNLICHKEITEN VEREINFACHUNGEN IN JAVA
Primitive Datentypen Syntax: Kontrollstrukturen Klassen, Sichtbarkeit(public, private) Multiple Konstruktoren, this, new Packages in Java/namespaces in C++ VEREINFACHUNGEN IN JAVA Keine Pointer – nur Referenzen Keine Funktionen – static Methoden Keine globalen Variablen – public static Variablen nutzen Keine Destruktoren – garbage collection und finalize() Keine Header-Dateien – stattdessen Interfaces Keine Operatorenüberladung – nur Methodenüberladung Keine Mehrfachvererbung – dafür mehrfache Implementierung von Interfaces möglich C++ und Java Fazit
93
Danke für Eure Aufmerksamkeit
Ähnliche Präsentationen
© 2025 SlidePlayer.org Inc.
All rights reserved.