enum Couleur { ROUGE, VERT };
virtual void f (Couleur couleur)
{
switch (couleur)
{
case ROUGE: f_Rouge(); break;
case VERT: f_Vert(); break;
};
}
virtual void f_Rouge() { f (ROUGE); }
virtual void f_Vert() { f (VERT); }
};
Les fonctions de cette classe sont "globalement virtuelles pures",
i.e. pour que ça marche, une classe dérivée doit redéfinir soit f(),
soit f_Rouge() et f_Vert().
Y a-t-il un moyen de tester cela à la compilation ?
parce que C1 et C2 n'hérite pas virtuellement de C ?
Tout à fait.
et oui, mais pourtant il ne fallait pas le faire...
Donc la solution proposée par Marc est valable.
elle l'est en héritage simple (car elle impose de définir la moitié désirée des méthodes); elle ne n'est plus en héritage virtuel car une classe héritant de C1 et C2 regénère exactement le même défaut que la classe unique d'origine.
Avec toujours la réserve que l'utilisateur doit savoir s'il faut hériter de C1 ou C2, mais ce n'est peut-être pas un problème.
question focus du problème, je ne suis pas sur d'avoir compris l'intérêt du risque de Stk Over. ou de devoir choisir entre C1 et C2 simplement pour fournir des points d'accès publiques multiples (qui devraient donc appartenir au modèle exposé) !?
ne proposerait-il pas un contrat plus simple et compréhensible ?
Sylvain.
Rémy wrote on 12/06/2006 13:04:
parce que C1 et C2 n'hérite pas virtuellement de C ?
Tout à fait.
et oui, mais pourtant il ne fallait pas le faire...
Donc la solution proposée par Marc est valable.
elle l'est en héritage simple (car elle impose de définir la moitié
désirée des méthodes); elle ne n'est plus en héritage virtuel car une
classe héritant de C1 et C2 regénère exactement le même défaut que la
classe unique d'origine.
Avec toujours la réserve que l'utilisateur doit savoir s'il faut hériter de
C1 ou C2, mais ce n'est peut-être pas un problème.
question focus du problème, je ne suis pas sur d'avoir compris l'intérêt
du risque de Stk Over. ou de devoir choisir entre C1 et C2 simplement
pour fournir des points d'accès publiques multiples (qui devraient donc
appartenir au modèle exposé) !?
parce que C1 et C2 n'hérite pas virtuellement de C ?
Tout à fait.
et oui, mais pourtant il ne fallait pas le faire...
Donc la solution proposée par Marc est valable.
elle l'est en héritage simple (car elle impose de définir la moitié désirée des méthodes); elle ne n'est plus en héritage virtuel car une classe héritant de C1 et C2 regénère exactement le même défaut que la classe unique d'origine.
Avec toujours la réserve que l'utilisateur doit savoir s'il faut hériter de C1 ou C2, mais ce n'est peut-être pas un problème.
question focus du problème, je ne suis pas sur d'avoir compris l'intérêt du risque de Stk Over. ou de devoir choisir entre C1 et C2 simplement pour fournir des points d'accès publiques multiples (qui devraient donc appartenir au modèle exposé) !?
ne proposerait-il pas un contrat plus simple et compréhensible ?
Sylvain.
kanze
Fabien LE LEZ wrote:
Soit la classe :
class C { public: virtual ~C(){}
enum Couleur { ROUGE, VERT }; virtual void f (Couleur couleur) { switch (couleur) { case ROUGE: f_Rouge(); break; case VERT: f_Vert(); break; }; } virtual void f_Rouge() { f (ROUGE); } virtual void f_Vert() { f (VERT); } };
Les fonctions de cette classe sont "globalement virtuelles pures", i.e. pour que ça marche, une classe dérivée doit redéfinir soit f(), soit f_Rouge() et f_Vert().
Y a-t-il un moyen de tester cela à la compilation ?
Est-ce que quelque chose comme le suivant ne ferait-il pas l'affaire :
template< bool overridesF > class Intermediate ;
class Base { public: virtual ~Base() {} enum Color { red, green } ; virtual void f( Color color ) { switch ( color ) { case red : fRed() ; break ;
case green : fGreen() ; break ; } }
virtual void fRed() { f( red ) ; } virtual void fGreen() { f( green ) ; }
Base( Base const& ) ; // ou {}, si on veut supporter // la copie. } ;
template<> class Intermediate< true > : public Base { public: virtual void f( Color ) = 0 ; } ;
template<> class Intermediate< false > : public Base { public: virtual void fRed() = 0 ; virtual void fGreen() = 0 ; } ;
Évidemment, ici, il faut que l'utilisateur dérive d'une des instantiations de Intermediate : true s'il veut supplanter f, false pour ne pas supplanter f, mais plutôt les autres fonctions.
-- 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
Fabien LE LEZ wrote:
Soit la classe :
class C
{
public:
virtual ~C(){}
enum Couleur { ROUGE, VERT };
virtual void f (Couleur couleur)
{
switch (couleur)
{
case ROUGE: f_Rouge(); break;
case VERT: f_Vert(); break;
};
}
virtual void f_Rouge() { f (ROUGE); }
virtual void f_Vert() { f (VERT); }
};
Les fonctions de cette classe sont "globalement virtuelles
pures", i.e. pour que ça marche, une classe dérivée doit
redéfinir soit f(), soit f_Rouge() et f_Vert().
Y a-t-il un moyen de tester cela à la compilation ?
Est-ce que quelque chose comme le suivant ne ferait-il pas
l'affaire :
template< bool overridesF > class Intermediate ;
class Base
{
public:
virtual ~Base() {}
enum Color { red, green } ;
virtual void f( Color color )
{
switch ( color ) {
case red :
fRed() ;
break ;
case green :
fGreen() ;
break ;
}
}
virtual void fRed() { f( red ) ; }
virtual void fGreen() { f( green ) ; }
Base( Base const& ) ; // ou {}, si on veut supporter
// la copie.
} ;
template<>
class Intermediate< true > : public Base
{
public:
virtual void f( Color ) = 0 ;
} ;
template<>
class Intermediate< false > : public Base
{
public:
virtual void fRed() = 0 ;
virtual void fGreen() = 0 ;
} ;
Évidemment, ici, il faut que l'utilisateur dérive d'une des
instantiations de Intermediate : true s'il veut supplanter f,
false pour ne pas supplanter f, mais plutôt les autres
fonctions.
--
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
enum Couleur { ROUGE, VERT }; virtual void f (Couleur couleur) { switch (couleur) { case ROUGE: f_Rouge(); break; case VERT: f_Vert(); break; }; } virtual void f_Rouge() { f (ROUGE); } virtual void f_Vert() { f (VERT); } };
Les fonctions de cette classe sont "globalement virtuelles pures", i.e. pour que ça marche, une classe dérivée doit redéfinir soit f(), soit f_Rouge() et f_Vert().
Y a-t-il un moyen de tester cela à la compilation ?
Est-ce que quelque chose comme le suivant ne ferait-il pas l'affaire :
template< bool overridesF > class Intermediate ;
class Base { public: virtual ~Base() {} enum Color { red, green } ; virtual void f( Color color ) { switch ( color ) { case red : fRed() ; break ;
case green : fGreen() ; break ; } }
virtual void fRed() { f( red ) ; } virtual void fGreen() { f( green ) ; }
Base( Base const& ) ; // ou {}, si on veut supporter // la copie. } ;
template<> class Intermediate< true > : public Base { public: virtual void f( Color ) = 0 ; } ;
template<> class Intermediate< false > : public Base { public: virtual void fRed() = 0 ; virtual void fGreen() = 0 ; } ;
Évidemment, ici, il faut que l'utilisateur dérive d'une des instantiations de Intermediate : true s'il veut supplanter f, false pour ne pas supplanter f, mais plutôt les autres fonctions.
-- 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
Fabien LE LEZ
On 13 Jun 2006 00:51:49 -0700, "kanze" :
template<> class Intermediate< true > : public Base
Y a-t-il une réelle utilité aux templates ici ?
Je verrais plutôt un
class Intermediate_2_fonctions ; class Intermediate_1_fonction ; // Note : ces noms sont assez nuls, il faudra trouver mieux
class Base { public: [...] private: friend class Intermediate_2_fonctions ; friend class Intermediate_1_fonction ; [...] } ;
class Intermediate_1_fonction : public Base { public: virtual void f( Color ) = 0 ; } ;
class Intermediate_2_fonctions: public Base { public: virtual void fRed() = 0 ; virtual void fGreen() = 0 ; } ;
En fait, je préfère la solution de Marc <news:e6jcj9$2tp$ : mettre le code dans les classes "intermédiaires".
On 13 Jun 2006 00:51:49 -0700, "kanze" <kanze@gabi-soft.fr>:
template<>
class Intermediate< true > : public Base
Y a-t-il une réelle utilité aux templates ici ?
Je verrais plutôt un
class Intermediate_2_fonctions ;
class Intermediate_1_fonction ;
// Note : ces noms sont assez nuls, il faudra trouver mieux
class Base
{
public:
[...]
private:
friend class Intermediate_2_fonctions ;
friend class Intermediate_1_fonction ;
[...]
} ;
class Intermediate_1_fonction : public Base
{
public:
virtual void f( Color ) = 0 ;
} ;
class Intermediate_2_fonctions: public Base
{
public:
virtual void fRed() = 0 ;
virtual void fGreen() = 0 ;
} ;
En fait, je préfère la solution de Marc
<news:e6jcj9$2tp$1@talisker.lacave.net> : mettre le code dans les
classes "intermédiaires".