OVH Cloud OVH Cloud

Terminologie: classe abstraite

53 réponses
Avatar
Luc Hermitte
Salut.

Je me posais une question au sujet de ce qu'était reconnu comme une
classe abstraite.

Jusqu'à présent, ma définition a toujours été : "une classe non
instanciable".

Dans la norme, la formulation ressemble à peu près à : "Une classe
abstraite est non instanciable (1). Une classe est abstraite si elle
dispose d'au moins une fonction membre qui soit virtuelle pure (fmqsvp)
(2)".

Là arrive le pinaillage. J'ai croisé des définitions qui disaient qu'une
"classe abstraite est une classe qui a au moins une fmqsvp" (3).
Si on s'en tient à la formulation officielle, la seconde partie est une
condition suffisante mais non nécessaire. Ce qui ne suffit pas à déduire
(3).

Si on définit une classe dont les constructeurs sont tous au moins
protégés (et dépourvue de créateurs amis ou assimilés, voir les fonctions
statiques des singletons), on arrive aussi à définir une classe qui ne
soit pas instanciable...
... à un détail près: elle peut quand même être instanciée dans les
fonctions membres des descendants de la classe.

struct Abs {
protected:
Abs() {}
};

struct fils : Abs {
void f() { Abs a; }
};


Est-ce ce détail qui nous donne la condition nécessaire (je ne vois pas
d'autres façon d'avoir des classes non instanciables et utilisables (tout
privé)) qui manquait pour justifier la formulation (3) ?

Personnellement, je n'aime pas cette formulation (3) car elle tient du
détail d'implémentation. C'est peut-être bien la seule façon de définir
des classes abstraites en C++, mais ce n'est pas ça qui est réellement
important AHMA.

Bref, j'aurais aimé avoir l'avis d'autres pinailleurs sur la question. Et
eventuellement savoir si j'avais manqué un point.


--
Luc Hermitte <hermitte at free.fr>
FAQ de <news:fr.comp.lang.c++> :
<http://www.cmla.ens-cachan.fr/Utilisateurs/dosreis/C++/FAQ/>
Dejanews : <http://groups.google.com/advanced_group_search>

10 réponses

2 3 4 5 6
Avatar
Aurélien REGAT-BARREL
Oui. Si on fait une classe qui est sémantiquement abstraite mais que,
pour une raison ou pour une autre, aucune de ses fonctions membres n'est
virtuelle, alors déclarer le constructeur comme protected est un bon
moyen de s'assurer que la classe ne sera pas instanciée en tant que
telle.



Il est toujours possible dans ce cas de déclarer le destructeur virtuel
pur, ce qui me semble mieux. Pour moi, constructeur non publique me fait
plus penser à factory qu'à classe abstraite.


Justement dans le cas de factory dirais-tu que c'est une classe abstraite ?
Pourquoi utiliser un constructeur protected au lieu d'une vraie classe
abstraite ?
Et sinon le destructeur virtuel pur, si on peut seulement, c.a.d qu'il n'y a
rien à libérer... Mais même sémantiquement j'aime pas trop, je préfère un
objet qu'on ne peut pas créer qu'un objet qu'on ne peut détruire et par voie
de conséquence créer non plus.

--
Aurélien REGAT-BARREL


Avatar
Jean-Marc Bourguet
"Aurélien REGAT-BARREL" writes:

Donc : peut-on dire d'une classe au constructeur protégé qu'elle est
abstraite ?


Dans quel sens? Au sens C++ non (on peut avoir une instance
quelque part, locale à un membre de la classe ou d'une
classe dérivée par exemple).


Justement, c'est l'"autre" sens qui m'intéresse. Quel est-il ?


Dans "l'autre sens", une classe est abstraite si tu decides qu'elle
est abstraite quelle que soit son implementation. L'inconveniant est
que tu ne peux pas t'aider du compilateur pour verifier que son
utilisation correspond a ce que tu as decide.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org



Avatar
Jean-Marc Bourguet
"Aurélien REGAT-BARREL" writes:

Et sinon le destructeur virtuel pur, si on peut seulement, c.a.d qu'il n'y a
rien à libérer...


Avoir un membre virtuel pur n'empeche en rien de lui donner une
implementation. Ca impose simplement aux classes derivees de
supplanter ce membre.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Jean-Marc Bourguet
"Aurélien REGAT-BARREL" writes:

Avoir un membre virtuel pur n'empeche en rien de lui donner une
implementation. Ca impose simplement aux classes derivees de
supplanter ce membre.


Ben si j'alloue un pointeur en private dans le constructeur (je chipote mais
bon, c'est le bon endroit pout il me semble ;-)... Je pense que le
programmeur a suffisament à faire avec sa classe dérivée pour devoir en plus
terminer le boulot de cette dont il dérive.


Je repete: avoir un membre virtuel pur n'empeche en rien de lui donner
une implementation.

class foo {
foo() { bar = new char[10]; }
~foo() = 0;
};

