Classe abstraite ou pimpl ?

Le
Fabien LE LEZ
Bonjour,

Si je veux cacher les entrailles d'une classe, et ne montrer à son
utilisateur que les fonctions publiques, j'ai en gros le choix entre :

- l'idiome pimpl :

// .h
class C
{
public:
void f();
private:
class Implementation;
Implementation* pimpl;
};

// .cpp
void C::f()
{
pimpl-> f();
}

- l'idiome "classe de base abstraite" :

// .h
class C
{
public:
virtual void f()= 0;
};

// .cpp
class Implementation: public C
{
void f()
{
// Le code ici
}
}


Mon problème, c'est que je viens de m'apercevoir que je choisis entre
ces deux méthodes plus ou moins au hasard, suivant celle qui me vient
à l'esprit en premier.
Y a-t-il des critères rationnels pour choisir ?
Note : il s'agit généralement de classes à sémantique d'entité, non
copiables.

Merci d'avance
Vos réponses Page 1 / 3
Trier par : date / pertinence
Charles Brossollet
Le #261643
J'utilise les deux, moi aussi, et je pense que du moment qu'il n'y a
pas de nécessité de faire hériter ta classe, c'est kif-kif. Mais si
tu veux hériter, la classe abstraite s'impose naturellement.
Fabien LE LEZ
Le #261642
On 25 Sep 2005 02:39:06 -0700, "Charles Brossollet"

et je pense que du moment qu'il n'y a
pas de nécessité de faire hériter ta classe, c'est kif-kif.


De toutes façons, dans les deux cas le code client n'a pas à hériter
de ma classe.

Et l'idiome pimpl peut aussi gérer l'héritage : il suffit de faire
dériver une classe de la classe "Implementation".

Stan
Le #261637
"Fabien LE LEZ"
Bonjour,

Si je veux cacher les entrailles d'une classe, et ne montrer à son
utilisateur que les fonctions publiques, j'ai en gros le choix entre :

- l'idiome pimpl :

// .h
class C
{
public:
void f();
private:
class Implementation;
Implementation* pimpl;
};

// .cpp
void C::f()
{
pimpl-> f();
}

- l'idiome "classe de base abstraite" :

// .h
class C
{
public:
virtual void f()= 0;
};

// .cpp
class Implementation: public C
{
void f()
{
// Le code ici
}
}


Mon problème, c'est que je viens de m'apercevoir que je choisis entre
ces deux méthodes plus ou moins au hasard, suivant celle qui me vient
à l'esprit en premier.
Y a-t-il des critères rationnels pour choisir ?


