OVH Cloud OVH Cloud

private, private et private

23 réponses
Avatar
Fabien LE LEZ
Bonjour,

Dans certaines classes, j'ai trois types de membres privés :

- des membres "réellement" privés, auxquels aucune autre classe n'a
accès ;
- des déclarations de nouvelles fonctions virtuelles (éventuellement
pures) ;
- des implémentations de fonctions virtuelles d'une classe de base.

Exemple :

class B
{
private:
virtual void f()= 0;
};

class D: public B
{
private:
/*virtual*/ void f(); // Fonction qui vient de B.
void g(); // Fonction spécifique à D.
int une_variable_membre;
virtual void h(); // Fonction que les classes héritant de D.
};

J'aimerais savoir comment vous faites pour distinguer visuellement ces
différent types de membres privés.

Mettez-vous trois sections "private:" différentes, toujours dans le
même ordre ?
Y a-t-il d'autres méthodes ?

Question subsidiaire : spécifiez-vous le "virtual" même quand il est
implicite (comme pour B::f()) ?

Merci d'avance...

3 réponses

1 2 3
Avatar
kanze
Fabien CHÊNE wrote:
"kanze" writes:

Fabien CHÊNE wrote:
James Kanze writes:

[...] le modèle de la programmation par contrat est
assez répandue qu'il l'a sans doute supposé connu. Dans
la pratique, évidemment, la classe ne contient pas que
des fonctions virtuelles pûres, mais aussi des fonctions
non-virtuelles publiques qui les appellent,
[snip]


Qu'appelles-tu "programmation par contrat" ?


Je ne le connais pas d'autre nom. C'est Bertrand Meyer qui
en est l'auteur original je crois.

L'idiome que je reconnais la, est celui de la template
méthode popularisée par Gamma et al.


(Par « template méthode », je suppose que tu veux dire le
modèle template -- le « template pattern » en anglais.


"template methode" (ou "template methode pattern") est le
terme utilisé par Herb Sutter dans les exceptional C++. Je
pensais que c'était suffisament répendu. Mais je ne suis pas
opposé, loin de là, à l'appeler autrement. (Je ne peut pas
m'empêcher de penser qu'un mot tel que customization aurait pu
être utilisé pour désigner ce modèle de conception.)


Je ne me rappelais plus de la terminologie exacte de Herb. Je
sais qu'il l'a rapproché au « template design pattern » du GoF ;
je me suis opposé, parce qu'il s'agit à mon avis de deux choses
différentes. Dans le GoF, c'est « Template Design Pattern », ce
que je traduis par « modèle de template ». (Dans cette
utilisation, la meilleur traduction de « template » serait
« modèle ». Mais « modèle de modèle », ça me laisse froid.) Si
Herb y a ajouté « method », c'est encore pire, parce que
précisement, dans le modèle, ce n'est pas lié à une fonction
unique.

Quant à la possibilité de l'appeler « customisation », pourquoi
pas ? Mais comment distinguer alors entre la customisation au
moyen des fonctions virtuelles supplantées dans une classe
dérivée, et la customisation au moyen d'un délégué (ce que le
GoF appelle le modèle stratégie, je crois -- mais je m'en
servais bien avant le GoF).

Je t'en prie, pas encore une autre signification pour «
méthode ».)


Ah bon, il y en a une autre ? ;)


J'utilisais le mèthode Booch dans le temps. Le mot « méthode »,
pour moi, se rapproche à la méthodologie.

Dans d'autres langages, on s'en sert pour signifier une
fonction. Ce qui prète parfois à la confusion, mais en général
le contexte permet à distinguer. Ici, tu t'en sers comme
traduction de « pattern ». C'est trop.

[...]
Au temps pour moi. Peut-on parvenir à séparer logiquement les
préconditions/postconditions, des invariants d'une classe ?


Je ne suis pas trop sûr ce que tu entends par « séparer
logiquement ». Les pré- et les postconditions concernent surtout
les fonctions ; les invariants, la classe (mais évidemment, les
invariants de la classe sont à la fois pré- et post-conditions
de toute fonction membre). Quand je vérifie les invariants, je
le fais toujours au moyen d'une fonction « checkInvariants() »
(qui aborte le cas où). Une fonction avec toutes ces
vérifications serait donc :

ReturnType someOperation( ParamType param )
{
checkInvariants() ;
assert( preconditions ) ;
ReturnType result = doSomeOperation( param ) ;
checkInvariants() ;
assert( postconditions ) ;
return result ;
}

Dans la pratique, la plupart de mes classes sont assez simple,
avec des invariants plutôt triviaux -- et je m'en passe souvent
des vérifications. En ce qui concerne les post-conditions, il
n'ont une signification que pour les fonctions non-const ; qui
en général ne renvoient rien, ce qui simplifie la charpente de
fonction ci-dessus.

