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
drkm
"Christophe Lephay" writes:

drkm wrote:

Il y a peut-être une petite confusion entre « instanciable » et
« instanciée ». Pour moi, une classe n'est pas instanciable, par
nature, lorsqu'elle est abstraite. Et n'est jamais instanciée, par
construction, dans l'exemple ci-dessus.


Il n'y a aucune confusion. Je voulais juste souligner que [...]


Je ne parlais pas de toi. Dans ce fil, il a été dit que la classe A
de l'exemple :

class A {
A() {
}
} ;

n'était pas instanciable. Et que donc on pouvait parler de classe
abstraite. Il me semble pourtant que cette classe est bel et bien
instanciable, mais n'est jamais instanciée.

Peut-on dire que dans le programme suivant, B est abstraite ?

struct B {
} ;

int main() {
}

--drkm


Avatar
Gabriel Dos Reis
drkm writes:

| "Christophe Lephay" writes:
|
| > drkm wrote:
|
| >> Il y a peut-être une petite confusion entre « instanciable » et
| >> « instanciée ». Pour moi, une classe n'est pas instanciable, par
| >> nature, lorsqu'elle est abstraite. Et n'est jamais instanciée, par
| >> construction, dans l'exemple ci-dessus.
|
| > Il n'y a aucune confusion. Je voulais juste souligner que [...]
|
| Je ne parlais pas de toi. Dans ce fil, il a été dit que la classe A
| de l'exemple :
|
| class A {
| A() {
| }
| } ;
|
| n'était pas instanciable. Et que donc on pouvait parler de classe
| abstraite. Il me semble pourtant que cette classe est bel et bien
| instanciable, mais n'est jamais instanciée.
|
| Peut-on dire que dans le programme suivant, B est abstraite ?
|
| struct B {
| } ;
|
| int main() {
| }

Non, parce que son nom commence par « B » et non « A » comme abstraite :-)

-- Gaby
Avatar
Arnaud Meurgues
Aurélien REGAT-BARREL wrote:

Mais est-elle abstraite selon un sens quelconque (et lequel) ?
A la question "Peut-on dire qu'une classe avec un constructeur privé est
abstraite" vous répondez quoi ?


Non:

class A {
A() {}
public:
static A* instanciate() { return new A; }
};

n'est pas abstraite et son constructeur est privé.

Quelle est selon vous la raison principale entre choisir de rendre abstraite
une classe via le sens C++ classique et via un constructeur privé ?


Ben, une classe abstraite, en générale, sert de classe de base pour des
sous-classes. Si son(ses) constructeur(s) est(sont) privé(s), on ne peut
pas instancier non plus les classes dérivées et l'intérêt devient très
très limité.

--
Arnaud
(Supprimez les geneurs pour me répondre)

Avatar
Aurélien REGAT-BARREL
Désolé pour le retard

Quelle est selon vous la raison principale entre choisir de rendre
abstraite


une classe via le sens C++ classique et via un constructeur privé ?


Ben, une classe abstraite, en générale, sert de classe de base pour des
sous-classes. Si son(ses) constructeur(s) est(sont) privé(s), on ne peut
pas instancier non plus les classes dérivées et l'intérêt devient très
très limité.


Ben j'ai déjà vu l'utilisation de constructeur privé (protected en fait)
pour les classes de base.
Je pense que la différence se situe si on souhaite imposer de définir une ou
plusieurs fonctions (=> virtuelles pures) ou si on veut juste servir de
dénominateur commun, de base.
Avec une classe abstraite C++ on souligne peut être plus le principe
d'interface (comme dans les ABC), alors qu'utiliser une classe non
instanciable est peut être mieux si on veut juste par exemple cacher des
détails d'implémentation. Par exemple une classe traducteur avec tout le
code qui faut pour chercher la traduction d'un mot dans un dictionnaire
interne, sauf que la classe de base a un dictionnaire vide. Ses classes
dérivées ne font pas grand chose de plus que de remplir le dictionnaire dans
une langue donnée.

class Traducteur
{
public:
string Traduit( const string & Mot )
{
return this->dico.find( Mot )->second;
}

protected:
map<string, string> dico;

protected:
Traducteur();
};