Le premier cas permet une séparation physique de l'interface et de
l'implémentation,
ce qui ce traduit aussi par un gain de temps de re-compilation ( si on
modifie l'implémentation ).


--
-Stan

Richard Delorme
Le #262487
Bonjour,

Si je veux cacher les entrailles d'une classe, et ne montrer à son
utilisateur que les fonctions publiques,


Quel intérêt de cacher l'implémentation ?

[...]
Mon problème, c'est que je viens de m'apercevoir que je choisis entre
ces deux méthodes plus ou moins au hasard, suivant celle qui me vient
à l'esprit en premier.
Y a-t-il des critères rationnels pour choisir ?


J'ai l'impression que cela ressemble au choix plus général entre "is-a"
(une classe B hérite d'une classe A) et "has-a" (une classe B contient
une classe A). En dehors de quelques cas d'école, je ne crois pas qu'il
y ait de critères rationnels autre qu'empiriques pour choisir.

--
Richard

Marc Boyer
Le #262486
Fabien LE LEZ
Bonjour,

Si je veux cacher les entrailles d'une classe, et ne montrer à son
utilisateur que les fonctions publiques, j'ai en gros le choix entre :
- l'idiome pimpl :
- l'idiome "classe de base abstraite" :


J'aurais tendance à préférer la classe de base abstraite, car:
- l'indirection générée par la virtualité est gérée par le
compilateur, donc possiblement plus efficacement.
- le compilateur peut signaler quand on a oublié d'instancier
une méthode

Mais bon, ce sont les avantages que je vois, je peux ne pas voir
les désavantages.

Marc Boyer
--
À vélo, prendre une rue à contre-sens est moins dangeureux
que prendre un boulevard dans le sens légal. À qui la faute ?

Fabien LE LEZ
Le #262106
On Mon, 26 Sep 2005 09:47:44 +0200, "Stan"
Le premier cas permet une séparation physique de l'interface et de
l'implémentation,
ce qui ce traduit aussi par un gain de temps de re-compilation


N'est-ce pas aussi le cas du deuxième ?

D'ailleurs, sous Windows au moins, le deuxième cas semble idiomatique
quand l'implémentation se trouve dans une DLL.

Stan
Le #262473
"Fabien LE LEZ"
On Mon, 26 Sep 2005 09:47:44 +0200, "Stan"
Le premier cas permet une séparation physique de l'interface et de
l'implémentation,
ce qui ce traduit aussi par un gain de temps de re-compilation


N'est-ce pas aussi le cas du deuxième ?



Pour ce qui est de la séparation physique de l'interface et de
l'implémentation,
dans le premier cas, tu peux ne fournir qu'un fichier obj et un fichier
d'inclusion
et là, tu es sûr que les détails de l'implémentations seront masqués.

C'est ce qui se pratique parfois.

--
-Stan


Aurelien Regat-Barrel
Le #262471
Moi je vois une assez grosse différence: la classe virtuelle possède
obligatoirement une sémantique de référence, avec allocation dynamique
(et il manque le code de la factory dans ton code), alors que le pimpl
peut être utilisé par valeur.
Au niveau de l'implémentation, je trouve le pimpl moins agréable :
gestion de l'allocation du pimpl, déclaration/implémentation d'une
classe dans un .cpp, ça fait un code un peu plus lourd je trouve.

--
Aurélien Regat-Barrel
JBB
Le #262470
Fabien LE LEZ wrote:
Bonjour,

Si je veux cacher les entrailles d'une classe, et ne montrer à son
utilisateur que les fonctions publiques, j'ai en gros le choix entre :

- l'idiome pimpl :

// .h
class C
{
public:
void f();
private:
class Implementation;
Implementation* pimpl;
};

// .cpp
void C::f()
{
pimpl-> f();
}

- l'idiome "classe de base abstraite" :

// .h
class C
{
public:
virtual void f()= 0;
};

// .cpp
class Implementation: public C
{
void f()
{
// Le code ici
}
}


Mon problème, c'est que je viens de m'apercevoir que je choisis entre
ces deux méthodes plus ou moins au hasard, suivant celle qui me vient
à l'esprit en premier.
Y a-t-il des critères rationnels pour choisir ?
Note : il s'agit généralement de classes à sémantique d'entité, non
copiables.

Merci d'avance...

Si on lieu d'un fonction f() tu en as 50, tu gagnera peut etre un peu

de temps à faire de la classe de base abstraite.

En plus dans le methode pimpl tu peut te tromper dans l'indirection:
ex : void C::f() { pimpl-> g();) //encore une victime du copier coller

pimpl est donc un peu plus souple mais peut donc entrainer plus d'erreur.

Apres il faut voir aussi si tu as l'intention de deriver de C (utiliser
pimpl) , ou si tu veux pouvoir utiliser plusieurs interfaces C, avec des
classes d'implementation differentes (utiliser la classe abstraite).

Fabien LE LEZ
Le #262467
On Mon, 26 Sep 2005 15:16:35 +0200, "Stan"
dans le premier cas, tu peux ne fournir qu'un fichier obj et un fichier
d'inclusion


Et pourquoi est-ce impossible dans le deuxième cas ?

Publicité
Poster une réponse
Anonyme