Grundlagen der Informatik 13. Sonstiges
Transcription
Grundlagen der Informatik 13. Sonstiges
Grundlagen der Informatik 13. Sonstiges Bits und Bytes Fehlerbehandlung Operatorfunktionen Konstruktoren&Destruktoren Klassen Grundlagen der Informatik (Alex Rempel) 1 Grundlagen der Informatik Bits und Bytes ● Übertragung unter Geräten oft in Bits&Bytes ● Alte Protokolle immer noch oft genutzt (z.B. MODBUS) – normalerweise serielle Kommunikation ● – Informationen werden in Bitarrays übertragen ● ● sparsame Übetragung nötig (Bandbreite, Kabellänge u.a. Faktoren) XML oder andere beschreibende Informationsprotokolle kommen da überhaupt nicht in Frage Beispiel: Leckwarnsystem – Eine Zentrale hat bis zu 64 Kabeln je 16m ● Kabelbruch und Leck im x. Kabelmeter werden erkannt ● Ein PC soll seriell alles min. 10 Mal pro Sekunde abfragen können Grundlagen der Informatik (Alex Rempel) 2 Grundlagen der Informatik Bits und Bytes ● Leckwarnsystem: naive Implementierung ● Annahme: RS-232 seriell, 9600 Baud (hier auch bps) #include <iostream> using namespace std; 1 Cable = 3B, 64x = 192B, KB/s = 2.92969 const unsigned int uiCABLES = 64; const unsigned long ulUPDATETICKS = 100; // ms struct Cable { bool bBreak; bool bLeak; unsigned char ucMeter; }; // 1 Byte // 1 Byte // 1 Byte 9600 bps = 1200 Bps => 1,17 KBps möglich, d.h. 2.93 KBps zu viel void main() { Cable deviceCables[uiCABLES]; double dByteRate = sizeof(deviceCables)*1000.0/ulUPDATETICKS; cout << "1 Cable = " << sizeof(Cable) << "B, " << "64x = " << sizeof(deviceCables) << "B, " << "KB/s = " << dByteRate/1024 << endl; } Grundlagen der Informatik (Alex Rempel) 3 Grundlagen der Informatik Bits und Bytes ● Leckwarnsystem: bessere Implementierung ● Annahme: RS-232 seriell, 19200 Baud (hier auch bps) #include <iostream> using namespace std; 1 Cable = 1B, 64x = 64B, KB/s = 0.976563 const unsigned int uiCABLES = 64; const unsigned long ulUPDATETICKS = 100; // ms struct Cable { bool bBreak bool bLeak unsigned char unsigned char ucMeter }; : : : : 1; 1; 2; 4; // // // // 1 1 2 4 bit bit empty bits bits void main() { Cable deviceCables[uiCABLES]; double dByteRate = sizeof(deviceCables)*1000.0/ulUPDATETICKS; cout << "1 Cable = " << sizeof(Cable) << "B, " << "64x = " << sizeof(deviceCables) << "B, " << "KB/s = " << dByteRate/1024 << endl; } Grundlagen der Informatik (Alex Rempel) 9600 bps = 1200 Bps => 1,17 KBps möglich, d.h. 0,98 KBps sind OK Doppelpunkt gibt Bits vor, Gesamtgröße sollte sich an Bytes orientieren 4 Grundlagen der Informatik Bits und Bytes ● Leckwarnsystem: jetzt 1B, wie richtig übertragen? ● Beispiel: Kabel mit Leck ab dem 5.Meter als Byte 00011110 #include <iostream> using namespace std; void printBinary(unsigned char ucByte) { for (int i=7; i >= 0; --i) cout << ( ucByte&(1<<i) ? "1" : "0" ); } Aber 01000101 erwartet! struct Cable { bool bBreak bool bLeak unsigned char unsigned char ucMeter }; Leere Bits sind zufällig aufgefüllt (hier mit 11)! : : : : 1; 1; 2; 4; // // // // 1 1 2 4 bit bit empty bits bits Halfbyte mit Leckbit ist nun LoHalfbyte UND gedreht! void main() { Cable c; c.bBreak = false; c.bLeak = true; c.ucMeter = 1; printBinary(*(unsigned char*)(&c)); cout << endl; } Grundlagen der Informatik (Alex Rempel) Meterbits korrekt, aber im HiHalfbyte! 5 Grundlagen der Informatik Bits und Bytes ● Leckwarnsystem: Kabelleck ab dem 5.Meter als Byte #include <iostream> using namespace std; 00010010 void printBinary(unsigned char ucByte) { for (int i=7; i >= 0; --i) cout << ( ucByte&(1<<i) ? "1" : "0" ); } struct Cable { bool bBreak bool bLeak unsigned char ucEmpty unsigned char ucMeter }; : : : : 1; 1; 2; 4; // // // // 1 1 2 4 bit bit empty bits bits Leere Bits korrigiert, aber immer noch Einiges zu drehen... Besser gleich Funktionen bereitstellen... void main() { Cable c; c.bBreak = false; c.bLeak = true; c.ucMeter = 1; c.ucEmpty = 0; printBinary(*(unsigned char*)(&c)); cout << endl; } Grundlagen der Informatik (Alex Rempel) 6 Grundlagen der Informatik Bits und Bytes ● Leckwarnsystem: Kabelleck ab dem 5.Meter als Byte #include "cable.h" #include <iostream> using namespace std; main.cpp void printBinary(unsigned char ucByte) { for (int i=7; i >= 0; --i) cout << ( ucByte&(1<<i) ? "1" : "0" ); } void printCable(Cable& c) { if (c.bBreak) cout << "\nCable break\n"; else if (c.bLeak) cout << "\nCable leak in " << (int)c.ucMeter << ".m\n"; else cout << "\nCable OK\n"; } void main() { Cable c; c.fromByte(0x41); // =01000001 printBinary(c.toByte()); printCable(c); 01000001 cout << endl; } Cable leak in 1.m #ifndef _CABLE_H_ cable.h #define _CABLE_H_ struct Cable { bool bBreak : 1; bool bLeak : 1; unsigned char : 2; unsigned char ucMeter : 4; unsigned char toByte(); void fromByte(unsigned char ucByte); }; #endif #include "cable.h" cable.cpp unsigned char Cable::toByte() { unsigned char ucByte = 0; if (bBreak) ucByte |= (1<<7); // 1000 0000 else if (bLeak) ucByte |= (1<<6) + ucMeter; // 0100 xxxx return ucByte; } void Cable::fromByte( unsigned char ucByte ) { bBreak = ( ucByte&(1<<7) ) > 0; bLeak = ( ucByte&(1<<6) ) > 0; ucMeter = ucByte&0xF; } Grundlagen der Informatik (Alex Rempel) 7 Grundlagen der Informatik Bits und Bytes ● Gerade für Elektrotechnik ist also Folgendes wichtig: ● ● Bitoperatoren – & and: 1011 & 0101 = 0001 (0 Bits der Maske löschen) – | or: 1011 | 0101 = 1111 (1 Bits der Maske setzen) – ^ xor: 1011 | 0101 = 1110 (1 Bits der Maske invertieren) – ~ not: ~1011 = 0100 (alles invertieren) – >> rshift: 1011 >> 2 = 0010 (rechts schieben, mit 0 auffüllen) – << lshift: 1011 << 2 = 1100 (links schieben, mit 0 auffüllen) Bitfelder in Strukturen – Angabe der Komponentenbitgröße mit 'component : bits;' – Gesamte Struktur sollte ein Vielfaches eines Bytes sein Grundlagen der Informatik (Alex Rempel) 8 Grundlagen der Informatik Fehlerbehandlung ● Möglichkeiten der Fehlerbehandlung ● Direkter Programmabbruch ● Nutzung des Rückgabewertes als Fehlerangabe ● Setzen eines Flags und separat von Fehlerdetails dazu ● Ausnahmebehandlung (Exceptions) – Exceptions werden geworfen und gefangen ● Aufgerufene Funktion wirft eine Exception ● Aufgerufene Funktion kann die Exception fangen ● Aufrufende Funktion kann die Exception fangen Grundlagen der Informatik (Alex Rempel) 9 Grundlagen der Informatik Fehlerbehandlung ● Direkter Programmabbruch ● 4/5=0.8 4/0=0 Nutzung von Assertions – Achtung: in Release ignoriert! Release Debug 4/5=0.8 Assertion failed: b && “division by zero!“ ... #include <assert.h> // in debug mode only #include <iostream> using namespace std; double divide(double a, double b) { assert(b != 0 && "division by zero!"); return b ? a/b : 0; } void main() { cout << "4/5=" << divide(4,5) << endl; cout << "4/0=" << divide(4,0) << endl; } Grundlagen der Informatik (Alex Rempel) 10 Grundlagen der Informatik Fehlerbehandlung ● Nutzung des Rückgabewertes ● Wahrheitswert für geklappt / nicht geklappt 1 2 3 4 5 some error! #include <iostream> using namespace std; bool printArray(int* pFirst, int* pLast) { if (!pFirst || !pLast || pFirst > pLast) return false; while (pFirst <= pLast) cout << *pFirst++ << " "; cout << endl; return true; } void main() { int ii[5] = {1,2,3,4,5}; if (!printArray(ii,ii+4)) cout << "some error!" << endl; if (!printArray(ii,NULL)) cout << "some error!" << endl; } Grundlagen der Informatik (Alex Rempel) 11 Grundlagen der Informatik Fehlerbehandlung ● Nutzung des Rückgabewertes ● int Wert für 0=OK, sonst Fehlerdifferenzierung #include <iostream> using namespace std; 1 2 3 4 5 error: -1 error: -2 int printArray(int* pFirst, int* pLast) { if (!pFirst || !pLast) return -1; else if (pFirst > pLast) return -2; while (pFirst <= pLast) cout << *pFirst++ << " "; cout << endl; return 0; } void main() { int ii[5] = {1,2,3,4,5}; int iError = printArray(ii,ii+4); if (iError) cout << "error: " << iError << endl; iError = printArray(ii,NULL); if (iError) cout << "error: " << iError << endl; iError = printArray(ii+4,ii); if (iError) cout << "error: " << iError << endl; } Grundlagen der Informatik (Alex Rempel) 12 Grundlagen der Informatik Fehlerbehandlung ● Fehlerflag #include "State.h" #include <iostream> using namespace std; Nächste Folie 1 2 3 4 5 NULL pointer start pointer after end pointer State g_State; void printArray(int* pFirst, int* pLast) { if (!pFirst || !pLast) g_State.errorFlag = ENULL; else if (pFirst > pLast) g_State.errorFlag = EBGNAFTEREND; else { while (pFirst <= pLast) cout << *pFirst++ << " "; cout << endl; } } void main() { int ii[5] = {1,2,3,4,5}; g_State.clearError(); printArray(ii,ii+4); if (g_State.isError()) cout << g_State.getErrorDescription() << endl; g_State.clearError(); printArray(ii,NULL); if (g_State.isError()) cout << g_State.getErrorDescription() << endl; g_State.clearError(); printArray(ii+4,ii); if (g_State.isError()) cout << g_State.getErrorDescription() << endl; } Grundlagen der Informatik (Alex Rempel) 13 Grundlagen der Informatik Fehlerbehandlung ● Fehlerflag State.h #ifndef _STATE_H_ #define _STATE_H_ 1 2 3 4 5 NULL pointer start pointer after end pointer enum eError { EOK, ENULL, EBGNAFTEREND, ECOUNT }; const char cError[ECOUNT][128] = { "no error", "NULL pointer", "start pointer after end pointer" }; struct State { eError errorFlag; bool isError() void clearError() const char* getErrorDescription() }; { return errorFlag != EOK; } { errorFlag = EOK; } { return cError[errorFlag]; } #endif Grundlagen der Informatik (Alex Rempel) 14 Grundlagen der Informatik Fehlerbehandlung ● Ausnahmebehandlung #include <iostream> using namespace std; void printArray(int* pFirst, int* pLast) { if (!pFirst) throw "first pointer is NULL!"; else if (!pLast) throw 3; else if (pFirst > pLast) throw 4.5; else while (pFirst <= pLast) cout << *pFirst++ << " "; 1 2 3 4 5 cout << endl; } void main() { int ii[5] = {1,2,3,4,5}; try { printArray(ii,ii+4); } catch(const char* c) { cout << "error: " << c << endl; } catch(int i) { cout << "error: " << i << endl; } catch(...) { cout << "some error!" << endl; } } Grundlagen der Informatik (Alex Rempel) 15 Grundlagen der Informatik Fehlerbehandlung ● Ausnahmebehandlung #include <iostream> using namespace std; void printArray(int* pFirst, int* pLast) { if (!pFirst) throw "first pointer is NULL!"; else if (!pLast) throw 3; else if (pFirst > pLast) throw 4.5; else while (pFirst <= pLast) cout << *pFirst++ << " "; cout << endl; } void main() { int ii[5] = {1,2,3,4,5}; try { printArray(NULL,ii+4); } catch(const char* c) { cout << "error: " << c << endl; } catch(int i) { cout << "error: " << i << endl; } catch(...) { cout << "some error!" << endl; } } error: first pointer is NULL! Grundlagen der Informatik (Alex Rempel) 16 Grundlagen der Informatik Fehlerbehandlung ● Ausnahmebehandlung #include <iostream> using namespace std; void printArray(int* pFirst, int* pLast) { if (!pFirst) throw "first pointer is NULL!"; else if (!pLast) throw 3; else if (pFirst > pLast) throw 4.5; else while (pFirst <= pLast) cout << *pFirst++ << " "; cout << endl; } void main() { int ii[5] = {1,2,3,4,5}; try { printArray(ii,NULL); } catch(const char* c) { cout << "error: " << c << endl; } catch(int i) { cout << "error: " << i << endl; } catch(...) { cout << "some error!" << endl; } } error: 3 Grundlagen der Informatik (Alex Rempel) 17 Grundlagen der Informatik Fehlerbehandlung ● Ausnahmebehandlung #include <iostream> using namespace std; void printArray(int* pFirst, int* pLast) { if (!pFirst) throw "first pointer is NULL!"; else if (!pLast) throw 3; else if (pFirst > pLast) throw 4.5; else while (pFirst <= pLast) cout << *pFirst++ << " "; cout << endl; } void main() { int ii[5] = {1,2,3,4,5}; try { printArray(ii+4,ii); } catch(const char* c) { cout << "error: " << c << endl; } catch(int i) { cout << "error: " << i << endl; } catch(...) { cout << "some error!" << endl; } } some error! Grundlagen der Informatik (Alex Rempel) 18 Grundlagen der Informatik Fehlerbehandlung ● Ausnahmebehandlung Debug und Release #include <iostream> using namespace std; void printArray(int* pFirst, int* pLast) { if (!pFirst) throw "first pointer is NULL!"; else if (!pLast) throw 3; else if (pFirst > pLast) throw 4.5; else while (pFirst <= pLast) cout << *pFirst++ << " "; cout << endl; } Zwingt den Entwickler zur Behandlung der Ausnahmen void main() { int ii[5] = {1,2,3,4,5}; printArray(NULL,ii+4); } Grundlagen der Informatik (Alex Rempel) 19 Grundlagen der Informatik Operatorfunktionen ● Für einfache Datentypen sind Operatoren realisiert ● ● Beispiel: int a=0,b=3; a = a+b; Für Strukturen ist nur der Zuweisungsoperator da ● Weitere Operatoren können als Funktionen implementiert werden – Dabei kann jeder Operator beliebige interpretiert werden, je nachdem was sich der Entwickler dafür ausgedacht hat Grundlagen der Informatik (Alex Rempel) 20 Grundlagen der Informatik Operatorfunktionen ● Beispiel: 2 Vektoren addieren a + b = c = { 0.8 ; 16.44 } #include <iostream> using namespace std; struct Vector2d { double x; double y; }; Schlechte bzw. Lösung void main() { keine Vector2d a,b,c; a.x = 1.2; a.y = 2.54; b.x = -0.4; b.y = 13.9; c.x = a.x + b.x; c.y = a.y + b.y; cout << "a + b = c = { " << c.x << " ; " << c.y << " } " << endl; } Grundlagen der Informatik (Alex Rempel) 21 Grundlagen der Informatik Operatorfunktionen ● Beispiel: 2 Vektoren addieren a + b = c = { 0.8 ; 16.44 } #include <iostream> using namespace std; struct Vector2d { double x; double y; }; Vector2d add(const Vector2d& a, const Vector2d& b) { Vector2d v; v.x = a.x + b.x; v.y = a.y + b.y; return v; } Lösung gekapselt, aber der Aufruf ist nicht intuitiv void main() { Vector2d a,b; a.x = 1.2; a.y = 2.54; b.x = -0.4; b.y = 13.9; Vector2d c = add(a,b); cout << "a + b = c = { " << c.x << " ; " << c.y << " } " << endl; } Grundlagen der Informatik (Alex Rempel) 22 Grundlagen der Informatik Operatorfunktionen ● Beispiel: 2 Vektoren addieren a + b = c = { 0.8 ; 16.44 } #include <iostream> using namespace std; struct Vector2d { double x; double y; }; Vector2d operator+(const Vector2d& a, const Vector2d& b) { Vector2d v; v.x = a.x + b.x; v.y = a.y + b.y; return v; } Lösung gekapselt, Aufruf ist intuitiv void main() { Vector2d a,b; a.x = 1.2; a.y = 2.54; b.x = -0.4; b.y = 13.9; Vector2d c = a+b; cout << "a + b = c = { " << c.x << " ; " << c.y << " } " << endl; } Grundlagen der Informatik (Alex Rempel) 23 Grundlagen der Informatik Operatorfunktionen ● Beispiel: 2 Vektoren addieren a -= b = c = { 1.6 ; -11.36 } #include <iostream> using namespace std; struct Vector2d { double x; double y; void operator-=(const Vector2d& other) { x -= other.x; y -= other.y; } }; Auch in Strukturen möglich und sinnvoll void main() { Vector2d a,b; a.x = 1.2; a.y = 2.54; b.x = -0.4; b.y = 13.9; a -= b; cout << "a -= b = a = { " << a.x << " ; " << a.y << " } " << endl; } Grundlagen der Informatik (Alex Rempel) 24 Grundlagen der Informatik Konstruktoren&Destruktoren ● ● Initialisierung von Strukturen ist umständlich ● Es muss das Strukturobjekt erstellt werden ● Danach müssen alle Komponenten initialisiert werden Konstruktor ● Konstruktoren ermöglichen automatische Initialisierung – ● Werden beim Erstellen eines Strukturobjekts aufgerufen Destruktor ● struct structname { structname(); // constructor } struct structname { ~structname(); // destructor } Destruktoren ermöglichen automatisches Aufräumen – Werden vor dem Freigeben des Strukturobjekts aufgerufen Grundlagen der Informatik (Alex Rempel) 25 Grundlagen der Informatik Konstruktoren&Destruktoren ● Konstruktoren #include <iostream> using namespace std; a = { 0 ; 0 } b = { 0.5 ; -2.4 } c = { 0.5 ; -2.4 } struct Vector2d { Vector2d() // standard constructor Alternativinitialisierung von Komponenten :x(0.0),y(0.0) {}; vor dem Funktionsblock des Konstruktors Vector2d(double x, double y) Innerhalb von Strukturfunktionen ist { this->x = x; this->y = y; }; Vector2d(const Vector2d& v) // copy constructor this immer der Zeiger auf sich selbst { x = v.x; y = v.y; }; double x; double y; }; void main() { Vector2d a; Vector2d b(0.5,-2.4); Vector2d c(b); cout << "a = { " << a.x << " ; " << a.y << " } " << endl; cout << "b = { " << b.x << " ; " << b.y << " } " << endl; cout << "c = { " << c.x << " ; " << c.y << " } " << endl; } Grundlagen der Informatik (Alex Rempel) 26 Grundlagen der Informatik Konstruktoren&Destruktoren ● Destruktoren #ifndef _VECTOR2D_H_ #define _VECTOR2D_H_ #include "Vector2d.h" #include <iostream> struct Vector2d { Vector2d(); ~Vector2d(); double* x; double* y; }; Vector2d::Vector2d(){ x = new double(0); y = new double(0); }; #endif Vector2d.h Vector2d.cpp Vector2d::~Vector2d() { std::cout << "Destroying (" << *x << ";" << *y << ")\n"; delete x; delete y; }; #include "Vector2d.h" main.cpp #include <iostream> using namespace std; void main() { Vector2d fromStack; fromStack.x = 0.1; fromStack.y = 0.2; Vector2d* fromHeap = new Vector2d(); fromHeap->x = 0.3; fromHeap->y = 0.4; delete fromHeap; // fromHeap destructor called } // fromStack destructor called Destroying (0.3;0.4) Destroying (0.1;0.2) Grundlagen der Informatik (Alex Rempel) 27 Grundlagen der Informatik Klassen ● Klassen dienen der Objektorientierung und bieten ● Geheimnisprinzip (private/protected/public Member) – ● Kapselung von Membern (Komponenten und Methoden) – ● ● Zugriffsrechte auf Member Statische Member (pro Klasse statt pro Objekt) Vererbungshierarchien durch Ableitungen – Polymorphie (dynamische Vererbungserkennung) – Abstrakte Klassen (voll und teilweise) Fakt: Strukturen sind in C++ Klassen! ● Default: in Strukturen Member public, in Klassen private Grundlagen der Informatik (Alex Rempel) 28 Grundlagen der Informatik Klassen ● Geheimnisprinzip: per Default alle Member private ● private: nur Klasse selbst hat Zugriff auf die Komponente #include <iostream> #include <string> using namespace std; class Animal { std::string strName; bool bDangerous; Animal():strName("???"),bDangerous(true){}; }; void main() { Animal anml; cout << anml.strName << endl; } error C2248: „Animal::Animal“: Kein Zugriff auf private Member, dessen Deklaration in der Animal-Klasse erfolgte. Alle Komponenten sind per Default private, d.h. von außerhalb der Klasse zugriffsgeschützt Der Konstruktor ist private, somit kann kein Objekt der Klasse erstellt werden Grundlagen der Informatik (Alex Rempel) 29 Grundlagen der Informatik Klassen ● Geheimnisprinzip: per Default alle Member private ● public: die Komponente ist von außerhalb greifbar – Schlecht: für bessere Kapselung sollten Variablen private sein ● Auf die private Variablen sollte es public get/set Methoden geben #include <iostream> #include <string> using namespace std; ??? class Animal { public: string strName; bool bDangerous; Animal():strName("???"),bDangerous(true){}; }; Ab dieser Stelle sind alle folgenden Member public, bis ein anderer Modifikator kommt void main() { Animal anml; cout << anml.strName << endl; } Grundlagen der Informatik (Alex Rempel) 30 Grundlagen der Informatik Klassen ● Geheimnisprinzip: sinnvolle Verwendung ● protected – kommt später (erst bei Vererbung) Mouse #include <iostream> #include <string> using namespace std; class Animal { Variablen selbst sind vor private: Zugriff geschützt string strName; bool bDangerous; public: Zugriffsmethoden Animal():strName("???"),bDangerous(true){}; darauf sind offen string getName() { return strName; }; void setName(string& strName) { this->strName = strName; }; void setName(const char* strName) { this->strName = strName; }; bool isDangerous() { return bDangerous; }; void setDangerous(bool bDangerous) { this->bDangerous = bDangerous; }; }; void main() { Animal anml; anml.setName("Mouse"); cout << anml.getName() << endl; } Grundlagen der Informatik (Alex Rempel) 31 Grundlagen der Informatik Klassen ● Vererbungsprinzip: Spezialisierung Animal erbt alles von Creature und fügt eigene Spezialisierungen hinzu Creature: Ghost Animal: Lion is dangerous #include "Animal.h" #include <iostream> #include <string> using namespace std; main.cpp void main() { Creature c; c.strName = "Ghost"; Animal a; a.strName = "Lion"; cout << c.getName() << endl; cout << a.getName() << endl; } #ifndef _ANIMAL_H_ #define _ANIMAL_H_ #include <string> Animal.h class Creature { public: std::string strName; Creature():strName("???"){}; std::string getName() { return "Creature: " + strName; }; }; class Animal : public Creature { public: bool bDangerous; Animal():bDangerous(true),Creature(){}; std::string getName() { return "Animal: " + strName + " is " + (bDangerous ? "" : "not ") + "dangerous"; }; }; #endif Grundlagen der Informatik (Alex Rempel) 32 Grundlagen der Informatik Klassen ● Vererbungsprinzip: Mehrfachvererbung Eine Klasse kann von mehreren anderen Klassen erben void main() { AB ab; } AB.h class A { public: A(){ std::cout << "Constructor A \n"; }; ~A(){ std::cout << "Destructor A \n"; }; }; class B { public: B(){ std::cout << "Constructor B \n"; }; ~B(){ std::cout << "Destructor B \n"; }; }; Constructor A Constructor B Constructor AB Destructor AB Destructor B Destructor A #include "AB.h" #ifndef _AB_H_ #define _AB_H_ #include <iostream> main.cpp class AB : public A, public B { public: AB(){ std::cout << "Constructor AB \n"; }; ~AB(){ std::cout << "Destructor AB \n"; }; }; #endif Grundlagen der Informatik (Alex Rempel) 33 Grundlagen der Informatik Klassen ● Vererbungsprinzip: Polymorphie #ifndef _ABC_H_ #define _ABC_H_ #include <iostream> Virtuelle Methoden werden automatisch je nach dem dynamischen Heap-Typ ausgewählt Me be new A! Me be new B! Me be new C! Der Zeiger bleibt die ganze Zeit über ein Zeiger auf die Basisklasse #include "ABC.h" main.cpp void main() { A* p = NULL; p = new A(); p->print(); delete p; p = new B(); p->print(); delete p; p = new C(); p->print(); delete p; } class A { // class public: virtual ~A(){}; virtual void print() { std::cout << "Me be }; class B : public A { // class public: virtual ~B(){}; virtual void print() { std::cout << "Me be }; class C : public B { // class public: virtual ~C(){}; virtual void print() { std::cout << "Me be }; #endif Grundlagen der Informatik (Alex Rempel) ABC.h A new A!\n"; }; B new B!\n"; }; C new C!\n"; }; 34 Grundlagen der Informatik Klassen ● Vererbungsprinzip: Virtuelle Methoden #ifndef _ABC_H_ #define _ABC_H_ #include <iostream> Virtuelle Methoden der Basisklassen können explizit ausgeführt werden class A { public: virtual ~A(){}; virtual void print() { std::cout << "Me be new A!\n"; }; }; Fehlt eine virtuelle Methode, wird die der Basisklasse ausgeführt Me be new A! Me be new A! Me be new A! #include "ABC.h" ABC.h main.cpp void main() { A* p = NULL; p = new A(); p->print(); delete p; p = new B(); p->print(); delete p; p = new C(); p->print(); delete p; } class B : public A { public: virtual ~B(){}; virtual void print() { A::print(); }; }; class C : public B { public: virtual ~C(){}; // no print(), B::print() is called }; #endif Grundlagen der Informatik (Alex Rempel) 35