Das folgende Beispiel stammt aus dem Buch "Inside C++ - Objektmodell"
class Abstract_base {
public:
virtual ~Abstract_base () = 0;
virtual void interface () const = 0;
virtual const char* mumble () const
{
return _mumble;
}
protected:
char *_mumble;
};
Der Autor sagt, wenn ich _mumble
, das Datenelement der reinen virtuellen Basisklasse, initialisieren möchte, sollte ein "protected constructor" implementiert werden.
Aber warum geschützt ? Und warum ist "öffentlicher Konstruktor" für diese Klasse nicht geeignet?
Vielen Dank für Ihre Antworten, und es wäre perfekt, wenn es ein Beispiel gibt ~~ :)
Es spielt keine Rolle, da Sie sowieso keine Objekte der Basisklasse konstruieren dürfen. Wenn Sie protected
angeben, wird nur daran erinnert, dass die Klasse eine Basisklasse sein soll. Es ist nur Kosmetik/Dokumentation.
Erwägen
struct Base {
virtual ~Base() = 0;
protected:
Base() { std::puts("Base constructor"); }
};
Base::~Base() { std::puts("Base destructor"); }
struct Derived : Base {};
int main()
{
//Base b; // compiler error
Derived d;
Base *b = new Derived();
delete b;
}
Durch das Entfernen der protected
wird die Bedeutung des Programms in keiner Weise geändert.
Es spielt keine Rolle, ob der Konstruktor öffentlich oder geschützt ist, da eine abstrakte Klasse nicht instanziiert werden kann.
Sie müssen davon erben, damit der Konstruktor aufgerufen wird. Da die Derived -Klasse den Konstruktor der abstract class aufruft, spielt es keine Rolle, welche Schutzstufe Sie auswählen wie die Derived Klasse darauf zugreifen kann.
Ein Grund, den man möglicherweise haben könnte, um es protected
zu machen, besteht darin, daran zu erinnern, dass die Klasse durch Vererbung konstruiert werden muss, aber ehrlich gesagt sollte das klar genug sein, wenn man sieht, dass sie rein virtuell Member-Funktionen hat.
struct B {
virtual void func () = 0;
virtual ~B () = 0 { };
};
B::~B () { }
struct D : B {
void func () override;
};
int main () {
B b; // will error, no matter if Bs ctor is 'public' or 'protected'
// due to pure virtual member-function
D d; // legal, D has overriden `void B::func ()`
}
Eine reine virtuelle Klasse kann nicht instanziiert werden, daher macht es keinen Unterschied, ob der Konstruktor öffentlich oder geschützt ist.
Ein öffentlicher Konstruktor ist syntaktisch korrekt. Wenn Sie es jedoch geschützt machen, wird ein stärkerer Hinweis angezeigt, dass die Klasse nicht instanziiert werden kann.
Ein Beispiel: http://ideone.com/L66Prq
#include <iostream>
using namespace std;
class PublicAbstract {
public:
PublicAbstract() { }
virtual void doThings() =0;
};
class ProtectedAbstract {
protected:
ProtectedAbstract() { }
public:
virtual void doMoreThings() =0;
};
class B: public PublicAbstract {
public:
void doThings() { }
};
class C: public ProtectedAbstract {
public:
void doMoreThings() { }
};
int main() {
B b;
C c;
return 0;
}
Ein öffentlicher Konstruktor wäre nicht sehr nützlich, da abstrakte Klassen überhaupt nicht instanziiert werden können.
Ein geschützter Konstruktor ist sinnvoll: Auf diese Weise kann eine abgeleitete konkrete Klasse einen eigenen öffentlichen Konstruktor bereitstellen, der an den geschützten Konstruktor der abstrakten Basisklasse kettet.
Protecetd ctor stellt sicher, dass der ctor nur von den Klassen aufgerufen wird, die von Abstract_base
abgeleitet sind.
Public ctor ist nicht geeignet, da die Klasse eine pure virtual
Methode enthält! Wie planen Sie, eine rein virtuelle Klasse zu instanziieren, wenn nicht über ihre untergeordneten Klassen?