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