Aide pour realiser une classe de manipualtion de donnees
45 réponses
Aurélien REGAT-BARREL
Bonjour,
Ca parrait long, mais c'est vite lu :-)
J'ai un certain nombre de classes ABC, DEF, GHI, ... qui ont la
particularité d'avoir une certain nombre (presque tout le temps 3) de
"valeurs" toutes de type double. En fait, la seule chose qui différencies
ces classes est le nom de ces valeurs :
etc...
C'est utile de les différencier, car ces valeurs n'ont pas la même
signification, et le typage est nécessaire.
Jusque là tout va bien, tout est calculé correctement.
Probleme :
Je veux dessiner ces valeurs dans un graphe, 1 valeur au choix sur chaque
axe.
Par exemple, dessiner A() et B() sur mon graphe.
Je voudrais donc faire un truc générique, et pas XX fonctions pour chaque
type.
J'ai voulu faire hériter toutes ces classes d'une même classe de base :
Triplet.
class Triplet
{
public:
virtual double Value( int Index ) const = 0;
};
Ainsi je file mon ABC ou DEF ou XYZ à mon graphe et je lui dit "dessine moi
la valeur 1 et 2 et il fait Value( 1 ) et Value ( 2 ) pour les récupérer.
class ABC : public Triplet
{
// idem que plus haut
public:
double Value( int Index )
{
switch ( Index )
{
case 0 : return this->A();
case 1 : return this->B();
case 2 : return this->C();
}
// exception
}
};
Mais Triplet est abstraite, et je ne peux pas contruire un
std::vector<Triplet> à passer pour dessiner.
Je compte du coup re-écrire toutes les classes dans ce style :
class Triplet
{
public:
virtual double Value( int Index ) const { return this->values.at(
Index ); }
private:
std::vector<double> values;
};
"Aurélien REGAT-BARREL" wrote in message news:40d039f6$0$32165$
Bonjour,
Bonjour.
Mais Triplet est abstraite, et je ne peux pas contruire un std::vector<Triplet> à passer pour dessiner. Je compte du coup re-écrire toutes les classes dans ce style :
class Triplet { public: virtual double Value( int Index ) const { return this->values.at( Index ); } private: std::vector<double> values; };
Pourquoi ne pas garder ta première solution et utiliser un vector<Triplet*> au lieu de vector<Triplet> ?
-- Nicolas Repiquet
"Aurélien REGAT-BARREL" <nospam-aregatba@yahoo.fr.invalid> wrote in message
news:40d039f6$0$32165$626a14ce@news.free.fr...
Bonjour,
Bonjour.
Mais Triplet est abstraite, et je ne peux pas contruire un
std::vector<Triplet> à passer pour dessiner.
Je compte du coup re-écrire toutes les classes dans ce style :
class Triplet
{
public:
virtual double Value( int Index ) const { return this->values.at(
Index ); }
private:
std::vector<double> values;
};
Pourquoi ne pas garder ta première solution et utiliser un vector<Triplet*>
au lieu de vector<Triplet> ?
"Aurélien REGAT-BARREL" wrote in message news:40d039f6$0$32165$
Bonjour,
Bonjour.
Mais Triplet est abstraite, et je ne peux pas contruire un std::vector<Triplet> à passer pour dessiner. Je compte du coup re-écrire toutes les classes dans ce style :
class Triplet { public: virtual double Value( int Index ) const { return this->values.at( Index ); } private: std::vector<double> values; };
Pourquoi ne pas garder ta première solution et utiliser un vector<Triplet*> au lieu de vector<Triplet> ?
-- Nicolas Repiquet
Loïc Joly
Aurélien REGAT-BARREL wrote:
Bonjour, Ca parrait long, mais c'est vite lu :-)
J'ai un certain nombre de classes ABC, DEF, GHI, ... qui ont la particularité d'avoir une certain nombre (presque tout le temps 3) de "valeurs" toutes de type double. En fait, la seule chose qui différencies ces classes est le nom de ces valeurs :
Je propose une autre solution, qui évite de faire de l'héritage :
J'ai un certain nombre de classes ABC, DEF, GHI, ... qui ont la
particularité d'avoir une certain nombre (presque tout le temps 3) de
"valeurs" toutes de type double. En fait, la seule chose qui différencies
ces classes est le nom de ces valeurs :
Je propose une autre solution, qui évite de faire de l'héritage :
J'ai un certain nombre de classes ABC, DEF, GHI, ... qui ont la particularité d'avoir une certain nombre (presque tout le temps 3) de "valeurs" toutes de type double. En fait, la seule chose qui différencies ces classes est le nom de ces valeurs :
Je propose une autre solution, qui évite de faire de l'héritage :
Pourquoi ne pas garder ta première solution et utiliser un vector<Triplet*>
au lieu de vector<Triplet> ?
Merci pour ton aide. C'est le delete qui m'embête... C'est assez contraignant de devoir appeler delete sur chaque élément d'un vector reçu en paramètre : L'idéal serait :
// graphique void Graph::AddCurve( const std::vector<Triplet> & Values ) { this->curves.add( Values ); // avec Triplet*, il faudrait parcourir Values et faire des delete... :-( :-( :-( }
// autre part void DrawSelectedTriplets() { // liste des triplets à dessiner std::vector<Triplet> values;
// pour chaque triplet <t> // si sélectionné values.push_back( t ); // avec Triplet *, il faudrait allouer un nouveau Triplet copie de <t> :-( :-( :-(
J'ai oublié de préciser que mes Triplets sont souvents temporaires, c.a.d créés juste avant de les dessiner (dans DrawSelectedTriplets). Disons que j'ai bien les triplets ABC qui sont persistents, mais on peut vouloir dessiner CDE, FGH ou XXX qui sont générés à partir de ABC...
-- Aurélien REGAT-BARREL
Pourquoi ne pas garder ta première solution et utiliser un
vector<Triplet*>
au lieu de vector<Triplet> ?
Merci pour ton aide.
C'est le delete qui m'embête... C'est assez contraignant de devoir appeler
delete sur chaque élément d'un vector reçu en paramètre :
L'idéal serait :
// graphique
void Graph::AddCurve( const std::vector<Triplet> & Values )
{
this->curves.add( Values );
// avec Triplet*, il faudrait parcourir Values et faire des delete...
:-( :-( :-(
}
// autre part
void DrawSelectedTriplets()
{
// liste des triplets à dessiner
std::vector<Triplet> values;
// pour chaque triplet <t>
// si sélectionné
values.push_back( t );
// avec Triplet *, il faudrait allouer un nouveau Triplet copie
de <t> :-( :-( :-(
J'ai oublié de préciser que mes Triplets sont souvents temporaires, c.a.d
créés juste avant de les dessiner (dans DrawSelectedTriplets).
Disons que j'ai bien les triplets ABC qui sont persistents, mais on peut
vouloir dessiner CDE, FGH ou XXX qui sont générés à partir de ABC...
Pourquoi ne pas garder ta première solution et utiliser un vector<Triplet*>
au lieu de vector<Triplet> ?
Merci pour ton aide. C'est le delete qui m'embête... C'est assez contraignant de devoir appeler delete sur chaque élément d'un vector reçu en paramètre : L'idéal serait :
// graphique void Graph::AddCurve( const std::vector<Triplet> & Values ) { this->curves.add( Values ); // avec Triplet*, il faudrait parcourir Values et faire des delete... :-( :-( :-( }
// autre part void DrawSelectedTriplets() { // liste des triplets à dessiner std::vector<Triplet> values;
// pour chaque triplet <t> // si sélectionné values.push_back( t ); // avec Triplet *, il faudrait allouer un nouveau Triplet copie de <t> :-( :-( :-(
J'ai oublié de préciser que mes Triplets sont souvents temporaires, c.a.d créés juste avant de les dessiner (dans DrawSelectedTriplets). Disons que j'ai bien les triplets ABC qui sont persistents, mais on peut vouloir dessiner CDE, FGH ou XXX qui sont générés à partir de ABC...
-- Aurélien REGAT-BARREL
Aurélien Regat-Barrel
Je propose une autre solution, qui évite de faire de l'héritage :
Bonjour, Merci pour ron aide. Je vois à peu près l'idée, mais : - je voudrais créer un std::vector de Triplet - la fonction dessine (ou plutot AddTriplets en vue de les dessiner) est une fonction membre d'une autre classe "Graph". Comment insérer cette fonction template dans cette classe qui n'est pas template (et ne peut pas l'être car dérivant d'une classe d'une lib GUI) ?
-- Aurélien REGAT-BARREL
Je propose une autre solution, qui évite de faire de l'héritage :
Bonjour,
Merci pour ron aide.
Je vois à peu près l'idée, mais :
- je voudrais créer un std::vector de Triplet
- la fonction dessine (ou plutot AddTriplets en vue de les dessiner) est une
fonction membre d'une autre classe "Graph". Comment insérer cette fonction
template dans cette classe qui n'est pas template (et ne peut pas l'être car
dérivant d'une classe d'une lib GUI) ?
Bonjour, Merci pour ron aide. Je vois à peu près l'idée, mais : - je voudrais créer un std::vector de Triplet - la fonction dessine (ou plutot AddTriplets en vue de les dessiner) est une fonction membre d'une autre classe "Graph". Comment insérer cette fonction template dans cette classe qui n'est pas template (et ne peut pas l'être car dérivant d'une classe d'une lib GUI) ?
-- Aurélien REGAT-BARREL
Loïc Joly
Aurélien Regat-Barrel wrote:
Pourquoi ne pas garder ta première solution et utiliser un
vector<Triplet*>
au lieu de vector<Triplet> ?
Merci pour ton aide. C'est le delete qui m'embête... C'est assez contraignant de devoir appeler delete sur chaque élément d'un vector reçu en paramètre :
Dans ce cas, soit ton vecteur ne possède pas les triplets, et pas besoin de faire les delete, soit il les possède (soit de façon partagée ou suite à une copie en profondeur), et un vecteur de pointeurs intelligents (par exemple vector<boost::shared_ptr<Triplet> > pour de la propriété partagée, à condition qu'il y ait des boost::shared_ptr<Triplet> partout dans ton code) peut convenir.
-- Loïc
Aurélien Regat-Barrel wrote:
Pourquoi ne pas garder ta première solution et utiliser un
vector<Triplet*>
au lieu de vector<Triplet> ?
Merci pour ton aide.
C'est le delete qui m'embête... C'est assez contraignant de devoir appeler
delete sur chaque élément d'un vector reçu en paramètre :
Dans ce cas, soit ton vecteur ne possède pas les triplets, et pas besoin
de faire les delete, soit il les possède (soit de façon partagée ou
suite à une copie en profondeur), et un vecteur de pointeurs
intelligents (par exemple vector<boost::shared_ptr<Triplet> > pour de la
propriété partagée, à condition qu'il y ait des
boost::shared_ptr<Triplet> partout dans ton code) peut convenir.
Pourquoi ne pas garder ta première solution et utiliser un
vector<Triplet*>
au lieu de vector<Triplet> ?
Merci pour ton aide. C'est le delete qui m'embête... C'est assez contraignant de devoir appeler delete sur chaque élément d'un vector reçu en paramètre :
Dans ce cas, soit ton vecteur ne possède pas les triplets, et pas besoin de faire les delete, soit il les possède (soit de façon partagée ou suite à une copie en profondeur), et un vecteur de pointeurs intelligents (par exemple vector<boost::shared_ptr<Triplet> > pour de la propriété partagée, à condition qu'il y ait des boost::shared_ptr<Triplet> partout dans ton code) peut convenir.
-- Loïc
Aurélien REGAT-BARREL
Dans ce cas, soit ton vecteur ne possède pas les triplets, et pas besoin de faire les delete, soit il les possède (soit de façon partagée ou suite à une copie en profondeur), et un vecteur de pointeurs intelligents (par exemple vector<boost::shared_ptr<Triplet> > pour de la propriété partagée, à condition qu'il y ait des boost::shared_ptr<Triplet> partout dans ton code) peut convenir.
J'y ai pensé (à std::auto_ptr). Mais les pointeurs pour ça ça me gêne beaucoup. Je viens de penser à aure chose. J'aime bien cette idée d'interface via la classe abstraite. Probleme : on ne peut pas faire de std::vector de classes abstraites. Alternative :
Qu'en pensez-vous ? Ca me parrait meilleur que ma dernière idée de classe de base Triplet qui embarque un std::vector que ses dérivées (ABC, ...) utilisent pour stocker leur A, B et C...
-- Aurélien REGAT-BARREL
Dans ce cas, soit ton vecteur ne possède pas les triplets, et pas besoin
de faire les delete, soit il les possède (soit de façon partagée ou
suite à une copie en profondeur), et un vecteur de pointeurs
intelligents (par exemple vector<boost::shared_ptr<Triplet> > pour de la
propriété partagée, à condition qu'il y ait des
boost::shared_ptr<Triplet> partout dans ton code) peut convenir.
J'y ai pensé (à std::auto_ptr).
Mais les pointeurs pour ça ça me gêne beaucoup.
Je viens de penser à aure chose. J'aime bien cette idée d'interface via la
classe abstraite. Probleme : on ne peut pas faire de std::vector de classes
abstraites. Alternative :
Qu'en pensez-vous ?
Ca me parrait meilleur que ma dernière idée de classe de base Triplet qui
embarque un std::vector que ses dérivées (ABC, ...) utilisent pour stocker
leur A, B et C...
Dans ce cas, soit ton vecteur ne possède pas les triplets, et pas besoin de faire les delete, soit il les possède (soit de façon partagée ou suite à une copie en profondeur), et un vecteur de pointeurs intelligents (par exemple vector<boost::shared_ptr<Triplet> > pour de la propriété partagée, à condition qu'il y ait des boost::shared_ptr<Triplet> partout dans ton code) peut convenir.
J'y ai pensé (à std::auto_ptr). Mais les pointeurs pour ça ça me gêne beaucoup. Je viens de penser à aure chose. J'aime bien cette idée d'interface via la classe abstraite. Probleme : on ne peut pas faire de std::vector de classes abstraites. Alternative :
Qu'en pensez-vous ? Ca me parrait meilleur que ma dernière idée de classe de base Triplet qui embarque un std::vector que ses dérivées (ABC, ...) utilisent pour stocker leur A, B et C...
-- Aurélien REGAT-BARREL
Loïc Joly
Aurélien REGAT-BARREL wrote:
Dans ce cas, soit ton vecteur ne possède pas les triplets, et pas besoin de faire les delete, soit il les possède (soit de façon partagée ou suite à une copie en profondeur), et un vecteur de pointeurs intelligents (par exemple vector<boost::shared_ptr<Triplet> > pour de la propriété partagée, à condition qu'il y ait des boost::shared_ptr<Triplet> partout dans ton code) peut convenir.
J'y ai pensé (à std::auto_ptr).
Tu ne peux pas faire de vector<auto_ptr<T> >, de plus la sémentique d'auto_ptr est tellement étrange que je déconseille son utilisation.
Mais les pointeurs pour ça ça me gêne beaucoup.
Si tu n'expliques pas en quoi ça te gêne, on va a voir du mal à trouver une solution qui te plaise.
-- Loïc
Aurélien REGAT-BARREL wrote:
Dans ce cas, soit ton vecteur ne possède pas les triplets, et pas besoin
de faire les delete, soit il les possède (soit de façon partagée ou
suite à une copie en profondeur), et un vecteur de pointeurs
intelligents (par exemple vector<boost::shared_ptr<Triplet> > pour de la
propriété partagée, à condition qu'il y ait des
boost::shared_ptr<Triplet> partout dans ton code) peut convenir.
J'y ai pensé (à std::auto_ptr).
Tu ne peux pas faire de vector<auto_ptr<T> >, de plus la sémentique
d'auto_ptr est tellement étrange que je déconseille son utilisation.
Mais les pointeurs pour ça ça me gêne beaucoup.
Si tu n'expliques pas en quoi ça te gêne, on va a voir du mal à trouver
une solution qui te plaise.
Dans ce cas, soit ton vecteur ne possède pas les triplets, et pas besoin de faire les delete, soit il les possède (soit de façon partagée ou suite à une copie en profondeur), et un vecteur de pointeurs intelligents (par exemple vector<boost::shared_ptr<Triplet> > pour de la propriété partagée, à condition qu'il y ait des boost::shared_ptr<Triplet> partout dans ton code) peut convenir.
J'y ai pensé (à std::auto_ptr).
Tu ne peux pas faire de vector<auto_ptr<T> >, de plus la sémentique d'auto_ptr est tellement étrange que je déconseille son utilisation.
Mais les pointeurs pour ça ça me gêne beaucoup.
Si tu n'expliques pas en quoi ça te gêne, on va a voir du mal à trouver une solution qui te plaise.
-- Loïc
Aurélien REGAT-BARREL
Mais les pointeurs pour ça ça me gêne beaucoup.
Si tu n'expliques pas en quoi ça te gêne, on va a voir du mal à trouver une solution qui te plaise.
2 points : - J'essaye d'utiliser au minimum les pointeurs. Il n'y en pas pratiquement pas dans tout mon code. Faut allouer, désallouer, vérifier qu'il est pas null, checker l'allocation,... Jusque là je me suis très bien débrouillé sans. Mais j'ai peut être atteind les limites du "non pointeur" et il serait peut être plus élégant d'utiliser des interfaces (ABC) via des pointeurs intelligents que d'utiliser des classes de base faussement abstraites via un constrcuteur protected. - Utiliser des pointeurs (intelligents ou non) va me faire modifier pas mal de code.
Mais je garde l'idée sous la main, au moins pour le prochain problème du genre. Merci.
-- Aurélien REGAT-BARREL
Mais les pointeurs pour ça ça me gêne beaucoup.
Si tu n'expliques pas en quoi ça te gêne, on va a voir du mal à trouver
une solution qui te plaise.
2 points :
- J'essaye d'utiliser au minimum les pointeurs. Il n'y en pas pratiquement
pas dans tout mon code. Faut allouer, désallouer, vérifier qu'il est pas
null, checker l'allocation,... Jusque là je me suis très bien débrouillé
sans. Mais j'ai peut être atteind les limites du "non pointeur" et il serait
peut être plus élégant d'utiliser des interfaces (ABC) via des pointeurs
intelligents que d'utiliser des classes de base faussement abstraites via un
constrcuteur protected.
- Utiliser des pointeurs (intelligents ou non) va me faire modifier pas mal
de code.
Mais je garde l'idée sous la main, au moins pour le prochain problème du
genre.
Merci.
Si tu n'expliques pas en quoi ça te gêne, on va a voir du mal à trouver une solution qui te plaise.
2 points : - J'essaye d'utiliser au minimum les pointeurs. Il n'y en pas pratiquement pas dans tout mon code. Faut allouer, désallouer, vérifier qu'il est pas null, checker l'allocation,... Jusque là je me suis très bien débrouillé sans. Mais j'ai peut être atteind les limites du "non pointeur" et il serait peut être plus élégant d'utiliser des interfaces (ABC) via des pointeurs intelligents que d'utiliser des classes de base faussement abstraites via un constrcuteur protected. - Utiliser des pointeurs (intelligents ou non) va me faire modifier pas mal de code.
Mais je garde l'idée sous la main, au moins pour le prochain problème du genre. Merci.
-- Aurélien REGAT-BARREL
kanze
"Aurélien REGAT-BARREL" wrote in message news:<40d039f6$0$32165$...
Ca parrait long, mais c'est vite lu :-)
J'ai un certain nombre de classes ABC, DEF, GHI, ... qui ont la particularité d'avoir une certain nombre (presque tout le temps 3) de "valeurs" toutes de type double. En fait, la seule chose qui différencies ces classes est le nom de ces valeurs :
C'est utile de les différencier, car ces valeurs n'ont pas la même signification, et le typage est nécessaire. Jusque là tout va bien, tout est calculé correctement.
Probleme :
Je veux dessiner ces valeurs dans un graphe, 1 valeur au choix sur chaque axe. Par exemple, dessiner A() et B() sur mon graphe. Je voudrais donc faire un truc générique, et pas XX fonctions pour chaque type. J'ai voulu faire hériter toutes ces classes d'une même classe de base : Triplet.
class Triplet { public: virtual double Value( int Index ) const = 0; };
Ainsi je file mon ABC ou DEF ou XYZ à mon graphe et je lui dit "dessine moi la valeur 1 et 2 et il fait Value( 1 ) et Value ( 2 ) pour les récupérer.
class ABC : public Triplet { // idem que plus haut
public: double Value( int Index ) { switch ( Index ) { case 0 : return this->A(); case 1 : return this->B(); case 2 : return this->C(); } // exception } };
Mais Triplet est abstraite, et je ne peux pas contruire un std::vector<Triplet> à passer pour dessiner. Je compte du coup re-écrire toutes les classes dans ce style :
class Triplet { public: virtual double Value( int Index ) const { return this->values.at( Index ); } private: std::vector<double> values; };
Ceci dit, j'ai lu la reste de la discussion, où tu dis de ne pas aimer les pointeurs. Or, en C++, qu'on les aime ou non, le polymorphisme implique l'utilisation des pointeurs. Et un certain nombre d'autres choses. Si tes classes ABC et DEF sont réelement des valeurs, avec une sémantique de valeur, c'est peut-être que le polymorphisme, même limité, ne leur convient pas.
En plus de la solution template suggérer par Loïc, tu pourrais penser à une conversion implicite -- tu définis une class Triplet uniquement pour l'affichage, puis dans ABC, DEF, etc., tu définis un opérateur de conversion :
operator Triplet() { return ... }
où tu construis un Triplet des valeurs dans la classe dérivée.
-- 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
"Aurélien REGAT-BARREL" <nospam-aregatba@yahoo.fr.invalid> wrote in
message news:<40d039f6$0$32165$626a14ce@news.free.fr>...
Ca parrait long, mais c'est vite lu :-)
J'ai un certain nombre de classes ABC, DEF, GHI, ... qui ont la
particularité d'avoir une certain nombre (presque tout le temps 3) de
"valeurs" toutes de type double. En fait, la seule chose qui
différencies ces classes est le nom de ces valeurs :
C'est utile de les différencier, car ces valeurs n'ont pas la même
signification, et le typage est nécessaire. Jusque là tout va bien,
tout est calculé correctement.
Probleme :
Je veux dessiner ces valeurs dans un graphe, 1 valeur au choix sur
chaque axe. Par exemple, dessiner A() et B() sur mon graphe. Je
voudrais donc faire un truc générique, et pas XX fonctions pour chaque
type. J'ai voulu faire hériter toutes ces classes d'une même classe de
base : Triplet.
class Triplet
{
public:
virtual double Value( int Index ) const = 0;
};
Ainsi je file mon ABC ou DEF ou XYZ à mon graphe et je lui dit
"dessine moi la valeur 1 et 2 et il fait Value( 1 ) et Value ( 2 )
pour les récupérer.
class ABC : public Triplet
{
// idem que plus haut
public:
double Value( int Index )
{
switch ( Index )
{
case 0 : return this->A();
case 1 : return this->B();
case 2 : return this->C();
}
// exception
}
};
Mais Triplet est abstraite, et je ne peux pas contruire un
std::vector<Triplet> à passer pour dessiner.
Je compte du coup re-écrire toutes les classes dans ce style :
class Triplet
{
public:
virtual double Value( int Index ) const { return this->values.at(
Index ); }
private:
std::vector<double> values;
};
Ceci dit, j'ai lu la reste de la discussion, où tu dis de ne pas aimer
les pointeurs. Or, en C++, qu'on les aime ou non, le polymorphisme
implique l'utilisation des pointeurs. Et un certain nombre d'autres
choses. Si tes classes ABC et DEF sont réelement des valeurs, avec une
sémantique de valeur, c'est peut-être que le polymorphisme, même limité,
ne leur convient pas.
En plus de la solution template suggérer par Loïc, tu pourrais penser à
une conversion implicite -- tu définis une class Triplet uniquement pour
l'affichage, puis dans ABC, DEF, etc., tu définis un opérateur de
conversion :
operator Triplet() {
return ...
}
où tu construis un Triplet des valeurs dans la classe dérivée.
--
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
"Aurélien REGAT-BARREL" wrote in message news:<40d039f6$0$32165$...
Ca parrait long, mais c'est vite lu :-)
J'ai un certain nombre de classes ABC, DEF, GHI, ... qui ont la particularité d'avoir une certain nombre (presque tout le temps 3) de "valeurs" toutes de type double. En fait, la seule chose qui différencies ces classes est le nom de ces valeurs :
C'est utile de les différencier, car ces valeurs n'ont pas la même signification, et le typage est nécessaire. Jusque là tout va bien, tout est calculé correctement.
Probleme :
Je veux dessiner ces valeurs dans un graphe, 1 valeur au choix sur chaque axe. Par exemple, dessiner A() et B() sur mon graphe. Je voudrais donc faire un truc générique, et pas XX fonctions pour chaque type. J'ai voulu faire hériter toutes ces classes d'une même classe de base : Triplet.
class Triplet { public: virtual double Value( int Index ) const = 0; };
Ainsi je file mon ABC ou DEF ou XYZ à mon graphe et je lui dit "dessine moi la valeur 1 et 2 et il fait Value( 1 ) et Value ( 2 ) pour les récupérer.
class ABC : public Triplet { // idem que plus haut
public: double Value( int Index ) { switch ( Index ) { case 0 : return this->A(); case 1 : return this->B(); case 2 : return this->C(); } // exception } };
Mais Triplet est abstraite, et je ne peux pas contruire un std::vector<Triplet> à passer pour dessiner. Je compte du coup re-écrire toutes les classes dans ce style :
class Triplet { public: virtual double Value( int Index ) const { return this->values.at( Index ); } private: std::vector<double> values; };
Ceci dit, j'ai lu la reste de la discussion, où tu dis de ne pas aimer les pointeurs. Or, en C++, qu'on les aime ou non, le polymorphisme implique l'utilisation des pointeurs. Et un certain nombre d'autres choses. Si tes classes ABC et DEF sont réelement des valeurs, avec une sémantique de valeur, c'est peut-être que le polymorphisme, même limité, ne leur convient pas.
En plus de la solution template suggérer par Loïc, tu pourrais penser à une conversion implicite -- tu définis une class Triplet uniquement pour l'affichage, puis dans ABC, DEF, etc., tu définis un opérateur de conversion :
operator Triplet() { return ... }
où tu construis un Triplet des valeurs dans la classe dérivée.
-- 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
Aurélien REGAT-BARREL
Ça ne me semble pas mauvais.
Ceci dit, j'ai lu la reste de la discussion, où tu dis de ne pas aimer les pointeurs. Or, en C++, qu'on les aime ou non, le polymorphisme implique l'utilisation des pointeurs. Et un certain nombre d'autres choses.
Peux-tu détailler un petit peu. Pourquoi cela implique-t-il les pointeurs ?
Si tes classes ABC et DEF sont réelement des valeurs, avec une sémantique de valeur, c'est peut-être que le polymorphisme, même limité, ne leur convient pas.
Eh bien, si l'on considère que le polymorphisme est à utiliser lors d'une relation "est un", je pense qu'il est adapté ici. ABC, DEF, ... sont tous des Triplet. La seule chose qui les différencie, c'est le contexte de leurs valeurs. ABC va être les coordonnées d'un point en mètres, DEF en yards, GHI en kilomètres, etc... Il est donc important de les différencier pour les manipuler. Mais pour les afficher, j'ai un graphe qui se calibre automatiquement en fonction du min et du max. La fonction qui lui donne les Triplets à afficher se charge de mettre la légende à jour. En fait, mon graphe est un bête graphe générique qui ne fait que dessiner des Triplet. Passer par Triplet me permet de ne pas devoir le spécialiser pour chaque nouveau type de Triplet, réduction du couplage, ...
En plus de la solution template suggérer par Loïc, tu pourrais penser à une conversion implicite -- tu définis une class Triplet uniquement pour l'affichage, puis dans ABC, DEF, etc., tu définis un opérateur de conversion :
operator Triplet() { return ... }
où tu construis un Triplet des valeurs dans la classe dérivée.
Intéressant... Je garde ça sous le coude. Merci pour ta réponse.
-- Aurélien REGAT-BARREL
Ça ne me semble pas mauvais.
Ceci dit, j'ai lu la reste de la discussion, où tu dis de ne pas aimer
les pointeurs. Or, en C++, qu'on les aime ou non, le polymorphisme
implique l'utilisation des pointeurs. Et un certain nombre d'autres
choses.
Peux-tu détailler un petit peu. Pourquoi cela implique-t-il les pointeurs ?
Si tes classes ABC et DEF sont réelement des valeurs, avec une
sémantique de valeur, c'est peut-être que le polymorphisme, même limité,
ne leur convient pas.
Eh bien, si l'on considère que le polymorphisme est à utiliser lors d'une
relation "est un", je pense qu'il est adapté ici.
ABC, DEF, ... sont tous des Triplet. La seule chose qui les différencie,
c'est le contexte de leurs valeurs.
ABC va être les coordonnées d'un point en mètres, DEF en yards, GHI en
kilomètres, etc...
Il est donc important de les différencier pour les manipuler.
Mais pour les afficher, j'ai un graphe qui se calibre automatiquement en
fonction du min et du max.
La fonction qui lui donne les Triplets à afficher se charge de mettre la
légende à jour. En fait, mon graphe est un bête graphe générique qui ne fait
que dessiner des Triplet. Passer par Triplet me permet de ne pas devoir le
spécialiser pour chaque nouveau type de Triplet, réduction du couplage, ...
En plus de la solution template suggérer par Loïc, tu pourrais penser à
une conversion implicite -- tu définis une class Triplet uniquement pour
l'affichage, puis dans ABC, DEF, etc., tu définis un opérateur de
conversion :
operator Triplet() {
return ...
}
où tu construis un Triplet des valeurs dans la classe dérivée.
Intéressant... Je garde ça sous le coude.
Merci pour ta réponse.
Ceci dit, j'ai lu la reste de la discussion, où tu dis de ne pas aimer les pointeurs. Or, en C++, qu'on les aime ou non, le polymorphisme implique l'utilisation des pointeurs. Et un certain nombre d'autres choses.
Peux-tu détailler un petit peu. Pourquoi cela implique-t-il les pointeurs ?
Si tes classes ABC et DEF sont réelement des valeurs, avec une sémantique de valeur, c'est peut-être que le polymorphisme, même limité, ne leur convient pas.
Eh bien, si l'on considère que le polymorphisme est à utiliser lors d'une relation "est un", je pense qu'il est adapté ici. ABC, DEF, ... sont tous des Triplet. La seule chose qui les différencie, c'est le contexte de leurs valeurs. ABC va être les coordonnées d'un point en mètres, DEF en yards, GHI en kilomètres, etc... Il est donc important de les différencier pour les manipuler. Mais pour les afficher, j'ai un graphe qui se calibre automatiquement en fonction du min et du max. La fonction qui lui donne les Triplets à afficher se charge de mettre la légende à jour. En fait, mon graphe est un bête graphe générique qui ne fait que dessiner des Triplet. Passer par Triplet me permet de ne pas devoir le spécialiser pour chaque nouveau type de Triplet, réduction du couplage, ...
En plus de la solution template suggérer par Loïc, tu pourrais penser à une conversion implicite -- tu définis une class Triplet uniquement pour l'affichage, puis dans ABC, DEF, etc., tu définis un opérateur de conversion :
operator Triplet() { return ... }
où tu construis un Triplet des valeurs dans la classe dérivée.
Intéressant... Je garde ça sous le coude. Merci pour ta réponse.