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) ;
class D: public B {
private:
/*virtual*/ void f(); // Fonction qui vient de B.
virtual void h(); // Fonction que les classes héritant de D.
};
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) ;
class D: public B {
private:
/*virtual*/ void f(); // Fonction qui vient de B.
virtual void h(); // Fonction que les classes héritant de D.
};
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) ;
class D: public B {
private:
/*virtual*/ void f(); // Fonction qui vient de B.
virtual void h(); // Fonction que les classes héritant de D.
};
Fabien LE LEZ wrote on 28/04/2006 06:08:
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 ;
celles-ci sont claires/évidentes.
- des déclarations de nouvelles fonctions virtuelles
(éventuellement pures) ;
là je ne comprends pas le but.
en reprenant ton exemple:
class B {
private:
virtual void f() = null;
};
- B ne peux pas être instancée,
- toute classe fille devra définir f() mais ne pourra pas
appeler la méthode parent (pour une fille ayant un parent la
définissant),
- les utilisateurs de B (et descendants) n'auront jamais accès à f()
dès lors:
le sens d'une virtuelle privée continue à rester confus dans
les commentaires même de ton second exemple:
class D: public B {
private:
/*virtual*/ void f(); // Fonction qui vient de B.
virtual void h(); // Fonction que les classes héritant de D.
};
f() "qui vient de B" pourrait laisser comprendre qu'en effet
il 'vient' quelque chose, or ici il vient seulement une
absence (une virtualité pure) qui doit être bouchée (définie)
pour pouvoir instancier B
h() "Fonction que les classes héritant de D" (il manque peut
être une suite) - ne pourront pas appeler, - pourront
"surcharger" mais sans avantage/différence par rapport à une
déclaration propre de g(), h(), ...
un membre privé est implicitement masqué ("shadow-isé"), le
rendre virtual ne lève pas ce masquage, que reste-t-il alors
de virtual?
Fabien LE LEZ wrote on 28/04/2006 06:08:
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 ;
celles-ci sont claires/évidentes.
- des déclarations de nouvelles fonctions virtuelles
(éventuellement pures) ;
là je ne comprends pas le but.
en reprenant ton exemple:
class B {
private:
virtual void f() = null;
};
- B ne peux pas être instancée,
- toute classe fille devra définir f() mais ne pourra pas
appeler la méthode parent (pour une fille ayant un parent la
définissant),
- les utilisateurs de B (et descendants) n'auront jamais accès à f()
dès lors:
le sens d'une virtuelle privée continue à rester confus dans
les commentaires même de ton second exemple:
class D: public B {
private:
/*virtual*/ void f(); // Fonction qui vient de B.
virtual void h(); // Fonction que les classes héritant de D.
};
f() "qui vient de B" pourrait laisser comprendre qu'en effet
il 'vient' quelque chose, or ici il vient seulement une
absence (une virtualité pure) qui doit être bouchée (définie)
pour pouvoir instancier B
h() "Fonction que les classes héritant de D" (il manque peut
être une suite) - ne pourront pas appeler, - pourront
"surcharger" mais sans avantage/différence par rapport à une
déclaration propre de g(), h(), ...
un membre privé est implicitement masqué ("shadow-isé"), le
rendre virtual ne lève pas ce masquage, que reste-t-il alors
de virtual?
Fabien LE LEZ wrote on 28/04/2006 06:08:
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 ;
celles-ci sont claires/évidentes.
- des déclarations de nouvelles fonctions virtuelles
(éventuellement pures) ;
là je ne comprends pas le but.
en reprenant ton exemple:
class B {
private:
virtual void f() = null;
};
- B ne peux pas être instancée,
- toute classe fille devra définir f() mais ne pourra pas
appeler la méthode parent (pour une fille ayant un parent la
définissant),
- les utilisateurs de B (et descendants) n'auront jamais accès à f()
dès lors:
le sens d'une virtuelle privée continue à rester confus dans
les commentaires même de ton second exemple:
class D: public B {
private:
/*virtual*/ void f(); // Fonction qui vient de B.
virtual void h(); // Fonction que les classes héritant de D.
};
f() "qui vient de B" pourrait laisser comprendre qu'en effet
il 'vient' quelque chose, or ici il vient seulement une
absence (une virtualité pure) qui doit être bouchée (définie)
pour pouvoir instancier B
h() "Fonction que les classes héritant de D" (il manque peut
être une suite) - ne pourront pas appeler, - pourront
"surcharger" mais sans avantage/différence par rapport à une
déclaration propre de g(), h(), ...
un membre privé est implicitement masqué ("shadow-isé"), le
rendre virtual ne lève pas ce masquage, que reste-t-il alors
de virtual?
merci James, mais ... ma question ne remettait pas en cause des idiomes
C'est sans doute l'idiome de la programmation par contrat.
Certains vont jusqu'à dire que toute fonction virtuelle doit
être privée.
Fabien n'a montré que la partie essentielle à sa question ; 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,
class D: public B {
private:
/*virtual*/ void f(); // Fonction qui vient de B.
virtual void h(); // Fonction que les classes héritant de D.
};
En supposant qu'il s'agit d'une implémentation de B qui lui-même
utilise le modèle de template : conceptuellement, f() est
probablement « invisible » aux classes dérivées -- elle a été
implémentée, et le contrat de B a été rempli. En revanche, les
classes qui dérivent de D sont bien concernées par h() -- c'est
en supplantant h() qu'elles peuvent customiser D.
Pour donner un exemple concret (pas forcément très réaliste,
parce qu'énormement simplifié) :
class GUIComponent{
public :
void draw() const {
doDraw() ;
}
private:
virtual void doDraw() = 0 ;
} ;
class GUIMessage : public GUIComponent {
private: // À supplanter dans les classes dérivées
virtual Color* getBackgroundColor() const {
return &defaultBackgroundColor ;
}
private: // Réelement : en Java, des fonctions final
virtual void doDraw() const
{
// ...
/* ... */ getBackgroundColor() ;
// ...
}
} ;
un membre privé est implicitement masqué ("shadow-isé"), le
rendre virtual ne lève pas ce masquage, que reste-t-il alors
de virtual?
Je ne comprends pas exactement ce que tu essaies à dire. Privé
ou non est orthogonal au masquage -- et virtuelle ou non est
orthogonal aux deux.
merci James, mais ... ma question ne remettait pas en cause des idiomes
C'est sans doute l'idiome de la programmation par contrat.
Certains vont jusqu'à dire que toute fonction virtuelle doit
être privée.
Fabien n'a montré que la partie essentielle à sa question ; 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,
class D: public B {
private:
/*virtual*/ void f(); // Fonction qui vient de B.
virtual void h(); // Fonction que les classes héritant de D.
};
En supposant qu'il s'agit d'une implémentation de B qui lui-même
utilise le modèle de template : conceptuellement, f() est
probablement « invisible » aux classes dérivées -- elle a été
implémentée, et le contrat de B a été rempli. En revanche, les
classes qui dérivent de D sont bien concernées par h() -- c'est
en supplantant h() qu'elles peuvent customiser D.
Pour donner un exemple concret (pas forcément très réaliste,
parce qu'énormement simplifié) :
class GUIComponent{
public :
void draw() const {
doDraw() ;
}
private:
virtual void doDraw() = 0 ;
} ;
class GUIMessage : public GUIComponent {
private: // À supplanter dans les classes dérivées
virtual Color* getBackgroundColor() const {
return &defaultBackgroundColor ;
}
private: // Réelement : en Java, des fonctions final
virtual void doDraw() const
{
// ...
/* ... */ getBackgroundColor() ;
// ...
}
} ;
un membre privé est implicitement masqué ("shadow-isé"), le
rendre virtual ne lève pas ce masquage, que reste-t-il alors
de virtual?
Je ne comprends pas exactement ce que tu essaies à dire. Privé
ou non est orthogonal au masquage -- et virtuelle ou non est
orthogonal aux deux.
merci James, mais ... ma question ne remettait pas en cause des idiomes
C'est sans doute l'idiome de la programmation par contrat.
Certains vont jusqu'à dire que toute fonction virtuelle doit
être privée.
Fabien n'a montré que la partie essentielle à sa question ; 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,
class D: public B {
private:
/*virtual*/ void f(); // Fonction qui vient de B.
virtual void h(); // Fonction que les classes héritant de D.
};
En supposant qu'il s'agit d'une implémentation de B qui lui-même
utilise le modèle de template : conceptuellement, f() est
probablement « invisible » aux classes dérivées -- elle a été
implémentée, et le contrat de B a été rempli. En revanche, les
classes qui dérivent de D sont bien concernées par h() -- c'est
en supplantant h() qu'elles peuvent customiser D.
Pour donner un exemple concret (pas forcément très réaliste,
parce qu'énormement simplifié) :
class GUIComponent{
public :
void draw() const {
doDraw() ;
}
private:
virtual void doDraw() = 0 ;
} ;
class GUIMessage : public GUIComponent {
private: // À supplanter dans les classes dérivées
virtual Color* getBackgroundColor() const {
return &defaultBackgroundColor ;
}
private: // Réelement : en Java, des fonctions final
virtual void doDraw() const
{
// ...
/* ... */ getBackgroundColor() ;
// ...
}
} ;
un membre privé est implicitement masqué ("shadow-isé"), le
rendre virtual ne lève pas ce masquage, que reste-t-il alors
de virtual?
Je ne comprends pas exactement ce que tu essaies à dire. Privé
ou non est orthogonal au masquage -- et virtuelle ou non est
orthogonal aux deux.
James Kanze wrote on 30/04/2006 12:34:
ta méthode clone soulève 2 problèmes (liés au langage ou à des
bugs de compilos) que tu contournes en introduisant un test
sur le type d'instance créé (pour détecter un oubli de
surcharge de doClone dans une classe fille), tel que tu le
codes cela fonctionnera mais forcera un dynamic_cast pour
l'appelant s'il doit vraiment utiliser le clone comme
l'original (y compris pour des fonctions membres non déclarées
dans la classe de base).
or cela illustre une limitation du modifier private, puisque
avec les définitions suivantes (en supposant les csts)
class Base {
public:
Base* clone() {
Base* result = doClone();
assert(typeid(*result) == typeid(*this));
return result;
}
private:
virtual Base* doClone() = null;
};
class Derived : public Base {
private:
virtual Base* doClone() { return new Derived(*this); }
};
class Third : public Derived {
};
l'appel:
Third t;
t.clone();
sera exécuté; ie Base::clone() est appelée, qui appellera
Derived::clone() qui est pourtant private donc inaccessible à
Third - d'où le assert(typeid) au runtime pour pallier ce
point. c'est le problème 1, peut être lié à certains
compilateurs uniquement.
le second problème vient du type retourné par clone; je
préférerais les définitions:
class Base {
public:
virtual Base* clone() = null;
};
class Derived : public Base {
public:
Derived* clone() { return new Derived(*this); }
};
class Third : public Derived {
public:
Third* clone() { return new Third(*this); }
};
ici un dynamic_cast serait économisé, mais (problème 2)
certains compilos ne supportent pas la surcharge du type d'une
fonction.
class D: public B {
private:
/*virtual*/ void f(); // Fonction qui vient de B.
virtual void h(); // Fonction que les classes héritant de D.
};
En supposant qu'il s'agit d'une implémentation de B qui
lui-même utilise le modèle de template : conceptuellement,
f() est probablement « invisible » aux classes dérivées --
elle a été implémentée, et le contrat de B a été rempli. En
revanche, les classes qui dérivent de D sont bien concernées
par h() -- c'est en supplantant h() qu'elles peuvent
customiser D.
je suis évidemment d'accord avec ça -- je reformule ma
question plus simplement: est-on toujours vraiment certain de
savoir ce qui a le droit d'être appelé par une classe fille et
ce qui doit être accessible qu'à une seule classe ? ou encore
n'est-il pas plus sage de se laisser la possibilité d'invoquer
des services parents ? (mes conjectures et spéculations sur ce
qui ne "les" regarde pas a très souvent été contredit par
l'expérience...).
en reprenant ton exemple de composant d'UI, est-ce vraiment
indispensable de chaque classe fille doive définir son
getBackgroundColor() ?
j'aurais plutot envie d'avancer le contraire: une classe
parent (type Component) définit une couleur de fond standard
conforme au skin/thème/système et chaque controle comme chaque
Container (ayant une vocation spécifique) /peut/ (et non doit)
redéfinir cette couleur.
j'aurais plutôt envie de dire (de manière approximative, soit):
- une fonction virtuelle doit être privée si elle participe à
une tache simple définie une fois pour toute (ta méthode "f",
les méthodes overflow, undeflow de B.S.)
- une fonction virtuelle doit être protected si elle participe
à une tache complexe impliquant de nombreuses autres méthodes
surchargées ou non.
Pour donner un exemple concret (pas forcément très réaliste,
parce qu'énormement simplifié) :
class GUIComponent{
public :
void draw() const {
doDraw() ;
}
private:
virtual void doDraw() = 0 ;
} ;
class GUIMessage : public GUIComponent {
private: // À supplanter dans les classes dérivées
virtual Color* getBackgroundColor() const {
return &defaultBackgroundColor ;
}
private: // Réelement : en Java, des fonctions final
virtual void doDraw() const
{
// ...
/* ... */ getBackgroundColor() ;
// ...
}
} ;
private doDraw ne me parait pas pertinent car il prive de la
possibilité de le surcharger en l'invoquant dans la nouvelle
classe - pourquoi estimer que 'son' implémentation est la
meilleure qui ne méritera jamais le moindre ajout ?, pourquoi
obliger l'auteur d'une nouvelle classe a tout recoder ?
final doDraw ne laisse également perplexe, c'est la méthode
draw qui est vue de l'extérieur,
non doDraw, un final draw forcerait l'utilisation de doDraw et
lui seul (et donc sa redéfinition complète);
ici il suffira de surcharger draw et qu'importe le caractère
final de doDraw
- ce qui d'ailleurs n'est pas contradictoire avec ta
présentation, on peut lire en effet que draw() ne dépends que
d'un doDraw final et que tant que celui-ci est pertinent, il
ne regarde personne de savoir ce qu'il fait en interne; c'est
plus le fait de rendre privé toutes les sous méthodes
utilitaires de doDraw (getBkClr, ...) qui me gène.
un membre privé est implicitement masqué ("shadow-isé"),
le rendre virtual ne lève pas ce masquage, que reste-t-il
alors de virtual?
Je ne comprends pas exactement ce que tu essaies à dire.
Privé ou non est orthogonal au masquage -- et virtuelle ou
non est orthogonal aux deux.
j'aurais du dire "ne renforce pas" la masquage (l'interdiction
de l'appel direct à la fonction d'une classe de base n'est pas
renforcé par l'ajout de virtual puisqu'il est déjà empéché par
l'attribut private).
James Kanze wrote on 30/04/2006 12:34:
ta méthode clone soulève 2 problèmes (liés au langage ou à des
bugs de compilos) que tu contournes en introduisant un test
sur le type d'instance créé (pour détecter un oubli de
surcharge de doClone dans une classe fille), tel que tu le
codes cela fonctionnera mais forcera un dynamic_cast pour
l'appelant s'il doit vraiment utiliser le clone comme
l'original (y compris pour des fonctions membres non déclarées
dans la classe de base).
or cela illustre une limitation du modifier private, puisque
avec les définitions suivantes (en supposant les csts)
class Base {
public:
Base* clone() {
Base* result = doClone();
assert(typeid(*result) == typeid(*this));
return result;
}
private:
virtual Base* doClone() = null;
};
class Derived : public Base {
private:
virtual Base* doClone() { return new Derived(*this); }
};
class Third : public Derived {
};
l'appel:
Third t;
t.clone();
sera exécuté; ie Base::clone() est appelée, qui appellera
Derived::clone() qui est pourtant private donc inaccessible à
Third - d'où le assert(typeid) au runtime pour pallier ce
point. c'est le problème 1, peut être lié à certains
compilateurs uniquement.
le second problème vient du type retourné par clone; je
préférerais les définitions:
class Base {
public:
virtual Base* clone() = null;
};
class Derived : public Base {
public:
Derived* clone() { return new Derived(*this); }
};
class Third : public Derived {
public:
Third* clone() { return new Third(*this); }
};
ici un dynamic_cast serait économisé, mais (problème 2)
certains compilos ne supportent pas la surcharge du type d'une
fonction.
class D: public B {
private:
/*virtual*/ void f(); // Fonction qui vient de B.
virtual void h(); // Fonction que les classes héritant de D.
};
En supposant qu'il s'agit d'une implémentation de B qui
lui-même utilise le modèle de template : conceptuellement,
f() est probablement « invisible » aux classes dérivées --
elle a été implémentée, et le contrat de B a été rempli. En
revanche, les classes qui dérivent de D sont bien concernées
par h() -- c'est en supplantant h() qu'elles peuvent
customiser D.
je suis évidemment d'accord avec ça -- je reformule ma
question plus simplement: est-on toujours vraiment certain de
savoir ce qui a le droit d'être appelé par une classe fille et
ce qui doit être accessible qu'à une seule classe ? ou encore
n'est-il pas plus sage de se laisser la possibilité d'invoquer
des services parents ? (mes conjectures et spéculations sur ce
qui ne "les" regarde pas a très souvent été contredit par
l'expérience...).
en reprenant ton exemple de composant d'UI, est-ce vraiment
indispensable de chaque classe fille doive définir son
getBackgroundColor() ?
j'aurais plutot envie d'avancer le contraire: une classe
parent (type Component) définit une couleur de fond standard
conforme au skin/thème/système et chaque controle comme chaque
Container (ayant une vocation spécifique) /peut/ (et non doit)
redéfinir cette couleur.
j'aurais plutôt envie de dire (de manière approximative, soit):
- une fonction virtuelle doit être privée si elle participe à
une tache simple définie une fois pour toute (ta méthode "f",
les méthodes overflow, undeflow de B.S.)
- une fonction virtuelle doit être protected si elle participe
à une tache complexe impliquant de nombreuses autres méthodes
surchargées ou non.
Pour donner un exemple concret (pas forcément très réaliste,
parce qu'énormement simplifié) :
class GUIComponent{
public :
void draw() const {
doDraw() ;
}
private:
virtual void doDraw() = 0 ;
} ;
class GUIMessage : public GUIComponent {
private: // À supplanter dans les classes dérivées
virtual Color* getBackgroundColor() const {
return &defaultBackgroundColor ;
}
private: // Réelement : en Java, des fonctions final
virtual void doDraw() const
{
// ...
/* ... */ getBackgroundColor() ;
// ...
}
} ;
private doDraw ne me parait pas pertinent car il prive de la
possibilité de le surcharger en l'invoquant dans la nouvelle
classe - pourquoi estimer que 'son' implémentation est la
meilleure qui ne méritera jamais le moindre ajout ?, pourquoi
obliger l'auteur d'une nouvelle classe a tout recoder ?
final doDraw ne laisse également perplexe, c'est la méthode
draw qui est vue de l'extérieur,
non doDraw, un final draw forcerait l'utilisation de doDraw et
lui seul (et donc sa redéfinition complète);
ici il suffira de surcharger draw et qu'importe le caractère
final de doDraw
- ce qui d'ailleurs n'est pas contradictoire avec ta
présentation, on peut lire en effet que draw() ne dépends que
d'un doDraw final et que tant que celui-ci est pertinent, il
ne regarde personne de savoir ce qu'il fait en interne; c'est
plus le fait de rendre privé toutes les sous méthodes
utilitaires de doDraw (getBkClr, ...) qui me gène.
un membre privé est implicitement masqué ("shadow-isé"),
le rendre virtual ne lève pas ce masquage, que reste-t-il
alors de virtual?
Je ne comprends pas exactement ce que tu essaies à dire.
Privé ou non est orthogonal au masquage -- et virtuelle ou
non est orthogonal aux deux.
j'aurais du dire "ne renforce pas" la masquage (l'interdiction
de l'appel direct à la fonction d'une classe de base n'est pas
renforcé par l'ajout de virtual puisqu'il est déjà empéché par
l'attribut private).
James Kanze wrote on 30/04/2006 12:34:
ta méthode clone soulève 2 problèmes (liés au langage ou à des
bugs de compilos) que tu contournes en introduisant un test
sur le type d'instance créé (pour détecter un oubli de
surcharge de doClone dans une classe fille), tel que tu le
codes cela fonctionnera mais forcera un dynamic_cast pour
l'appelant s'il doit vraiment utiliser le clone comme
l'original (y compris pour des fonctions membres non déclarées
dans la classe de base).
or cela illustre une limitation du modifier private, puisque
avec les définitions suivantes (en supposant les csts)
class Base {
public:
Base* clone() {
Base* result = doClone();
assert(typeid(*result) == typeid(*this));
return result;
}
private:
virtual Base* doClone() = null;
};
class Derived : public Base {
private:
virtual Base* doClone() { return new Derived(*this); }
};
class Third : public Derived {
};
l'appel:
Third t;
t.clone();
sera exécuté; ie Base::clone() est appelée, qui appellera
Derived::clone() qui est pourtant private donc inaccessible à
Third - d'où le assert(typeid) au runtime pour pallier ce
point. c'est le problème 1, peut être lié à certains
compilateurs uniquement.
le second problème vient du type retourné par clone; je
préférerais les définitions:
class Base {
public:
virtual Base* clone() = null;
};
class Derived : public Base {
public:
Derived* clone() { return new Derived(*this); }
};
class Third : public Derived {
public:
Third* clone() { return new Third(*this); }
};
ici un dynamic_cast serait économisé, mais (problème 2)
certains compilos ne supportent pas la surcharge du type d'une
fonction.
class D: public B {
private:
/*virtual*/ void f(); // Fonction qui vient de B.
virtual void h(); // Fonction que les classes héritant de D.
};
En supposant qu'il s'agit d'une implémentation de B qui
lui-même utilise le modèle de template : conceptuellement,
f() est probablement « invisible » aux classes dérivées --
elle a été implémentée, et le contrat de B a été rempli. En
revanche, les classes qui dérivent de D sont bien concernées
par h() -- c'est en supplantant h() qu'elles peuvent
customiser D.
je suis évidemment d'accord avec ça -- je reformule ma
question plus simplement: est-on toujours vraiment certain de
savoir ce qui a le droit d'être appelé par une classe fille et
ce qui doit être accessible qu'à une seule classe ? ou encore
n'est-il pas plus sage de se laisser la possibilité d'invoquer
des services parents ? (mes conjectures et spéculations sur ce
qui ne "les" regarde pas a très souvent été contredit par
l'expérience...).
en reprenant ton exemple de composant d'UI, est-ce vraiment
indispensable de chaque classe fille doive définir son
getBackgroundColor() ?
j'aurais plutot envie d'avancer le contraire: une classe
parent (type Component) définit une couleur de fond standard
conforme au skin/thème/système et chaque controle comme chaque
Container (ayant une vocation spécifique) /peut/ (et non doit)
redéfinir cette couleur.
j'aurais plutôt envie de dire (de manière approximative, soit):
- une fonction virtuelle doit être privée si elle participe à
une tache simple définie une fois pour toute (ta méthode "f",
les méthodes overflow, undeflow de B.S.)
- une fonction virtuelle doit être protected si elle participe
à une tache complexe impliquant de nombreuses autres méthodes
surchargées ou non.
Pour donner un exemple concret (pas forcément très réaliste,
parce qu'énormement simplifié) :
class GUIComponent{
public :
void draw() const {
doDraw() ;
}
private:
virtual void doDraw() = 0 ;
} ;
class GUIMessage : public GUIComponent {
private: // À supplanter dans les classes dérivées
virtual Color* getBackgroundColor() const {
return &defaultBackgroundColor ;
}
private: // Réelement : en Java, des fonctions final
virtual void doDraw() const
{
// ...
/* ... */ getBackgroundColor() ;
// ...
}
} ;
private doDraw ne me parait pas pertinent car il prive de la
possibilité de le surcharger en l'invoquant dans la nouvelle
classe - pourquoi estimer que 'son' implémentation est la
meilleure qui ne méritera jamais le moindre ajout ?, pourquoi
obliger l'auteur d'une nouvelle classe a tout recoder ?
final doDraw ne laisse également perplexe, c'est la méthode
draw qui est vue de l'extérieur,
non doDraw, un final draw forcerait l'utilisation de doDraw et
lui seul (et donc sa redéfinition complète);
ici il suffira de surcharger draw et qu'importe le caractère
final de doDraw
- ce qui d'ailleurs n'est pas contradictoire avec ta
présentation, on peut lire en effet que draw() ne dépends que
d'un doDraw final et que tant que celui-ci est pertinent, il
ne regarde personne de savoir ce qu'il fait en interne; c'est
plus le fait de rendre privé toutes les sous méthodes
utilitaires de doDraw (getBkClr, ...) qui me gène.
un membre privé est implicitement masqué ("shadow-isé"),
le rendre virtual ne lève pas ce masquage, que reste-t-il
alors de virtual?
Je ne comprends pas exactement ce que tu essaies à dire.
Privé ou non est orthogonal au masquage -- et virtuelle ou
non est orthogonal aux deux.
j'aurais du dire "ne renforce pas" la masquage (l'interdiction
de l'appel direct à la fonction d'une classe de base n'est pas
renforcé par l'ajout de virtual puisqu'il est déjà empéché par
l'attribut private).
[...] 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]
Le problème, c'est que Fabien a supposé qu'on reconnaît les
idiomes et les modèles d'où il a extrait ces exemples. Si on ne
connaît pas bien le GoF, ou les autres idiomes courants en C++,
c'est vrai que les extraits qu'il a présenté n'ont pas de sens.
[snip]
En supposant qu'il s'agit d'une implémentation de B qui
lui-même utilise le modèle de template : conceptuellement, f() est
^^^^^^^^^^^^^^^^^^^^^^^
probablement « invisible » aux classes dérivées -- elle a été
implémentée, et le contrat de B a été rempli.
[...] 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]
Le problème, c'est que Fabien a supposé qu'on reconnaît les
idiomes et les modèles d'où il a extrait ces exemples. Si on ne
connaît pas bien le GoF, ou les autres idiomes courants en C++,
c'est vrai que les extraits qu'il a présenté n'ont pas de sens.
[snip]
En supposant qu'il s'agit d'une implémentation de B qui
lui-même utilise le modèle de template : conceptuellement, f() est
^^^^^^^^^^^^^^^^^^^^^^^
probablement « invisible » aux classes dérivées -- elle a été
implémentée, et le contrat de B a été rempli.
[...] 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]
Le problème, c'est que Fabien a supposé qu'on reconnaît les
idiomes et les modèles d'où il a extrait ces exemples. Si on ne
connaît pas bien le GoF, ou les autres idiomes courants en C++,
c'est vrai que les extraits qu'il a présenté n'ont pas de sens.
[snip]
En supposant qu'il s'agit d'une implémentation de B qui
lui-même utilise le modèle de template : conceptuellement, f() est
^^^^^^^^^^^^^^^^^^^^^^^
probablement « invisible » aux classes dérivées -- elle a été
implémentée, et le contrat de B a été rempli.
Je ne trouve pas "programmation par contrat" dans ce que j'assimile à
goF -- via google.
Je ne trouve pas "programmation par contrat" dans ce que j'assimile à
goF -- via google.
Je ne trouve pas "programmation par contrat" dans ce que j'assimile à
goF -- via google.
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" ?
L'idiome que je reconnais la, est celui de la template méthode
popularisée par Gamma et al.
Accessoirement, Quel est l'origine du terme "programmation par
contrat" ?
Je n'ai pas l'impression que cela désigne les vérifications de
pré/post-conditions, maintenance d'invariants, etc comme on le
trouve dans d'autres langages (voire même dans les papiers
pour C++0X).
De là à en déduire qu'il est aussi bien nommé que l'est
*template* méthode ? :)
Le problème, c'est que Fabien a supposé qu'on reconnaît les
idiomes et les modèles d'où il a extrait ces exemples. Si on
ne connaît pas bien le GoF, ou les autres idiomes courants
en C++, c'est vrai que les extraits qu'il a présenté n'ont
pas de sens. [snip]
Je ne trouve pas "programmation par contrat" dans ce que
j'assimile à goF -- via google.
En supposant qu'il s'agit d'une implémentation de B qui
lui-même utilise le modèle de template : conceptuellement, f() est
^^^^^^^^^^^^^^^^^^^^^^^
Est-ce la traduction de template méthode ?
James Kanze <kanze.james@neuf.fr> 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" ?
L'idiome que je reconnais la, est celui de la template méthode
popularisée par Gamma et al.
Accessoirement, Quel est l'origine du terme "programmation par
contrat" ?
Je n'ai pas l'impression que cela désigne les vérifications de
pré/post-conditions, maintenance d'invariants, etc comme on le
trouve dans d'autres langages (voire même dans les papiers
pour C++0X).
De là à en déduire qu'il est aussi bien nommé que l'est
*template* méthode ? :)
Le problème, c'est que Fabien a supposé qu'on reconnaît les
idiomes et les modèles d'où il a extrait ces exemples. Si on
ne connaît pas bien le GoF, ou les autres idiomes courants
en C++, c'est vrai que les extraits qu'il a présenté n'ont
pas de sens. [snip]
Je ne trouve pas "programmation par contrat" dans ce que
j'assimile à goF -- via google.
En supposant qu'il s'agit d'une implémentation de B qui
lui-même utilise le modèle de template : conceptuellement, f() est
^^^^^^^^^^^^^^^^^^^^^^^
Est-ce la traduction de template méthode ?
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" ?
L'idiome que je reconnais la, est celui de la template méthode
popularisée par Gamma et al.
Accessoirement, Quel est l'origine du terme "programmation par
contrat" ?
Je n'ai pas l'impression que cela désigne les vérifications de
pré/post-conditions, maintenance d'invariants, etc comme on le
trouve dans d'autres langages (voire même dans les papiers
pour C++0X).
De là à en déduire qu'il est aussi bien nommé que l'est
*template* méthode ? :)
Le problème, c'est que Fabien a supposé qu'on reconnaît les
idiomes et les modèles d'où il a extrait ces exemples. Si on
ne connaît pas bien le GoF, ou les autres idiomes courants
en C++, c'est vrai que les extraits qu'il a présenté n'ont
pas de sens. [snip]
Je ne trouve pas "programmation par contrat" dans ce que
j'assimile à goF -- via google.
En supposant qu'il s'agit d'une implémentation de B qui
lui-même utilise le modèle de template : conceptuellement, f() est
^^^^^^^^^^^^^^^^^^^^^^^
Est-ce la traduction de template méthode ?
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.
Je t'en prie, pas encore une autre signification pour « méthode ».)
Ce n'est pas vraiment la même chose. Supérficiellement, oui,
mais la finalité en est bien différente. Quand je définis un
contrat dans une classe de base, cette classe est
conceptuellement une interface ; elle n'a pas de comportement
propre à elle. Tandis que dans le modèle de template, le gros du
comportement se trouve dans la classe de base ; les fonctions
virtuelles ne servent qu'à une « customisation » d'un
comportement déjà assez bien défini.
Accessoirement, Quel est l'origine du terme "programmation par
contrat" ?
Autant que je sache, c'est bien Bertrand Meyer qui l'a conçu. Au
départ, il parlait de « design by contract », mais ensuite, il
en a fait une marque déposée. Moi, je l'avais traduit en
« programming by contract » très tôt, parce que je l'implémente
au niveau du programme ; je ne crois pas que j'en suis seul, ni
que j'en étais le premier à faire ce changement. Dans le langage
D, Walter Bright utilise l'expression « contract programming ».Je n'ai pas l'impression que cela désigne les vérifications de
pré/post-conditions, maintenance d'invariants, etc comme on le
trouve dans d'autres langages (voire même dans les papiers
pour C++0X).
Bien sûr que si. En fait, la technique en question ici, c'est
une technique que j'ai développé exprès pour émuler les
contraints d'Eiffel, en réponse aux questions posées dans
comp.lang.c++.moderated. (À vrai dire, je suis sûr que j'ai vue
une suggestion de l'idée avant. Mais je n'arrive pas à en
trouver la moindre référence. Alors, en attendant, j'en suis
plus ou moins réconnu comme l'auteur de la technique en C++.)
De là à en déduire qu'il est aussi bien nommé que l'est
*template* méthode ? :)
Je tiens à la distinction, malgré les ressemblances
supérficielles. Mais tous les auteurs ne le font pas ; Herb
Sutter confond allegrement les deux concepts, par exemple. Comme
j'ai dit, la différence, ce n'est pas tellement ce que tu fais,
mais pourquoi. Si les fonctions non virtuelles sont là pour
valider le contrat, c'est de la programmation par contrat ; si
elles contiennent la charpente d'une implémentation, voire plus,
c'est le modèle de template.
En supposant qu'il s'agit d'une implémentation de B qui
lui-même utilise le modèle de template : conceptuellement, f() est
^^^^^^^^^^^^^^^^^^^^^^^
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 ».
Fabien CHÊNE wrote:
James Kanze <kanze.james@neuf.fr> 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.
Je t'en prie, pas encore une autre signification pour « méthode ».)
Ce n'est pas vraiment la même chose. Supérficiellement, oui,
mais la finalité en est bien différente. Quand je définis un
contrat dans une classe de base, cette classe est
conceptuellement une interface ; elle n'a pas de comportement
propre à elle. Tandis que dans le modèle de template, le gros du
comportement se trouve dans la classe de base ; les fonctions
virtuelles ne servent qu'à une « customisation » d'un
comportement déjà assez bien défini.
Accessoirement, Quel est l'origine du terme "programmation par
contrat" ?
Autant que je sache, c'est bien Bertrand Meyer qui l'a conçu. Au
départ, il parlait de « design by contract », mais ensuite, il
en a fait une marque déposée. Moi, je l'avais traduit en
« programming by contract » très tôt, parce que je l'implémente
au niveau du programme ; je ne crois pas que j'en suis seul, ni
que j'en étais le premier à faire ce changement. Dans le langage
D, Walter Bright utilise l'expression « contract programming ».
Je n'ai pas l'impression que cela désigne les vérifications de
pré/post-conditions, maintenance d'invariants, etc comme on le
trouve dans d'autres langages (voire même dans les papiers
pour C++0X).
Bien sûr que si. En fait, la technique en question ici, c'est
une technique que j'ai développé exprès pour émuler les
contraints d'Eiffel, en réponse aux questions posées dans
comp.lang.c++.moderated. (À vrai dire, je suis sûr que j'ai vue
une suggestion de l'idée avant. Mais je n'arrive pas à en
trouver la moindre référence. Alors, en attendant, j'en suis
plus ou moins réconnu comme l'auteur de la technique en C++.)
De là à en déduire qu'il est aussi bien nommé que l'est
*template* méthode ? :)
Je tiens à la distinction, malgré les ressemblances
supérficielles. Mais tous les auteurs ne le font pas ; Herb
Sutter confond allegrement les deux concepts, par exemple. Comme
j'ai dit, la différence, ce n'est pas tellement ce que tu fais,
mais pourquoi. Si les fonctions non virtuelles sont là pour
valider le contrat, c'est de la programmation par contrat ; si
elles contiennent la charpente d'une implémentation, voire plus,
c'est le modèle de template.
En supposant qu'il s'agit d'une implémentation de B qui
lui-même utilise le modèle de template : conceptuellement, f() est
^^^^^^^^^^^^^^^^^^^^^^^
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 ».
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.
Je t'en prie, pas encore une autre signification pour « méthode ».)
Ce n'est pas vraiment la même chose. Supérficiellement, oui,
mais la finalité en est bien différente. Quand je définis un
contrat dans une classe de base, cette classe est
conceptuellement une interface ; elle n'a pas de comportement
propre à elle. Tandis que dans le modèle de template, le gros du
comportement se trouve dans la classe de base ; les fonctions
virtuelles ne servent qu'à une « customisation » d'un
comportement déjà assez bien défini.
Accessoirement, Quel est l'origine du terme "programmation par
contrat" ?
Autant que je sache, c'est bien Bertrand Meyer qui l'a conçu. Au
départ, il parlait de « design by contract », mais ensuite, il
en a fait une marque déposée. Moi, je l'avais traduit en
« programming by contract » très tôt, parce que je l'implémente
au niveau du programme ; je ne crois pas que j'en suis seul, ni
que j'en étais le premier à faire ce changement. Dans le langage
D, Walter Bright utilise l'expression « contract programming ».Je n'ai pas l'impression que cela désigne les vérifications de
pré/post-conditions, maintenance d'invariants, etc comme on le
trouve dans d'autres langages (voire même dans les papiers
pour C++0X).
Bien sûr que si. En fait, la technique en question ici, c'est
une technique que j'ai développé exprès pour émuler les
contraints d'Eiffel, en réponse aux questions posées dans
comp.lang.c++.moderated. (À vrai dire, je suis sûr que j'ai vue
une suggestion de l'idée avant. Mais je n'arrive pas à en
trouver la moindre référence. Alors, en attendant, j'en suis
plus ou moins réconnu comme l'auteur de la technique en C++.)
De là à en déduire qu'il est aussi bien nommé que l'est
*template* méthode ? :)
Je tiens à la distinction, malgré les ressemblances
supérficielles. Mais tous les auteurs ne le font pas ; Herb
Sutter confond allegrement les deux concepts, par exemple. Comme
j'ai dit, la différence, ce n'est pas tellement ce que tu fais,
mais pourquoi. Si les fonctions non virtuelles sont là pour
valider le contrat, c'est de la programmation par contrat ; si
elles contiennent la charpente d'une implémentation, voire plus,
c'est le modèle de template.
En supposant qu'il s'agit d'une implémentation de B qui
lui-même utilise le modèle de template : conceptuellement, f() est
^^^^^^^^^^^^^^^^^^^^^^^
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 ».
Je t'en prie, pas encore une autre signification pour « méthode ».)
Ah bon, il y en a une autre ? ;)
Je t'en prie, pas encore une autre signification pour « méthode ».)
Ah bon, il y en a une autre ? ;)
Je t'en prie, pas encore une autre signification pour « méthode ».)
Ah bon, il y en a une autre ? ;)