class TraducteurAnglais : public Traducteur
{
public:
TraducteurAnglais()
{
this->dico[ "salut" ] = "hello";
}
};

Non ?

--
Aurélien REGAT-BARREL


Avatar
Arnaud Meurgues
Aurélien REGAT-BARREL wrote:

Quelle est selon vous la raison principale entre choisir de rendre abstraite
une classe via le sens C++ classique et via un constructeur privé ?


Ben, une classe abstraite, en générale, sert de classe de base pour des
sous-classes. Si son(ses) constructeur(s) est(sont) privé(s), on ne peut
pas instancier non plus les classes dérivées et l'intérêt devient très
très limité.


Ben j'ai déjà vu l'utilisation de constructeur privé (protected en fait)
pour les classes de base.


Privé et protégé, c'est très différent. S'il est privé, on ne peut plus
dériver la classe. S'il est protégé, la dériver est le seul moyen de
l'utiliser, et c'est donc une manière d'imposer que ce soit une classe
abstraite (c'est à dire non destinée à être instanciée en tant que telle).

Je pense que la différence se situe si on souhaite imposer de définir une ou
plusieurs fonctions (=> virtuelles pures) ou si on veut juste servir de
dénominateur commun, de base.


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.

Avec une classe abstraite C++ on souligne peut être plus le principe
d'interface (comme dans les ABC), alors qu'utiliser une classe non
instanciable est peut être mieux si on veut juste par exemple cacher des
détails d'implémentation.


Si l'on veut cacher des détails d'implémentation, il y a aussi
l'héritage privé.

Dans le cas que tu cites, il y a bien un désir d'usage polymorphisme (tu
veux pouvoir traiter d'importe quel traducteur de la même manière). Donc
la classe de base a bien un rôle de classe abstraite.

--
Arnaud
(Supprimez les geneurs pour me répondre)



Avatar
Aurélien REGAT-BARREL
Privé et protégé, c'est très différent. S'il est privé, on ne peut plus
dériver la classe. S'il est protégé, la dériver est le seul moyen de
l'utiliser, et c'est donc une manière d'imposer que ce soit une classe
abstraite (c'est à dire non destinée à être instanciée en tant que telle).


Oui je m'en suis apperçu en répondant. En fait je voulais dire constructeur
protégé jusque là...
Donc : peut-on dire d'une classe au constructeur protégé qu'elle est
abstraite ? Quelle différence avec une classe avec f.m.virtuelle pure ?

Si l'on veut cacher des détails d'implémentation, il y a aussi
l'héritage privé.

Dans le cas que tu cites, il y a bien un désir d'usage polymorphisme (tu
veux pouvoir traiter d'importe quel traducteur de la même manière). Donc
la classe de base a bien un rôle de classe abstraite.


Oui j'ai pas terminé mon exemple. Le but était de mettre tout ça dans une
factory qui renvoie un type de Traducteur en fonction je en sais quoi.
Merci.

--
Aurélien REGAT-BARREL

Avatar
Arnaud Meurgues
Aurélien REGAT-BARREL wrote:

Donc : peut-on dire d'une classe au constructeur protégé qu'elle est
abstraite ? Quelle différence avec une classe avec f.m.virtuelle pure ?


Là, je ne sais pas.

Pour moi, il y a deux concept distincts :
1 - la sémantique de classe abstraite en modélisation. Dans ce cas,
c'est une classe non destinée à être instanciée qui sert de racine d'un
arbre d'héritage afin de permettre un usage polymorphique (dynamique)
2 - la sémantique de classe abstraite de C++ qui dit qu'une classe
est abstraite si elle a une fonction virtuelle pure.

Le premier est un concept indépendant de l'implémentation.
Le second est un concept purement C++.

Et le second concept ne couvre pas toutes les implémentations C++
possibles du premier.

Mais c'est ma vision de la chose et peut-être que d'autres pourraient en
avoir une autre (voire me démontrer que la mienne est fausse).
--
Arnaud
(Supprimez les geneurs pour me répondre)

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).

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
Loïc Joly
Arnaud Meurgues wrote:

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.

--
Loïc

Avatar
Aurélien REGAT-BARREL
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 ?

--
Aurélien REGAT-BARREL


2 3 4 5 6