Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Vocabulaire.

42 réponses
Avatar
Alexis Guillaume
Bonjour =E0 tous.

Je suis en train de concevoir une hi=E9rarchie de classe en C++ :

class base {
public:
virtual void foo();
};

Dans les commentaires, j'impose que si foo() est d=E9riv=E9e dans une
classe fille, alors cette m=E9thode d=E9riv=E9e doit aussi appeler
explicitement base::foo() apr=E8s avoir fait ce qu'elle voulait. Plus
g=E9n=E9ralement, si on a C qui h=E9rite de B et B qui h=E9rite base, et qu=
e B
et C d=E9rivent foo(), alors C::foo() doit appeler B::foo() et B::foo()
doit appeler base::foo().

Je dois r=E9diger un document de conception et j'ai bien du mal =E0
trouver comment appeler ce genre de fonctions virtuelles. Je pensais =E0
quelque chose comme "m=E9thode virtuelle cha=EEn=E9e"... Mais il y a
s=FBrement mieux et il y a peut-=EAtre m=EAme un mot qui existe d=E9j=E0 po=
ur
cela auquel cas c'est bien s=FBr lui que j'emploirai.

Merci pour vos avis =E9clair=E9s.
Alexis Guillaume.

10 réponses

1 2 3 4 5
Avatar
Michael DOUBEZ
Pascal J. Bourguignon wrote:
Alexis Guillaume writes:

Il y a le pattern "chaine de responsabilité" que tu peux employer. Ca a
l'air d'en être une forme (je ne peux pas dire avec les éléments que tu
donnes).


En effet je me renseigne sur ce pattern et ça a l'air d'être ce que je
veux faire. Merci beaucoup ! :-)



Oui, enfin, c'est le fonctionnement normal en programmation objet
quand on surcharge une méthode, d'appeler la méthode de la superclass.

C'est tellement normal, que dans les langages de programmation objet
normaux, il y a en général un mot clé ou une syntaxe particulière,
quand ce n'est pas automatique.



Ce qui ne marche que dans le cas où l'héritage est simple. Comme C++
supporte l'héritage multiple, c'est assez difficile de fournir un tel
mot clé.

[snip]
Tu es en train de documenter quelque chose qui est ce qui devrait se
faire par défaut, car c'est la façon naturelle d'implémenter le
principe de substitution de Lyskov.



Sauf dans les cas où la fonction virtuelle ne fait qu'implémenter un
comportement par défaut et où les surcharges suivantes modifient ce
comportement.
Ou alors dans un principe de décoration (une sous classe décore la
classe supérieur - par exemple des filtres).

[snip]
Une autre solution serait d'utiliser une méthode crochet, c'est à dire
qu'on défini dans la super classe une méthode WX qui s'assure que la
méthode Y est appelée en même temps que X, la superclasse ne
définissant pas X (ou fournissant une définition par défaut vide), en
spécifiant simplement qu'une sous-classe doit surcharger X (comme elle
le veut, la méthode Y étant appelée automatiquemetn par WX.



Le problème ici est qu'il peut y avoir un nombre indéfini de surcharge
de la classe et chaque surcharge intermédiaire doit être appelée.

--
Michael
Avatar
pjb
Michael DOUBEZ writes:

Jean-Marc Bourguet wrote:
(Pascal J. Bourguignon) writes:

Alexis Guillaume writes:

Il y a le pattern "chaine de responsabilité" que tu peux employer. Ca a
l'air d'en être une forme (je ne peux pas dire avec les éléments que tu
donnes).


En effet je me renseigne sur ce pattern et ça a l'air d'être ce que je
veux faire. Merci beaucoup ! :-)


Oui, enfin, c'est le fonctionnement normal en programmation objet quand
on surcharge une méthode, d'appeler la méthode de la superclass.


Bizarre, dans la plupart des cas, ce n'est pas ce que je fais (a
commencer
par tous les cas ou la fonction membre est pure dans la classe de base).



Une fonction virtuelle pure a peut avoir un corps bien que ce soit
assez rare (sauf peut être quand c'est le destructeur).



Ça doit être "nouveau". Quelle est la syntaxe pour l'écrire?

--
__Pascal Bourguignon__
Avatar
espie
In article ,
Pascal J. Bourguignon wrote:
Oui, dans le second cas, quand on utilise :before ou :after.



Dans le premier cas, on utilise (call-next-method) pour indiquer à
quel moment _les_ méthodes des superclasses, ou des classes héritées
en même temps que la classe courante, doivent être appelées.



Beurk.

Une raison de plus d'eviter common-lisp.

Je n'aime pas les trucs dont il faut se souvenir qui imposent un
certain schema et ordre d'appel (y compris en C++, je les tolere quand il
y a raison imperieuse).

