Programmieren in C / C++ Erste Schritte mit C++ Klassen und Objekte Hochschule Fulda – FB AI Sommersemester 2017 http://c.rz.hs-fulda.de Peter Klingebiel, HS Fulda, FB AI
C 1 C ist soweit schon bekannt: C ist eine imperative strukturierte Sprache Daten werden durch die Mühle von Funktionen gejagt, um dann zu einem Resultat (Ergebnisdaten) zu kommen Trennung der Daten von den Funktionen Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
C 2 einige wesentliche Vorteile von C: Laufzeiteffizienz bzgl. Codegröße / Geschwindigkeit Hardwarenähe, z.B. direkter Speicherzugriff erspart oft Assemblerprogrammierung „es gibt nichts, was man in C nicht programmieren kann“ C hat allerdings auch einige große Nachteile: Daten sind nicht gekapselt und vor Zugriffen geschützt schwache Typisierung trotz Libraries kein stringentes Modulkonzept schon bei einfachen Aufgabenstellungen, z.B. bei einfachen Eingaben, müssen oft Pointer verwendet werden Pointer erlauben ziemliche „Schweinereien“ Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
C++ 1 C++ ist objektorientiert Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
C++ 2 Objekte kapseln Daten (Attribute) und Operationen auf den Daten (Methoden, Memberfunktionen) Daten in C = Attribute in C++ Funktionen in C = Methoden / Memberfunktionen in C++ Objekte kommunizieren durch Senden und Empfangen von Nachrichten Objekte enstehen durch Instantiierung einer Klasse C++ aus C abgeleitet C++ ist objektorientierte Weiterentwicklung von C C++ enthält zu 100% C C-Code und C++-Code gleichzeitig verwendbar Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
C++ 3 Beispiel C #include <stdio.h> int main(void) { printf("Hello World!\n"); return 0; } Beispiel C++: #include <iostream> int main(void) { std::cout << " Hello World!" << std::endl; return 0; } Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
C++ 4 1971-73 Dennis Ritchie entwickelt bei den Bell Labs C für die Programmierung des neuen UNIX-Betriebssystems 1978 Ritchie/Kernighan: „The C Programming Language“ (die C-Bibel, dt. „Programmieren in C“) 1980-87 Bjarne Stroustrup entwickelt C++ bei AT&T, unter dem Namen C with Classes, ab 1983 C++ 1998 Standardisierung C++ (ISO/IEC 14882:1998) 2003 Verbesserung als C++03 (ISO/IEC 14882:2003) 2011 Neuer Standard C++11 (ISO/IEC 14882:2011) 2014 C++14 (ISO/IEC 14882.2014) neuere Standards C++17 und C++20 sind in Arbeit Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Unterschiede C – C++ 1 Dateiendungen (Header und Quelldateien) C: .h und .c C++: .h und .cpp C unterstützt strukturierte Programmierung Variable, Strukturen, Funktionen C++ unterstützt objektorientierte Programmierung Klassen, Objekte, Attribute, Methoden, Kapselung, Vererbung, Überladen, Polymorphie usw. C++ = C + objektorientierte Programmierung + einige nette Features Seit ISO-Standard C99 ist C etwas näher an C++ Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Unterschiede C – C++ 2 Variablen-Definitionen C (ältere Standards) nur zu Beginn eines Blocks { // Beginn eines Blocks int i; ... for(i = 0; i < n ; i++) ... } C++ (C auch ab C99) an fast beliebiger Stelle ... for(int i = 0; i < n ; i++) ... ... Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Unterschiede C – C++ 3 Typ-Konvertierung (type casts) C int xi; double xd; ... xd = (double) xi; ... C++ int xi; double xd; ... xd = (double) xi; // wie C xd = double(xi); // besser lesbar! ... Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Unterschiede C – C++ 4 Kommentare C: /* einzeiliger Kommentar */ /* mehrzeiliger Kommentar */ C++ (C auch C99 und später): // einzeiliger Kommentar /* mehrzeiliger Kommentar */ Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Unterschiede C – C++ 5 mehr und neue Datentypen, z.B. endlich ein Boolescher Datentyp C: #define TRUE 1 #define FALSE 0 ... int flag = TRUE; flag = FALSE; ... C++: bool flag = false; ... flag = true; Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Unterschiede C – C++ 6 Parameterübergabe bei Funktionsaufrufen C: call by value und call by address int a, b; ... funcv(a, b); // cbv funca(&a, &b); // in funca() Pointer! ... C++: call by value, call by address, call by reference int a, b; ... funcv(a, b); // cbv funca(&a, &b); // in funca() Pointer! funcr(a, b); // in funcr() Referenz! Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Unterschiede C – C++ 7 Polymorphie / Überladen von Funktionen C: unterschiedliche Namen für Funktionen mit gleicher Aufgabe, aber unterschiedlichen Parametern int summe_int(int, int); double summe_double(double, double); C++: Funktionen / Methoden können gleiche Namen verwenden, müssen allerdings unterschiedliche Parameterlisten haben (Signatur) int summe(int, int); double summe(double, double); double summe(double, int); double summe(int, double); ... Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Unterschiede C – C++ 8 Dynamische Speicherplatz-Allozierung C: mit Funktionen alloc() und free() #define N 16 int *f = (int *) malloc(N * sizeof(int)); f[0] = 4711; ... free(f); C++: mit Operatoren new und delete int n = 16; int *f = new int[n]; // Speicher reservieren f[0] = 4711; ... delete [] f; // Speicher freigeben Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Unterschiede C – C++ 9 … und natürlich auch noch C++: Objektorientierung Klassen / Objekte Datenkapselung private und öffentliche Attribute (Daten) private und öffentliche Methoden (Funktionen) Namensräume (Namespaces) Überladen von Operatoren (Polymorphie) Vererbung Templates … Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Ein- / Ausgabe 1 Objekte für Ein-/Ausgabe Streambibliothek #include <iostream> // ohne .h ! Standardobjekte cin, cout, cerr Ausgaben auf Standardausgabe cout std::cout << "Hallo Welt!\n"; std::cout << "Hallo Welt!" << std::endl; std::cout << "Pi hat den Wert" << 3.141; Vielfältige Formattierungen möglich Eingaben von Standardeingabe cin int i, j; std::cin >> i; // i einlesen std::cin >> i >> j; // i, j einlesen Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Namespaces 1 Namespaces definieren für Objekte und Daten eigene Namensräume Bsp: Ein-/Ausgabeobjekte sind im Namespace std definiert std::cout << "Hallo Welt!\n"; sie werden mit dem Scopeoperator :: zugegriffen namespace::element std::cout << "Hallo Welt!"; der Operator using macht einzelne Elemente oder ganze Namensräume bekannt using std::cout; // Element cout cout << "Hallo Welt!" << std::endl; using namespace std; // Namespace std cout << "Hallo Welt!" << endl; Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Namespaces 2 Namensräume müssen ausserhalb von Klassen oder Funktionen definiert werden namespace mydata { int i, j; } void proc() { using namespace std; cout << "Bitte 2 Integer eingeben: "; cin >> mydata.i >> mydata.j; cout << "i = " << mydata.i << endl; using namespace mydata; cout << "j= " << j << endl; } Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Überladen von Funktionen 1 Funktionen können überladen werden (Polymorphie), d.h. Funktionen gleichen Namens sind möglich sie müssen sich allerdings in der Parameterliste unterscheiden, d.h. Anzahl und / oder Typen der Parameter, d.h. in der sog. Signatur einer Funktion int sum(int, int); int sum(int, int, int); double sum(double, double); ... int i, j; double d; i = sum(1, 3); // Parameter: 2 Integer j = sum(1, 2, 3); // Parameter: 3 Integer d = sum(1.1, 2.2); // Parameter: 2 Double Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Referenzen 1 Referenzen sind interne Zeiger, die aber wie normale Variable behandelt werden using namespace std; int i = 1; // Variable int *ip = &i; // Pointer auf Variable int &ir = i; // Referenz auf Variable cout << i; // Ausgabe: 1 ir += 1; cout << ir; // Ausgabe: 2 cout << i; // Ausgabe: 2 *ip += 1; cout << *ip; // Ausgabe: 3 ip++; cout << *ip; // ??? Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Referenzen 2 Referenzen sind besonders bei Funktionen mit veränderbaren Parametern sinnvoll C (und auch C++): call by value void swap(int a, int b) { int t = a; // a, b im aufrufenden a = b; b = t; // Block unverändert! } C (und auch C++): call by address void swap(int *a, int *b) { int t = *a; // a, b im aufrufenden *a = *b; *b = t; // Block vertauscht! } Referenzen: call by address call by reference Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Referenzen 3 nur C++: call by reference void swap(int &a, int &b) { int t = a; a = b; b = t; } nach Aufruf sind die Parameter vertauscht, da Referenzen interne Pointer sind int a = 1; int b = 2; cout << a << " " << b; // Ausgabe: 1 2 swap(a, b); cout << a << " " << b; // Ausgabe: 2 1 Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Paradigmata 1 C++ ist eine Programmiersprache die mehreren Programmierparadigmata folgt ursprünglich entwickelt als C mit Klassen Prozedurale Programmierung Modulare Programmierung Strukturierte Programmierung Objektorientierte Programmierung Generische Programmierung Maschinennahe Programmierung Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Objektorientierung 1 Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
C-Structs 1 von C bekannt: Verbunddatentyp struct Deklaration des Datentyps struct io_reg { // io-register unsigned char ctrl; // steuerregister unsigned char data; // datenregister }; Definition von Variablen struct io_reg reg; // io-register struct io_reg *regp; // io-register-zeiger Zugriff auf die Komponenten ist fast überall möglich char d; regp = ® reg.ctrl |= IOREG_WRITE; regp->data = 0xAA; Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
C++-Klassen 1 Auch C++ kennt den Verbunddatentyp struct Deklaration des Datentyps wie in C struct io_reg { // io-register unsigned char ctrl; // steuerregister unsigned char data; // datenregister }; Definition von Variablen ohne Schlüsselwort struct io_reg reg; // io-register io_reg *regp; // io-register-zeiger struct-Deklaration ist eine Klassendeklaration class die Komponenten sind frei zugreifbar, d.h. sie sind public reg.ctrl |= IOREG_WRITE; regp->data = 0xAA; Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
C++-Klassen 2 Klassendefinition mit Schlüsselwort class Deklaration der Klasse class io_reg { // io-register unsigned char ctrl; // steuerregister unsigned char data; // datenregister }; Definition von Objekten und Zeigern darauf io_reg reg; // object io_reg *regp = new io_reg(); // zeiger die Memberattribute sind nicht frei zugreifbar, d.h. sie sind automatisch als private deklariert reg.ctrl |= IOREG_WRITE; // NICHT erlaubt! regp->data = 0xAA; // NICHT erlaubt! Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
C++-Klassen 3 die Attribute / Memberdaten sind gekapselt für den Zugriff auf die Attribute der Klasse sind somit Member-Methoden oder –Funktionen nötig typedef unsigned char byte; class io_reg { public: // oeffentlich nutzbar byte get_ctrl(void); void set_ctrl(byte b); byte get_data(void); void set_data(byte d); private: // nur in der Klasse nutzbar byte ctrl_; byte data_; }; Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
C++-Klassen 4 einfache Implementierung der Memberfunktionen byte io_reg::get_ctrl(void) { return ctrl_; } void io_reg::set_ctrl(byte b) { ctrl_ = b; } byte io_reg::get_data(void) { return data_; } void io_reg::set_data(byte d) { data_ = d; } Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
C++-Klassen 5 Verwendung der Klasse io_reg io_reg reg1; // object io_reg *reg2 = new io_reg(); // pointer ... reg1.set_ctrl(0x01); reg2->set_ctrl(0x04); reg1.set_data(0xAA); reg2->set_data(0xBB); ... byte d1 = reg1.get_data(); byte d2 = reg2->get_data(); ... delete reg2; Nutzung von Pointern mit new und delete sehr fehleranfällig! Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
C++-Klassen 6 besser: Konstruktoren und Destruktoren typedef unsigned char byte; class io_reg { public: // oeffentlich nutzbar io_reg(void); // konstruktor ~io_reg(void); // destruktor ... }; Implementierung von Konstruktor und Destruktor io_reg::io_reg(void) { ctrl_ = 0; data_ = 0; } ~io_reg(void) { } // nichts zu tun! Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
C++-Klassen 7 Trennung von Deklaration und Implementierung // io_reg.h – Headerfile #ifndef _IO_REG #define _IO_REG typedef unsigned char byte; class io_reg { public: io_reg(void); // konstruktor ~io_reg(void); // destruktor byte get_ctrl(); // lesen steuerregister void set_ctrl(byte b); // schreiben steuerregister byte get_data(); // lesen datenregister void set_data(byte d); // schreiben datenregister private: byte ctrl_; // dteuerregister byte data_; // datenregister }; #endif Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
C++-Klassen 8 // io_reg.cpp - Implementierung #include "io_reg.h„ io_reg::io_reg() { // konstruktor data_ = 0; ctrl_ = 0; } io_reg::~io_reg() // destruktor { // hier ist nichts zu tun } Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
C++-Klassen 9 byte io_reg::get_ctrl() // lesen steuerregister { return ctrl_; } void io_reg::set_ctrl(byte b) // schreiben steuerregister { ctrl_ = b; } byte io_reg::get_data() // lesen datenregister return data_; } void io_reg::set_data(byte d) // schreiben datenregister { data_ = d; } Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
C++-Klassen 10 Überladen von Methoden / Funktionen möglich z.B. mehrere Konstruktoren // io_reg.h io_reg(void); io_reg(byte); io_reg(byte, byte); ... // io_reg.cpp io_reg::io_reg(void){ // ohne parameter data_ = 0; ctrl_ = 0; } io_reg::io_reg(byte d) { // ein parameter data_ = d; ctrl_ = 0; } io_reg::io_reg(byte c, byte d) { // zwei parameter data_ = d; ctrl_ = c; } Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
C++-Klassen 11 Benutzung der Klassen mit den drei unterschiedlichen Konstruktoren // Definition der drei Register-Objekte io_reg reg1(); io_reg reg2(0xFF); io_reg reg3(0x07, 0xCC); ... // Setzen der undefinierten Register reg1.set_ctrl(0x01); reg1.set_data(0xAA); reg2.set_ctrl(0x10); ... // Auslesen der Datenregister byte d1 = reg1.get_data(); // -> 0xAA byte d2 = reg2.get_data(); // -> 0xFF byte d3 = reg3.get_data(); // -> 0xCC Destruktoren werden implizit aufgerufen Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Klassen und Objekte 1 Klassen beschreiben / definieren einen Datentyp Klassen belegen keinen Speicherplatz Objekte sind Instanzen von Klassen Objekte belegen den benötigten Speicherplatz, der zum Zeitpunkt des Instantiieren des Objekts angefordert / zur Verfügung gestellt wird Objekte werden angelegt / erzeugt mit Definition: io_reg reg1; Zeiger io_reg *reg2 = new io_reg; Konstruktor io_reg reg3(); Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI
Klassen und Objekte 2 Objekte leben (haben Speicherplatz, sind nutzbar) vom Zeitpunkt der Definition bis zum Ende des Blocks bzw. des Programms Objekte werden dynamisch erzeugt und sollten entfernt werden, wenn sie nicht mehr benötigt werden, was i.d.R. automatisch passiert Instantiierung von Objekten sollte mit Konstruktoren erfolgen, da diese einfach zu handhaben sind und die Verwaltung bei C++ bzw. im Laufzeitsystem erfolgt Pointer mit new und delete sind sehr fehleranfällig und vor allem auch nicht notwendig! Programmieren in C / C++ - Peter Klingebiel - HS Fulda - FB AI