et une classe B concrete
class B:public A
{
public :
B() {};
virtual ~B() {};
virtual bool Calcule(double &, double);
}
A l'utilisation :
B b;
b=2ECalcule(y,0.5); // fonctionne
std::vector<double> l_Yv, l_Xv;
/* init de l_Xv .....*/
b=2ECalcule(l_Yv, l_Xv);
--> KO, mon compilo me dit "Interpolate' : cannot convert parameter 1
from 'classstd::vector<double>' to 'double &'"
J'ai essay=E9 d'ajouter la d=E9finition de virtual bool
Calcule(std::vector<double> &, const std::vector<double> &); dans la
classe B mais au link, le compilo se plait car il ne trouve pas
B::virtual bool Calcule(std::vector<double> &, const
std::vector<double> &)
Mon compilo : MSVC++ 6.0 SP5
Y'a quelque chose qui m'=E9chappe ! Serait-ce un bug du compilo ?
class A { public : virtual bool Calcule(double &, double)=0; virtual bool Calcule(std::vector<double> &, const std::vector<double> &);
Déclarer une fonction virtuelle pure et une fonction normale avec le même nom ne me paraît pas une bonne idée dans l'absolu.
}
Il faut un point-virgule ici.
et une classe B concrete class B:public A { public : B() {}; virtual ~B() {};
virtual bool Calcule(double &, double);
Si tu n'as pas de warning ici, ton compilateur a effectivement un problème. En gros, B::Calcule() "cache" tous les A::Calcule().
Cf http://www.gotw.ca/gotw/005.htm
vdaanen
On 24 juil, 17:09, Fabien LE LEZ wrote:
On Tue, 24 Jul 2007 14:46:25 -0000, :
class A { public : virtual bool Calcule(double &, double)=0; virtual bool Calcule(std::vector<double> &, const std::vector<double> &);
Déclarer une fonction virtuelle pure et une fonction normale avec le même nom ne me paraît pas une bonne idée dans l'absolu. Les 2 methodes font la meme chose mais l'une sur une donnees de type
double et l'autre sur un vecteur de données.
.... apparemment, je suis bon pour changer le nom de la 2eme :(
}
Il faut un point-virgule ici. Juste une erreur de re-frappe.
et une classe B concrete class B:public A { public : B() {}; virtual ~B() {};
virtual bool Calcule(double &, double);
Si tu n'as pas de warning ici, ton compilateur a effectivement un problème. En gros, B::Calcule() "cache" tous les A::Calcule().
Oui, c'est egalement mon impression
Cfhttp://www.gotw.ca/gotw/005.htm merci pour le lien
On 24 juil, 17:09, Fabien LE LEZ <grams...@gramster.com> wrote:
On Tue, 24 Jul 2007 14:46:25 -0000, vdaa...@gmail.com:
class A
{
public :
virtual bool Calcule(double &, double)=0;
virtual bool Calcule(std::vector<double> &, const std::vector<double> &);
Déclarer une fonction virtuelle pure et une fonction normale avec le
même nom ne me paraît pas une bonne idée dans l'absolu.
Les 2 methodes font la meme chose mais l'une sur une donnees de type
double et l'autre sur un vecteur de données.
.... apparemment, je suis bon pour changer le nom de la 2eme :(
}
Il faut un point-virgule ici.
Juste une erreur de re-frappe.
et une classe B concrete
class B:public A
{
public :
B() {};
virtual ~B() {};
virtual bool Calcule(double &, double);
Si tu n'as pas de warning ici, ton compilateur a effectivement un
problème.
En gros, B::Calcule() "cache" tous les A::Calcule().
Oui, c'est egalement mon impression
Cfhttp://www.gotw.ca/gotw/005.htm
merci pour le lien
class A { public : virtual bool Calcule(double &, double)=0; virtual bool Calcule(std::vector<double> &, const std::vector<double> &);
Déclarer une fonction virtuelle pure et une fonction normale avec le même nom ne me paraît pas une bonne idée dans l'absolu. Les 2 methodes font la meme chose mais l'une sur une donnees de type
double et l'autre sur un vecteur de données.
.... apparemment, je suis bon pour changer le nom de la 2eme :(
}
Il faut un point-virgule ici. Juste une erreur de re-frappe.
et une classe B concrete class B:public A { public : B() {}; virtual ~B() {};
virtual bool Calcule(double &, double);
Si tu n'as pas de warning ici, ton compilateur a effectivement un problème. En gros, B::Calcule() "cache" tous les A::Calcule().
Oui, c'est egalement mon impression
Cfhttp://www.gotw.ca/gotw/005.htm merci pour le lien
Fabien LE LEZ
On Tue, 24 Jul 2007 14:46:25 -0000, :
Subject: Methodes virtuelle et virtuelle pure avec le meme nom. Mon compilateur s'embrouille !
Un conseil : évite le mot "méthode" en C++, car sa signification n'est pas claire. Il y a au moins deux significations possibles : "fonction membre" et "fonction membre virtuelle".
(Et tant que j'y suis : un "vector<>" est un tableau. Un vecteur est un objet mathématique, plus proche de std::valarray.)
Ainsi, tu gardes une interface cohérente (Calcule() accepte des double ou des vector<double>), tout en permettant aux classes dérivées de définir DoCalcule1 mais pas DoCalcule2.
On Tue, 24 Jul 2007 14:46:25 -0000, vdaanen@gmail.com:
Subject: Methodes virtuelle et virtuelle pure avec le meme nom. Mon compilateur s'embrouille !
Un conseil : évite le mot "méthode" en C++, car sa signification n'est
pas claire. Il y a au moins deux significations possibles : "fonction
membre" et "fonction membre virtuelle".
(Et tant que j'y suis : un "vector<>" est un tableau. Un vecteur est
un objet mathématique, plus proche de std::valarray.)
Ainsi, tu gardes une interface cohérente (Calcule() accepte des double
ou des vector<double>), tout en permettant aux classes dérivées de
définir DoCalcule1 mais pas DoCalcule2.
Subject: Methodes virtuelle et virtuelle pure avec le meme nom. Mon compilateur s'embrouille !
Un conseil : évite le mot "méthode" en C++, car sa signification n'est pas claire. Il y a au moins deux significations possibles : "fonction membre" et "fonction membre virtuelle".
(Et tant que j'y suis : un "vector<>" est un tableau. Un vecteur est un objet mathématique, plus proche de std::valarray.)
Ainsi, tu gardes une interface cohérente (Calcule() accepte des double ou des vector<double>), tout en permettant aux classes dérivées de définir DoCalcule1 mais pas DoCalcule2.
James Kanze
On Jul 24, 5:09 pm, Fabien LE LEZ wrote:
On Tue, 24 Jul 2007 14:46:25 -0000, :
class A { public : virtual bool Calcule(double &, double)=0; virtual bool Calcule(std::vector<double> &, const std::vector<double> &);
Déclarer une fonction virtuelle pure et une fonction normale avec le même nom ne me paraît pas une bonne idée dans l'absolu.
Ici, les deux fonctions sont virtuelles. A priori, je suppose qu'il a un traitement par défaut pour la calcule avec des tableaux, qui se base sur la calcule sur des doubles. (C'est un peu comme streambuf::xsputn, dont la définition par défaut renvoie, indirectement, à streambuf::overflow. Et que neuf fois sur dix, quand tu écris une dérivée de streambuf, il te suffit de supplanter overflow.)
}
Il faut un point-virgule ici.
et une classe B concrete class B:public A { public : B() {}; virtual ~B() {};
virtual bool Calcule(double &, double);
Si tu n'as pas de warning ici, ton compilateur a effectivement un problème.
La norme dit que ce qu'il fait est tout à fait légal. J'avoue ne jamais avoir eu besoin de réstreindre l'interface comme ça (c-à-d rendre l'interface de la class dérivée plus étroite que celle de la classe de base), mais il y a d'autres cas où le comportement de C++ ici correspond exactement à ce qu'on veut. (Si les fonctions étaient privées, et non virtuelles, par exemple, et qu'il existait des conversions entre les paramètres.)
Dans ce cas-ci, je crois qu'il suffit qu'il ajoute "using A::Calcule ;" dans la classe dérivée, pour dire au compilateur qu'on utilise l'interface complète de la classe A, au moins en ce qui concerne la fonction Calcule.
N'empeche que je crois, comme tu l'as indiqué dans une autre réponse, que le problème a sa source dans le fait qu'il mélange l'interface et l'implémentation. En les séparant, il ne doit rien avoir dans la classe dérivée qui masquerait l'interface (pas de fonction publique, en dehors des constructeurs et le destructeur), et que donc, il héritera l'interface complète de A. Et que tous les appels à l'implémentation auront lieu dans la classe A, et donc verrait l'« interface d'héritage » (c-à-d l'ensemble des fonctions virtuelles) complète de la classe A.
Je sens aussi qu'il faut des améliorations dans le vocabulaire. En fait, une classe de base typique affiche deux interfaces bien distinctes : une pour les utilisateurs, et une pour les implémenteurs. La première, celle qu'on entend la plus souvent par « interface », c'est l'ensemble des éléments publics. La deuxième, c'est d'une part ce que la classe met à la disposition des classes dérivées -- les parties protected, la plus souvent vide -- mais aussi les fonctions virtuelles que la classe dérivée doit, ou peut, supplanter (et qui seront typiquement privée). À mon avis, il n'y a que des avantages de maintenir séparées ses deux interfaces.
Il faudrait dire aussi que le posteur a fait un petit raccourci dans sa conception. Si j'ai bien compris, ce qu'il a, c'est :
-- une interface abstraite avec deux fonctions,
-- une implémentation « par défaut » d'une de ces fonctions en fonction de l'autre. C-à-d une implémentation d'une partie de la fonctionalité (un mixin, plus ou moins), et
-- des implémentations concrètes de l'interface complète, qui peuvent utiliser l'implémentation par défaut ci-dessus ou non, comme elles veulent.
Dans la mesure où ces deux premiers points sont distincts, conceptuellement, au moins, on dirait qu'il faut deux classes distinctes ; une implémentation concrète qui utilise le défaut héritera du mixin, en plus que de la classe de base. Ce qui donnerait quelque chose du genre :
J'ai simplifié beaucoup ici. Par exemple, je n'ai pas séparé l'interface utilisateur de l'interface d'héritage (et donc, le posteur aurait toujours son problème avec ConcreteUsingDefault). Aussi, en général, quand on se sert des mixins, je préfère qu'il soit plus ou moins systèmatique ; donc, ici, qu'on définisse aussi des mixin pour le cas double, et que la classe la plus dérivée ne définissent tout au moyen des mixins dont elle hérite. (Note que dans le cas des mixins, la classe la plus dérivée est en général un template, avec les classes d'implémentation comme paramètres.)
Mais tout ça est assez lourd, et pour le cas simple, où il s'agit d'une seule implémentation par défaut d'une des fonctions, je crois que je resterais avec la forme simplifiée qu'on avait à l'origine ici (mais probablement avec séparation de l'interface utilisateur de l'interface d'héritage).
-- 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
On Jul 24, 5:09 pm, Fabien LE LEZ <grams...@gramster.com> wrote:
On Tue, 24 Jul 2007 14:46:25 -0000, vdaa...@gmail.com:
class A
{
public :
virtual bool Calcule(double &, double)=0;
virtual bool Calcule(std::vector<double> &, const std::vector<double> &);
Déclarer une fonction virtuelle pure et une fonction normale
avec le même nom ne me paraît pas une bonne idée dans
l'absolu.
Ici, les deux fonctions sont virtuelles. A priori, je suppose
qu'il a un traitement par défaut pour la calcule avec des
tableaux, qui se base sur la calcule sur des doubles. (C'est un
peu comme streambuf::xsputn, dont la définition par défaut
renvoie, indirectement, à streambuf::overflow. Et que neuf fois
sur dix, quand tu écris une dérivée de streambuf, il te suffit
de supplanter overflow.)
}
Il faut un point-virgule ici.
et une classe B concrete
class B:public A
{
public :
B() {};
virtual ~B() {};
virtual bool Calcule(double &, double);
Si tu n'as pas de warning ici, ton compilateur a effectivement un
problème.
La norme dit que ce qu'il fait est tout à fait légal. J'avoue
ne jamais avoir eu besoin de réstreindre l'interface comme ça
(c-à-d rendre l'interface de la class dérivée plus étroite que
celle de la classe de base), mais il y a d'autres cas où le
comportement de C++ ici correspond exactement à ce qu'on veut.
(Si les fonctions étaient privées, et non virtuelles, par
exemple, et qu'il existait des conversions entre les
paramètres.)
Dans ce cas-ci, je crois qu'il suffit qu'il ajoute "using
A::Calcule ;" dans la classe dérivée, pour dire au compilateur
qu'on utilise l'interface complète de la classe A, au moins en
ce qui concerne la fonction Calcule.
N'empeche que je crois, comme tu l'as indiqué dans une autre
réponse, que le problème a sa source dans le fait qu'il mélange
l'interface et l'implémentation. En les séparant, il ne doit
rien avoir dans la classe dérivée qui masquerait l'interface
(pas de fonction publique, en dehors des constructeurs et le
destructeur), et que donc, il héritera l'interface complète de
A. Et que tous les appels à l'implémentation auront lieu dans la
classe A, et donc verrait l'« interface d'héritage » (c-à-d
l'ensemble des fonctions virtuelles) complète de la classe A.
Je sens aussi qu'il faut des améliorations dans le vocabulaire.
En fait, une classe de base typique affiche deux interfaces bien
distinctes : une pour les utilisateurs, et une pour les
implémenteurs. La première, celle qu'on entend la plus souvent
par « interface », c'est l'ensemble des éléments publics. La
deuxième, c'est d'une part ce que la classe met à la disposition
des classes dérivées -- les parties protected, la plus souvent
vide -- mais aussi les fonctions virtuelles que la classe
dérivée doit, ou peut, supplanter (et qui seront typiquement
privée). À mon avis, il n'y a que des avantages de maintenir
séparées ses deux interfaces.
Il faudrait dire aussi que le posteur a fait un petit raccourci
dans sa conception. Si j'ai bien compris, ce qu'il a, c'est :
-- une interface abstraite avec deux fonctions,
-- une implémentation « par défaut » d'une de ces fonctions
en fonction de l'autre. C-à-d une implémentation d'une
partie de la fonctionalité (un mixin, plus ou moins), et
-- des implémentations concrètes de l'interface complète, qui
peuvent utiliser l'implémentation par défaut ci-dessus ou
non, comme elles veulent.
Dans la mesure où ces deux premiers points sont distincts,
conceptuellement, au moins, on dirait qu'il faut deux classes
distinctes ; une implémentation concrète qui utilise le défaut
héritera du mixin, en plus que de la classe de base. Ce qui
donnerait quelque chose du genre :
J'ai simplifié beaucoup ici. Par exemple, je n'ai pas séparé
l'interface utilisateur de l'interface d'héritage (et donc, le
posteur aurait toujours son problème avec ConcreteUsingDefault).
Aussi, en général, quand on se sert des mixins, je préfère qu'il
soit plus ou moins systèmatique ; donc, ici, qu'on définisse
aussi des mixin pour le cas double, et que la classe la plus
dérivée ne définissent tout au moyen des mixins dont elle
hérite. (Note que dans le cas des mixins, la classe la plus
dérivée est en général un template, avec les classes
d'implémentation comme paramètres.)
Mais tout ça est assez lourd, et pour le cas simple, où il
s'agit d'une seule implémentation par défaut d'une des
fonctions, je crois que je resterais avec la forme simplifiée
qu'on avait à l'origine ici (mais probablement avec séparation
de l'interface utilisateur de l'interface d'héritage).
--
James Kanze (GABI Software) email:james.kanze@gmail.com
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
class A { public : virtual bool Calcule(double &, double)=0; virtual bool Calcule(std::vector<double> &, const std::vector<double> &);
Déclarer une fonction virtuelle pure et une fonction normale avec le même nom ne me paraît pas une bonne idée dans l'absolu.
Ici, les deux fonctions sont virtuelles. A priori, je suppose qu'il a un traitement par défaut pour la calcule avec des tableaux, qui se base sur la calcule sur des doubles. (C'est un peu comme streambuf::xsputn, dont la définition par défaut renvoie, indirectement, à streambuf::overflow. Et que neuf fois sur dix, quand tu écris une dérivée de streambuf, il te suffit de supplanter overflow.)
}
Il faut un point-virgule ici.
et une classe B concrete class B:public A { public : B() {}; virtual ~B() {};
virtual bool Calcule(double &, double);
Si tu n'as pas de warning ici, ton compilateur a effectivement un problème.
La norme dit que ce qu'il fait est tout à fait légal. J'avoue ne jamais avoir eu besoin de réstreindre l'interface comme ça (c-à-d rendre l'interface de la class dérivée plus étroite que celle de la classe de base), mais il y a d'autres cas où le comportement de C++ ici correspond exactement à ce qu'on veut. (Si les fonctions étaient privées, et non virtuelles, par exemple, et qu'il existait des conversions entre les paramètres.)
Dans ce cas-ci, je crois qu'il suffit qu'il ajoute "using A::Calcule ;" dans la classe dérivée, pour dire au compilateur qu'on utilise l'interface complète de la classe A, au moins en ce qui concerne la fonction Calcule.
N'empeche que je crois, comme tu l'as indiqué dans une autre réponse, que le problème a sa source dans le fait qu'il mélange l'interface et l'implémentation. En les séparant, il ne doit rien avoir dans la classe dérivée qui masquerait l'interface (pas de fonction publique, en dehors des constructeurs et le destructeur), et que donc, il héritera l'interface complète de A. Et que tous les appels à l'implémentation auront lieu dans la classe A, et donc verrait l'« interface d'héritage » (c-à-d l'ensemble des fonctions virtuelles) complète de la classe A.
Je sens aussi qu'il faut des améliorations dans le vocabulaire. En fait, une classe de base typique affiche deux interfaces bien distinctes : une pour les utilisateurs, et une pour les implémenteurs. La première, celle qu'on entend la plus souvent par « interface », c'est l'ensemble des éléments publics. La deuxième, c'est d'une part ce que la classe met à la disposition des classes dérivées -- les parties protected, la plus souvent vide -- mais aussi les fonctions virtuelles que la classe dérivée doit, ou peut, supplanter (et qui seront typiquement privée). À mon avis, il n'y a que des avantages de maintenir séparées ses deux interfaces.
Il faudrait dire aussi que le posteur a fait un petit raccourci dans sa conception. Si j'ai bien compris, ce qu'il a, c'est :
-- une interface abstraite avec deux fonctions,
-- une implémentation « par défaut » d'une de ces fonctions en fonction de l'autre. C-à-d une implémentation d'une partie de la fonctionalité (un mixin, plus ou moins), et
-- des implémentations concrètes de l'interface complète, qui peuvent utiliser l'implémentation par défaut ci-dessus ou non, comme elles veulent.
Dans la mesure où ces deux premiers points sont distincts, conceptuellement, au moins, on dirait qu'il faut deux classes distinctes ; une implémentation concrète qui utilise le défaut héritera du mixin, en plus que de la classe de base. Ce qui donnerait quelque chose du genre :
J'ai simplifié beaucoup ici. Par exemple, je n'ai pas séparé l'interface utilisateur de l'interface d'héritage (et donc, le posteur aurait toujours son problème avec ConcreteUsingDefault). Aussi, en général, quand on se sert des mixins, je préfère qu'il soit plus ou moins systèmatique ; donc, ici, qu'on définisse aussi des mixin pour le cas double, et que la classe la plus dérivée ne définissent tout au moyen des mixins dont elle hérite. (Note que dans le cas des mixins, la classe la plus dérivée est en général un template, avec les classes d'implémentation comme paramètres.)
Mais tout ça est assez lourd, et pour le cas simple, où il s'agit d'une seule implémentation par défaut d'une des fonctions, je crois que je resterais avec la forme simplifiée qu'on avait à l'origine ici (mais probablement avec séparation de l'interface utilisateur de l'interface d'héritage).
-- 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
Fabien LE LEZ
On Wed, 25 Jul 2007 08:43:45 -0000, James Kanze :
Si tu n'as pas de warning ici, ton compilateur a effectivement un problème.
La norme dit que ce qu'il fait est tout à fait légal.
Le compilo a bien un problème (il ne donne pas d'avertissement). Je n'ai pas parlé de bug. Je crois que tu parlerais de "qualité d'implémentation".
Peut-être y a-t-il un warning pour ça, activable sur demande.
On Wed, 25 Jul 2007 08:43:45 -0000, James Kanze
<james.kanze@gmail.com>:
Si tu n'as pas de warning ici, ton compilateur a effectivement un
problème.
La norme dit que ce qu'il fait est tout à fait légal.
Le compilo a bien un problème (il ne donne pas d'avertissement). Je
n'ai pas parlé de bug.
Je crois que tu parlerais de "qualité d'implémentation".
Peut-être y a-t-il un warning pour ça, activable sur demande.