Ca me parait complexe de rajouter des mecanismes pour specifier un ordre
a la noix d'appel de methodes, alors que c'est si simple d'ecrire soi-meme
ce qu'on veut dans l'ordre qu'on veut...
Avatar
pjb
Michael DOUBEZ writes:

Pascal J. Bourguignon wrote:
Alexis Guillaume writes:

Il y a le pattern "chaine de responsabilité" que tu peux employer. Ca a
l'air d'en être une forme (je ne peux pas dire avec les éléments que tu
donnes).


En effet je me renseigne sur ce pattern et ça a l'air d'être ce que je
veux faire. Merci beaucoup ! :-)


Oui, enfin, c'est le fonctionnement normal en programmation objet
quand on surcharge une méthode, d'appeler la méthode de la superclass.
C'est tellement normal, que dans les langages de programmation objet
normaux, il y a en général un mot clé ou une syntaxe particulière,
quand ce n'est pas automatique.



Ce qui ne marche que dans le cas où l'héritage est simple. Comme C++
supporte l'héritage multiple, c'est assez difficile de fournir un tel
mot clé.



Tu n'as pas bien fait attention aux exemples Common Lisp.
(call-next-method) appelle la méthode suivante, en tenant compte de
l'héritage multiple. Ce n'est pas forcément celle d'une super-classe.
Mais je n'entrerai pas plus dans la richesse du système objet de
Common Lisp.


[snip]
Tu es en train de documenter quelque chose qui est ce qui devrait se
faire par défaut, car c'est la façon naturelle d'implémenter le
principe de substitution de Lyskov.



Sauf dans les cas où la fonction virtuelle ne fait qu'implémenter un
comportement par défaut et où les surcharges suivantes modifient ce
comportement.
Ou alors dans un principe de décoration (une sous classe décore la
classe supérieur - par exemple des filtres).



On peut toujours par défaut ne rien faire, prendre F comme
pré-condition et V comme post-condition.


[snip]
Une autre solution serait d'utiliser une méthode crochet, c'est à dire
qu'on défini dans la super classe une méthode WX qui s'assure que la
méthode Y est appelée en même temps que X, la superclasse ne
définissant pas X (ou fournissant une définition par défaut vide), en
spécifiant simplement qu'une sous-classe doit surcharger X (comme elle
le veut, la méthode Y étant appelée automatiquemetn par WX.



Le problème ici est qu'il peut y avoir un nombre indéfini de surcharge
de la classe et chaque surcharge intermédiaire doit être appelée.



Bien entendu, toutes ces méthodes sont virtuelles, et quand la super
classe envoit le message this->X(), c'est la méthode de la sous-classe
dont this est exactement l'instance qui est appelée. Tout ce qu'on lui
demande c'est d'assurer la post-condition. Le mieux pour elle c'est
d'appeler la méthode X de la superclasse mais si elle ne le fait pas
ce n'est pas grave, et de toutes façons WX s'assure que Y soit
appelée.


--
__Pascal Bourguignon__
Avatar
pjb
(Marc Espie) writes:

In article ,
Pascal J. Bourguignon wrote:
Oui, dans le second cas, quand on utilise :before ou :after.



Dans le premier cas, on utilise (call-next-method) pour indiquer à
quel moment _les_ méthodes des superclasses, ou des classes héritées
en même temps que la classe courante, doivent être appelées.



Beurk.

Une raison de plus d'eviter common-lisp.

Je n'aime pas les trucs dont il faut se souvenir qui imposent un
certain schema et ordre d'appel (y compris en C++, je les tolere quand il
y a raison imperieuse).

Ca me parait complexe de rajouter des mecanismes pour specifier un ordre
a la noix d'appel de methodes, alors que c'est si simple d'ecrire soi-meme
ce qu'on veut dans l'ordre qu'on veut...



Justement, en C++ tu es obligé de specifier toi même l'ordre d'appel
des méthodes des super-classes. En CL, l'ordre d'appel des
superclasses est déduit logiquement par l'ordre d'héritage multiple.

Donc en C++ on a du ajouter un mécanisme pour spécifier un ordre à la
noix d'appel de méthode, qui consiste à mettre le nom de la
super-classe en dur dans l'appel:

this->SuperClass1::method();
this->SuperClass2::method();
// ...