foo::~foo() {
delete bar;
}

Quel boulot doit faire le programmeur de la classe derivee de foo?

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
Aurélien REGAT-BARREL
Avoir un membre virtuel pur n'empeche en rien de lui donner une
implementation. Ca impose simplement aux classes derivees de
supplanter ce membre.


Ben si j'alloue un pointeur en private dans le constructeur (je chipote mais
bon, c'est le bon endroit pout il me semble ;-)... Je pense que le
programmeur a suffisament à faire avec sa classe dérivée pour devoir en plus
terminer le boulot de cette dont il dérive.
Mais bon j'ai compris ta remarque.

--
Aurélien REGAT-BARREL

Avatar
Aurélien REGAT-BARREL
Dans "l'autre sens", une classe est abstraite si tu decides qu'elle
est abstraite quelle que soit son implementation. L'inconveniant est
que tu ne peux pas t'aider du compilateur pour verifier que son
utilisation correspond a ce que tu as decide.


Ok l'intérrêt est là alors : le compilo sert de garant et on n'a pas à
mettre des trucs en protected + commentaires "il faut implémenter ça" et
tout et tout... Sauf que pas mal de monde procède quand même ainsi j'ai
l'impression, en particulier pour les factory. Y a-t-il un intérrêt / raison
historique ou c'est juste une mauvaise habitude ?
Merci.

--
Aurélien REGAT-BARREL

Avatar
Jean-Marc Bourguet
"Aurélien REGAT-BARREL" writes:

Dans "l'autre sens", une classe est abstraite si tu decides qu'elle
est abstraite quelle que soit son implementation. L'inconveniant est
que tu ne peux pas t'aider du compilateur pour verifier que son
utilisation correspond a ce que tu as decide.


Ok l'intérrêt est là alors : le compilo sert de garant et on n'a pas
à mettre des trucs en protected + commentaires "il faut implémenter
ça" et tout et tout... Sauf que pas mal de monde procède quand même
ainsi j'ai l'impression, en particulier pour les factory.


Ton impression ne correspond pas a la mienne. Je vois tres rarement
des classes abstraites par conception qui ne le sont pas par les
regles du C++ (ces classes ont generalement un destructeur virtuel et
donc le rendre pur n'a aucun autre effet que de rendre la classe
abstraite pour le langage).

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
Aurélien REGAT-BARREL
(je chipote mais bon, c'est le bon endroit pout il me semble ;-)
J'ai bien fais de chipoter, je me coucherai moins bête ce soir :-)



Je repete: avoir un membre virtuel pur n'empeche en rien de lui donner
une implementation.

class foo {
foo() { bar = new char[10]; }
~foo() = 0;
};

foo::~foo() {
delete bar;
}

Quel boulot doit faire le programmeur de la classe derivee de foo?


Eh bien celui d'ouvrir un bouquin de C++ et de comprendre ce que tu viens
d'écrire. Comment cela est-il donc bien possible d'avoir une fonction
virtuelle pure (dont je croyais que ça voulait dire "non implémenté") qui
est bien réelle ?

--
Aurélien REGAT-BARREL


Avatar
Aurélien REGAT-BARREL
Ton impression ne correspond pas a la mienne. Je vois tres rarement
des classes abstraites par conception qui ne le sont pas par les
regles du C++ (ces classes ont generalement un destructeur virtuel et
donc le rendre pur n'a aucun autre effet que de rendre la classe
abstraite pour le langage).


J'ai rien dit. J'avais un exemple bien précis en tête, je comprenais pas
pourquoi les mecs n'avaient pas fait de fonction virtuelle pure. J'ai bien
ouvert mes yeux et j'ai compris : ils ont en fait. C'est juste que je me
suis laissé abusé par le fait que le constructeur est privé pour forcer à
utiliser une fonction statique New() qui oblige à manipuler la classe par
pointeur.
Donc tout est bon. Merci!

--
Aurélien REGAT-BARREL

Avatar
Jean-Marc Bourguet
"Aurélien REGAT-BARREL" writes:

(je chipote mais bon, c'est le bon endroit pout il me semble ;-)
J'ai bien fais de chipoter, je me coucherai moins bête ce soir :-)



Je repete: avoir un membre virtuel pur n'empeche en rien de lui donner
une implementation.

class foo {
foo() { bar = new char[10]; }
~foo() = 0;
};

foo::~foo() {
delete bar;
}

Quel boulot doit faire le programmeur de la classe derivee de foo?


Eh bien celui d'ouvrir un bouquin de C++ et de comprendre ce que tu
viens d'écrire. Comment cela est-il donc bien possible d'avoir une
fonction virtuelle pure (dont je croyais que ça voulait dire "non
implémenté") qui est bien réelle ?


Virtuel pure veut dire qui doit etre supplantee et qui peut ne pas
etre implementee (sauf pour le destructeur qui sera toujours existant,
qu'il soit virtuel pur ou non).

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org



2 3 4 5 6