Eine abstrakte Klasse, ist eine Klasse, die sich nicht instanziieren lässt. Dies macht dann Sinn, wenn man nur ein Interface (also die Schnittstellen) definieren will, aber das genauere Verhalten noch nicht festlegen will.
#include<iostream>
#include<string>
using namespace std;
class BaseFormat
{
public:
virtual ~BaseFormat() {}
virtual void header() = 0;
virtual void text(string const&, string const&) = 0;
virtual void footer() = 0;
};
class XMLFormat : public BaseFormat
{
public:
void header()
{
cout<<"<definition>\n";
}
void text(string const& name, string const& value)
{
cout<<"\t<"<<name<<'>'<<value<<"</"<<name<<">\n";
}
void footer()
{
cout<<"</definition>\n";
}
};
class CSVFormat : public BaseFormat
{
public:
void header()
{
}
void text(string const& name, string const& value)
{
cout<<<name<<';'<<value<<'\n';
}
void footer()
{
}
};
int main()
{
BaseFormat* frmt=new CSVFormat();
frmt->header();
frmt->text("Variable1", "Value1");
frmt->text("Variable2", "Value2");
frmt->text("Variable3", "Value3");
frmt->footer();
delete frmt;
}
BaseFormat ist eine abstrakte Klasse und dient uns als Interface. BaseFormat beschreibt lediglich die Schnittstellen. CSVFormat und XMLFormat implementieren diese Schnittstellen.
Die Deklaration virtual void header() = 0; bedeutet, dass header eine rein virtuelle (pure virtual) Methode ist. Rein virtuell heißt, dass sie von jeder abgeleiteten Klasse überschrieben werden muss. Es bedeutet aber nicht, dass sie keinen Körper haben kann:
#include<iostream>
class Base
{
public:
virtual ~Base() {}
virtual void foo() = 0;
// = 0 und Methodenkörper können nicht
//gleichzeitig auftreten, wir müssen foo
//deshalb gesondert implementieren
};
class Derived : public Base
{
public:
void foo()
{
cout<<"Derived::foo\n";
Base::foo();
}
};
void Base::foo()
{
cout<<"Base::foo\n";
}
int main()
{
Derived d;
d.foo();
}
Jede Klasse mit mindestens einer rein virtuellen Methode ist eine abstrakte Klasse und kann nicht instanziiert werden.
Wenn wir eine Klasse abstrakt machen wollen, ohne virtuelle Methoden anzubieten, können wir einfach den Destruktor rein virtuell machen. Allerdings muss jede Klasse einen Destruktor besitzen, deshalb müssen wir den rein virtuellen Destruktor implementieren. Denn der Compiler generiert ihn nicht mehr automatisch sobald wir in deklarieren.