B
class Koerper
{
public:
// Eine rein virtuelle Methode.
// Wir legen hier eine Schnittstelle fest, mit der man
// für (const) Koerper die Fläche bestimmen kann. Die Berechnung
// ist für jeden Körper anders, daher gibts hier keine
// Implementierung. Die Methode ist const, da jeder Körper seine
// Fläche berechnen können soll, auch wenn er konstant ist.
// Da diese Methode keine Implementierung hat, kann ich keine Instanz
// von Koerper anlegen.
virtual double Flaeche() const = 0;
// Ein virtueller Destruktor
virtual ~Koerper(){}
};
class Dreieck : public Koerper // häm.. ein Dreieck ist eni Körper? naja von mir aus
{
public:
Dreieck(double laenge, double hoehe);
// Hier implementiert Dreieck die Schnittstelle Flaeche.
double Flaeche()
{
// grundseite x hoehe / 2;
}
};
void PrintFlaeche(const Koerper& k)
{
std::cout << k.Flaeche();
}
int main()
{
// Koerper k; // das geht nicht. Koerper ist abstrakt.
Dreieck d(3.14, 1.0); // das geht :)
PrintFlaeche(d); // das geht
PrintFlaeche(Dreieck(42.314, 0.1)); // das geht auch
Koerper * k = new Dreieck(1.0, 1.0);
PrintFlaeche(*k);
delete k; // Ruft den Destruktor von Dreieck auf!
// weil wir einen virtuellen Destruktor haben
// In diesem Bsp. egal, weil es nirgendwo etwas aufzuräumen gibt
return 0;
}
Virtuelle Destruktoren und Kopierkonstruktoren werden interessanter, wenn es in der Klasse dynamisch erzeugte Elemente gibt.
class Dreiecksimplementierung; // Irgendwo definiert
class KompliziertesDreieck : public Koerper
{
public:
KompliziertesDreieck() : impl(new Dreiecksimplementierung) {}
// Kopierkonstruktor
KompliziertesDreieck(const KompliziertesDreieck& other) :
impl(new Dreiecksimplementierung(other.impl))
{}
~KompliziertesDreieck()
{
// zum Glück ist ~Koerper virtuell
delete impl;
}
private:
Dreiecksimplementierung* impl;
};
Benutzen wir hier einen SmartPointer (shared_ptr, unique_ptr) ist es schon wieder viel einfacher, da dann alles automatisch passiert.