[...]
Et je te rejoins surement quand, à un autre endroit dans ce
fil, tu dis ne pas trop utiliser le modèle de template. Je
pense que tu leur préfèrent alors les Mixins.


Je préfère en général les délégués. Je crois que les mixins,
c'est une forme extrème du modèle template -- c'est toujours à
travers des fonctions virtuelles de la classe de base qu'on
customise. Sans vouloir l'ériger en règle absolue, je me suis
servi des mixins que dans le cas où il y avait plusieurs
dégrées de customisation, ET que chaque dégrée était
fermée, avec un choix assez réduit des possibilités. Souvent, en
fait, j'ai introduit une classe supplémentaire pour chaque
dégrée, pour rendre la séparation plus visible. Quelque chose
du genre :

class Base
{
public:
// ...
private:
virtual void doA() = 0 ; // dégrée A...
virtual void doB() = 0 ; // dégrée B...
} ;

class A : public virtual Base
{
private:
virtual void doA() = 0 ; // dégrée A...
} ;

class B : public virtual Base
{
private:
virtual void doB() = 0 ; // dégrée B...
} ;

class Aa : public A
{
private:
virtual void doA() ; // variant a de A...
} ;

class Ab : public A
{
private:
virtual void doA() ; // variant b de A...
} ;

// la même chose pour B...

template< typename TypeA, typename TypeB >
class Concrete : public virtual Base, private TypeA, private TypeB
{
public:
// Que des constructeurs...
} ;

Les classes intermédiaire A et B ne font rien, à part
éventuellement assurer que l'héritage de Base est virtuel.
L'intérêt, en revanche, c'est qu'en héritant de A, je déclare au
lecteur que j'implémente la customisation de la dégrée A.
Aujourd'hui, en plus, j'utiliserais peut-être de la
méta-programmation pour imposer des contraintes dans le
template, que TypeA dérive de A et que TypeB dérive de B.

Note qu'en C++, il y a un contraint majeur dans toutes les
variantes du modèle template : la customisation n'est active
qu'une fois le constructeur terminé. Tu ne peux pas t'en servir
dans le constructeur de la classe de base. L'utilisation d'un
délégué règle ce problème (la plupart du temps, au prix d'une
allocation dynamique en plus).

[...]
Question subsidiaire : est-il imaginable de faire de la
programmation par contrat, tout en utilisant la méthode de
template ou les Mixins ? Ces deux choses m'ont l'air a priori
orthogonales.


Tout à fait.

En supposant qu'il s'agit d'une implémentation de B qui
lui-même utilise le modèle de template : conceptuellement, f() e st
^^^^^^^^^^^^^^^^^^^^^^^


Est-ce la traduction de template méthode ?


J'utilise le mot « modèle » assez systèmatiquement comme
traduction de « pattern » (dans « design pattern »). Le « mod èle
de template », c'est le « template pattern ».


Et moi, je traduis souvent template par modèle. Ce qui fait
que modèle de template me parait pour le moins abstrait.


Comme j'ai dit ci-dessus, si on se sert de la meilleur
traduction de chaque mot, on arrive à « modèle de modèle ». Le
problème ici, c'est que et « pattern » et « template » sont des
mots très précis en anglais, qui correspond à une utilisation
spécifique du mot français « modèle ». Je ne connais pas de mots
équivalents avec autant de précision en français.

Il faut dire que dans ce contexte, même l'utilisation du mot
«@template » en anglais est un détournement -- en dehors de
l'informatique, un template, ce n'est rien d'autre qu'un
pochoir. L'utilisation pour des documents, etc., est une
extention propre à l'informatique, et l'utilisation dans le C++
ou ici comme nom d'un modèle, c'est une extension de cette
extension. Étant donné que même en anglais, la signification est
tellement éloignée de sa signification de base, ça ne me gène
pas trop de l'utiliser tel quel en français -- ça ne me gènerait
pas non plus de le franciser en « templet », ni d'utiliser
pochoir, comme emprunt sémantique. Le problème, c'est que modèle
c'est bien établi pour les documents, mais qu'il manque de
précision, et pose des problèmes dans ce contexte précis.

--
James Kanze GABI Software
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




Avatar
fabien.chene.nospam
"kanze" writes:

"template methode" (ou "template methode pattern") est le
terme utilisé par Herb Sutter dans les exceptional C++. Je
pensais que c'était suffisament répendu. Mais je ne suis pas
opposé, loin de là, à l'appeler autrement. (Je ne peut pas
m'empêcher de penser qu'un mot tel que customization aurait pu
être utilisé pour désigner ce modèle de conception.)


