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 ~~ :)
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.
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.
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 ()`
}
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;
}
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.
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?