web-dev-qa-db-fra.com

La fonction constructeur dans une classe virtuelle pure devrait-elle être "protégée" ou "publique"?

L'exemple suivant provient du livre "Modèle d'objet Inside C++"

class Abstract_base {
public:
    virtual ~Abstract_base () = 0;
    virtual void interface () const = 0;
    virtual const char* mumble () const 
    {
        return _mumble;
    }
protected:
    char *_mumble;
};

L'auteur indique que si je veux initialiser _mumble, le membre de données de la classe de base virtuelle pure, un "constructeur protégé" doit être implémenté.

Mais pourquoi protégé ? Et pourquoi "constructeur public" ne convient pas à cette classe?

Merci pour vos réponses, et ce serait parfait s'il y a un exemple ~~ :)

9
Wizmann

Cela n'a pas vraiment d'importance, car vous n'êtes de toute façon pas autorisé à construire des objets de la classe de base. La rendre protected sert uniquement à rappeler que la classe est supposée être une classe de base; ce n'est que des cosmétiques/de la documentation.

Considérer

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

La suppression de protected ne modifie en aucun cas la signification du programme.

6
Fred Foo

Classes abstraites et construction de telles

Peu importe que le constructeur soit public ou protégé , puisqu'un classe abstraite ne peut pas être instancié.

Vous devez en hériter pour que son constructeur soit appelé, et puisque le Derived class appelle le constructeur de la classe abstraite le niveau de protection choisi n'a pas d'importance, tant que le Derived class peut y accéder.


Une des raisons que l’on pourrait avoir pour la rendre protected est de rappeler que la classe doit être construite par héritage, mais honnêtement, cela devrait être assez clair si on voit qu’elle a pure virtual member-functions.


exemple extrait

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 ()`
}
5

Une classe virtuelle pure ne peut pas être instanciée, donc cela ne fait aucune différence si le constructeur est public ou protégé.

Un constructeur public est syntaxiquement correct. Cependant, le rendre protégé portera une indication plus forte que la classe ne peut pas être instanciée.

Pour un exemple: 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

Un constructeur public ne serait pas très utile, car les classes abstraites ne peuvent pas être instanciées en premier lieu.

Un constructeur protégé a du sens: ainsi, une classe concrète dérivée peut fournir son propre constructeur public qui se lie au constructeur protégé de la classe abstraite de base.

2

Protecetd ctor s'assurera que le ctor ne soit appelé que par les classes dérivées de Abstract_base.

Public ctor n'est pas approprié car la classe contient une méthode pure virtual! Comment envisagez-vous d'instancier une classe virtuelle pure si ce n'est via ses classes enfants?

0
CinCout