it-swarm.com.de

Die Konstruktorfunktion in einer reinen virtuellen Klasse sollte "protected" oder "public" sein.

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 ~~ :)

9
Wizmann

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.

6
Fred Foo

Abstrakte Klassen und deren Aufbau

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.


beispiel-Snippet

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;
}
3
jsantander

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.

2

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?

0
CinCout