alors qu'en CL on écrit simplement soi-même ce qu'on veut dans
l'ordre qu'on veut.



(Hé! C'est la même chose dans les deux cas: on écrit sa méthode et si
on veut appeler la méthode de la super classe, on l'appelle. La
seule différence c'est qu'en Common Lisp on n'a pas besoin de répéter
le nom de la superclass ou de la méthode, donc ça fait moins de
travail et moins de bogue quand on refactorise).

--
__Pascal Bourguignon__
Avatar
Wykaaa
Fabien LE LEZ a écrit :
On Wed, 04 Mar 2009 16:27:33 +0100, (Pascal J.
Bourguignon):

Oui, enfin, c'est le fonctionnement normal en programmation objet
quand on surcharge une méthode, d'appeler la méthode de la superclass.



Ben oui, mais justement, C++ n'est pas un langage objet, et n'a
d'ailleurs pas la notion de "méthode".



Ah bon ? et une fonction membre c'est quoi ?
Avatar
Jean-Marc Bourguet
(Pascal J. Bourguignon) writes:

Une fonction virtuelle pure a peut avoir un corps bien que ce soit
assez rare (sauf peut être quand c'est le destructeur).



Ça doit être "nouveau". Quelle est la syntaxe pour l'écrire?



C'est déjà dans la deuxième édition de TC++PL, en 1991. J'ai pas cherché
dans des documents antérieurs.

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
Fabien LE LEZ
On Wed, 04 Mar 2009 18:12:36 +0100, Wykaaa :

Ben oui, mais justement, C++ n'est pas un langage objet, et n'a
d'ailleurs pas la notion de "méthode".



Ah bon ? et une fonction membre c'est quoi ?



Une fonction membre.

Le mot "méthode" est généralement employé dans les langages où les
fonctions membres sont toutes virtuelles. En C++, une fonction membre
n'est pas virtuelle, sauf si on le demande explicitement. Du coup,
utiliser le mot "méthode" n'apporte qu'une inutile confusion :
signifie-t-il "fonction membre" ou "fonction membre virtuelle" ?
Avatar
Wykaaa
Fabien LE LEZ a écrit :
On Wed, 04 Mar 2009 18:12:36 +0100, Wykaaa :

Ben oui, mais justement, C++ n'est pas un langage objet, et n'a
d'ailleurs pas la notion de "méthode".


Ah bon ? et une fonction membre c'est quoi ?



Une fonction membre.

Le mot "méthode" est généralement employé dans les langages où les
fonctions membres sont toutes virtuelles. En C++, une fonction membre
n'est pas virtuelle, sauf si on le demande explicitement. Du coup,
utiliser le mot "méthode" n'apporte qu'une inutile confusion :
signifie-t-il "fonction membre" ou "fonction membre virtuelle" ?




C'est vrai que, sauf erreur ou omission, la norme C++ ne parle pas de
méthode.
Avatar
James Kanze
On Mar 4, 1:57 pm, Alexis Guillaume wrote:

Je suis en train de concevoir une hiérarchie de classe en C++ :



class base {
public:
virtual void foo();
};



Dans les commentaires, j'impose que si foo() est dérivée dans
une classe fille, alors cette méthode dérivée doit aussi
appeler explicitement base::foo() après avoir fait ce qu'elle
voulait. Plus généralement, si on a C qui hérite de B et B qui
hérite base, et que B et C dérivent foo(), alors C::foo() doit
appeler B::foo() et B::foo() doit appeler base::foo().



Je dois rédiger un document de conception et j'ai bien du mal
à trouver comment appeler ce genre de fonctions virtuelles. Je
pensais à quelque chose comme "méthode virtuelle chaînée"...
Mais il y a sûrement mieux et il y a peut-être même un mot qui
existe déjà pour cela auquel cas c'est bien sûr lui que
j'emploirai.



Le mot qui me vient à l'esprit est « mauvaise conception ». Je
ne vois pas de cas où une telle conception convient. En gros,
donnée une fonction virtuelle « f », dans une classe de base, ou
bien, la classe dérivée l'implémente (et donc, une classe qui en
dérive ne doit pas l'implémenter), ou bien il ne l'implémente
pas (et donc, la fonction reste virtuelle). Si une classe
dérivée doit implémenter « f », mais laisser aussi la
possibilité qu'une classe qui dérive d'elle le customise, elle
doit définir une nouvelle fonction virtuelle pour le faire
(« template method pattern »). En gros, dans la pratique, on ne
supplante jamais qu'une fonction virtuelle pure.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
1 2 3 4 5