Je ne me rappelais plus de la terminologie exacte de Herb. Je
sais qu'il l'a rapproché au « template design pattern » du GoF ;
je me suis opposé, parce qu'il s'agit à mon avis de deux choses
différentes. Dans le GoF, c'est « Template Design Pattern », ce
que je traduis par « modèle de template ». (Dans cette
utilisation, la meilleur traduction de « template » serait
« modèle ». Mais « modèle de modèle », ça me laisse froid.) Si
Herb y a ajouté « method », c'est encore pire, parce que
précisement, dans le modèle, ce n'est pas lié à une fonction
unique.

Quant à la possibilité de l'appeler « customisation », pourquoi
pas ? Mais comment distinguer alors entre la customisation au
moyen des fonctions virtuelles supplantées dans une classe
dérivée, et la customisation au moyen d'un délégué (ce que le
GoF appelle le modèle stratégie, je crois -- mais je m'en
servais bien avant le GoF).


Customisation par fonction virtuelle, customisation par délégués.
Mais bon, on continuera vraisemblablement de se coltiner des "modèdes
de méthodes templates" ou autres atrocitées du même tonneau.

Je t'en prie, pas encore une autre signification pour «
méthode ».)


Ah bon, il y en a une autre ? ;)


J'utilisais le mèthode Booch dans le temps. Le mot « méthode »,
pour moi, se rapproche à la méthodologie.

Dans d'autres langages, on s'en sert pour signifier une
fonction. Ce qui prète parfois à la confusion, mais en général
le contexte permet à distinguer.


Il y a des cas où le contexte ne suffit pas pour distinguer fonction
membre, de fonction virtuelle.

[...]
Au temps pour moi. Peut-on parvenir à séparer logiquement les
préconditions/postconditions, des invariants d'une classe ?


Je ne suis pas trop sûr ce que tu entends par « séparer
logiquement ». Les pré- et les postconditions concernent surtout
les fonctions ; les invariants, la classe (mais évidemment, les
invariants de la classe sont à la fois pré- et post-conditions
de toute fonction membre). Quand je vérifie les invariants, je
le fais toujours au moyen d'une fonction « checkInvariants() »
(qui aborte le cas où). Une fonction avec toutes ces
vérifications serait donc :

ReturnType someOperation( ParamType param )
{
checkInvariants() ;
assert( preconditions ) ;
ReturnType result = doSomeOperation( param ) ;
checkInvariants() ;
assert( postconditions ) ;
return result ;
}

Dans la pratique, la plupart de mes classes sont assez simple,
avec des invariants plutôt triviaux -- et je m'en passe souvent
des vérifications. En ce qui concerne les post-conditions, il
n'ont une signification que pour les fonctions non-const ; qui
en général ne renvoient rien, ce qui simplifie la charpente de
fonction ci-dessus.


Merci pour l'exemple et la clarification.

[...]
Et je te rejoins surement quand, à un autre endroit dans ce
fil, tu dis ne pas trop utiliser le modèle de template. Je
pense que tu leur préfèrent alors les Mixins.


Je préfère en général les délégués. Je crois que les mixins,
c'est une forme extrème du modèle template -- c'est toujours à
travers des fonctions virtuelles de la classe de base qu'on
customise.


Je crois que mon utilisation des délégués révèlent d'avantage du réflexe
Pavlovien que de situations propices à l'application de ce pattern.
Disons que je ne crée pas une hiérarchie de classe dans le seul but
d'appliquer le modèle stratégie.

Pour les mixins, je les vois plutôt comme une factorisation de code
ingénieuse du modèle template. Je m'en sers uniquement en tant que tel
-- et le préfère au modèle template.


Note qu'en C++, il y a un contraint majeur dans toutes les
variantes du modèle template : la customisation n'est active
qu'une fois le constructeur terminé. Tu ne peux pas t'en servir
dans le constructeur de la classe de base. L'utilisation d'un
délégué règle ce problème (la plupart du temps, au prix d'une
allocation dynamique en plus).


C'est peut-être ce qui me conditionne à utiliser le modèle stratégie,
après réflexion :)


--
Fab



Avatar
Arnaud Meurgues
James Kanze wrote:

J'avais trouvé cela convainquant à l'époque et l'ai adopté
pour mon propre code.
[...]


le procès de développement n'est pas parfait. Et évidemment, si
tu produis les bibliothèques qui doivent servir en dehors de ta
société, tu ne peux absolument pas permettre une telle chose
dans les en-têtes que tu livres.)


Hélas. C'est pourquoi je ne parle que de « mon propre code ». Mais
j'apprécie beaucoup le confort de cette solution.

--
Arnaud


1 2 3