Jetzt: Polymorphie/Polymorphismus
â Vielgestaltigkeit
#include <iostream>
using std::cout, std::endl;
class Base {
public:
void print() { cout << "Base" << endl; }
};
class Child: public Base {
public:
void print() { cout << "Child" << endl; }
};
int main() {
Base * b = new Child();
b->print();
delete b;
}
ausgabe() So geht es natĂŒrlich noch nicht!
Methoden können dynamisch gebunden werden
â Auswahl zur Laufzeit
SchlĂŒsselwort virtual in C++
Virtuelle Methoden können ĂŒberschrieben werden
â Die Auswahl erfolgt nun fĂŒr diese Methode dynamisch
#include <iostream>
using std::cout, std::endl;
class Frucht {
public:
virtual void ausgabe() {
cout << "F" << endl;
};
virtual ~Frucht() {};
};
class Obst: public Frucht {
public:
void ausgabe() {
cout << "O" << endl;
};
};
class Suedfrucht: public Obst {
public:
void ausgabe() {
cout << "SF" << endl;
};
};
int main() {
Frucht * frucht = new Frucht();
Frucht * obst = new Obst();
Frucht * suedfrucht = new Suedfrucht();
frucht->ausgabe();
obst->ausgabe();
suedfrucht->ausgabe();
delete frucht;
delete obst;
delete suedfrucht;
}
virtualvirtual#include <iostream>
using std::cout, std::endl;
class Base {
public:
virtual ~Base() {
cout << "Base" << endl;
}
};
class Child : public Base {
public:
~Child() {
cout << "Child" << endl;
}
};
int main() {
Base * b = new Child();
delete b;
}
overrideoverride explizitvoid print() override;finaloverride: SchlĂŒsselwort finalDiamond-Shape
TatsÀchliche Vererbungshierarchie
Baseprint() verwendet werden soll â Error
Mother::print(); // Dies?Father::print(); // Oder dies?Base ableiten
# include <iostream>
using std::cout, std::endl;
class Base {
public:
virtual void print() {
cout << "Base" << endl;
}
};
class Mother: virtual public Base {};
class Father: virtual public Base {};
class Child : public Mother, public Father {};
int main() {
Child c;
c.print(); // Ok mit virtueller Ableitung
}
virtual void print() = 0; // = 0 deklariert Funktion als pure# include <iostream>
using std::cout, std::endl;
class Form {
public:
virtual void print_area() = 0;
};
class Quadrat : public Form {
double x_;
double y_;
public:
Quadrat(double x, double y) : x_(x), y_(y) {}
void print_area() override {
cout << x_ * y_ << endl;
}
};
class Kreis : public Form {
double r_;
public:
Kreis(double radius) : r_(radius) {}
void print_area() override {
cout << r_ * 3.14 << endl;
}
};
int main() {
Form * quadrat = new Quadrat(2.5, 3.0);
Form * kreis = new Kreis(1.0);
quadrat->print_area();
kreis->print_area();
}
AbschlieĂend ein Blick hinter die Kulissen: Vtables
Vtables steht fĂŒr Virtuelle Tabellen
Jede Klasse mit virtuellen Funktionen bekommt eine zusÀtzliche Member-Variable
â Zeiger auf Tabelle mit Funktionen
Einfache Umsetzung
__vptrZur Laufzeit: Nachschlagen in der Tabelle
Zeiger in Tabelle verweist auf konkrete Implementierung in Klasse
Mehrkosten: Einige Dereferenzierungen von Zeigern
â Ziemlich schnell
clang++ -Xclang -fdump-vtable-layouts vtable.cpp#include <iostream>
using std::cout, std::endl;
class Frucht {
public:
virtual void ausgabe() { cout << "F" << endl; }
};
class Obst : public Frucht {
public:
void ausgabe() override { cout << "O" << endl; }
};
class Suedfrucht : public Obst {
public:
void ausgabe() override { cout << "SF" << endl; }
};
int main() {
Frucht f;
Obst o;
Suedfrucht sf;
f.ausgabe();
o.ausgabe();
sf.ausgabe();
}Vtable for 'Frucht' (3 entries).
0 | offset_to_top (0)
1 | Frucht RTTI
-- (Frucht, 0) vtable address --
2 | void Frucht::ausgabe()
VTable indices for 'Frucht' (1 entries).
0 | void Frucht::ausgabe()
Vtable for 'Obst' (3 entries).
0 | offset_to_top (0)
1 | Obst RTTI
-- (Frucht, 0) vtable address --
-- (Obst, 0) vtable address --
2 | void Obst::ausgabe()
VTable indices for 'Obst' (1 entries).
0 | void Obst::ausgabe()
Vtable for 'Suedfrucht' (3 entries).
0 | offset_to_top (0)
1 | Suedfrucht RTTI
-- (Frucht, 0) vtable address --
-- (Obst, 0) vtable address --
-- (Suedfrucht, 0) vtable address --
2 | void Suedfrucht::ausgabe()
VTable indices for 'Suedfrucht' (1 entries).
0 | void Suedfrucht::ausgabe()
Bisher nicht besprochen: Reflexion
Eigenschaft vieler OOP-fÀhigen Programmiersprachen, z. B. Java
Bezeichnet FĂ€higkeit, Informationen ĂŒber sich selbst abzurufen
â z.B. eigener Typ oder Member inkl. Namen
Modellierung der RealitĂ€t mittels Klassenhierarchie â siehe Frucht-Beispiel
Vorteile von Polymorphie
Realisierung von Polymorphie mit SchlĂŒsselword virtual
Erzwingen der Implementierung mittels abstrakter Klassen
â Methoden als pure virtual definieren
Implementierung mittels vtables