Je cherche à faire passer à une fonction un ensemble de paramètres dont je ne connais pas le nombre et le type à l'avance (critère à optimiser dont les paramètres dépendent de la forme du critère). Pour obtenir un résultat assez général, je cherche alors à faire passer en paramètre de cette fonction critère un objet "paramètres".
Imaginons une fonction du type
double My_Func(CParams aParams
{ // Faire quelque chose avec aParam
Ici l'objet CParams est mon objet "paramètres". Pour simplifier, imaginons que je cherche à faire passer 1 double, 1 int et 1 objet CObject (précédemment défini) à ma fonction My_Func. Je réalise alors l'appel suivant
CObject aObject
// initialisation de aObjec
CParams aParams
aParams.Set(12.5, 14, aObject)
// (*1
Où la fonction "Set" va me permettre de stocker le double, l'int et le CObject dans un tableau de void* (ceci afin de pouvoir avoir un tableau indépendant du type des données en entrée)
Voici alors ma fonction Set
void CParams::Set(double aA, int aB, CObject aC
Soit par ailleurs la fonction GetDouble
double GetDouble(int aIdx
return (*(double*)theArgs[aIdx])
Je fais alors les tests suivants
- dans la fonction Set à la ligne // (*2
printf("%f\n", GetDouble(0))
Resultat : 12.
- dans le programme principal à la ligne // (*1
printf("%f\n", aParams.GetDouble(0))
Resultat : 0.
Le résultat ne produit pas alors le but recherché. Je n'arrive pas à comprendre pourquoi le tableau theArgs de void* ne contient plus rien dès lors que l'on est sorti de la fonction Set. J'ai du faire un erreur dans l'utilisation des pointeurs, mais je ne la vois pas
Si quelqu'un a une idée ou une solution, je suis preneur
"calloc", c'est du C. Même si, stricto sensu, on peut les utiliser en C++, je te conseille fortement d'utiliser new ou new[] à la place.
Mais même ceux-là, on peut généralement éviter de les utiliser.
En C++, un tableau, c'est std::vector<>, sauf si on a une bonne raison d'utiliser autre chose.
Il faudrait donc écrire, dans la déclaration de ta classe, à la place de "iNbArgs" et "theArgs" : std::vector<void*> theArgs;
puis, dans ta fonction Set() :
theArgs.erase (theArgs.begin(), theArgs.end()); /* Vider le tableau, si tu le juges nécessaire */
theArgs[0] = &aA;
theArgs.push_back (&aA); theArgs.push_back (&aB);
Sauf que... Ça ne marche pas.
void CParams::Set(double aA, int aB, CObject aC)
"aA" est donc un objet de type "double", local à ta fonction. Au moment où tu sors de la fonction, cet objet est détruit, et son adresse, stockée dans le tableau, ne veut plus rien dire.
Il y a des moyens de contourner ce problème, en gérant plus finement la durée de vie des objets, mais c'est casse-gueule. Boost::any serait sans doute plus adapté qu'un "void*".
D'ailleurs, je ne comprends pas ta démarche : si la fonction chargée de remplir le tableau, et la fonction qui l'utilise, connaissent toutes les deux les types des éléments, pourquoi faire un tableau de void* ?
Il serait tellement plus simple d'écrire :
class CParams { public: struct LesElements { double aA; int aB; CObjet aC; }; LesElements les_elements;
... };
On Tue, 2 May 2006 16:11:58 +0200, Stochastic
<Stochastic.276y2m@no-mx.frbox.net>:
Voici alors ma fonction Set:
Plusieurs problèmes ici, dont une erreur manifeste.
"calloc", c'est du C. Même si, stricto sensu, on peut les utiliser en
C++, je te conseille fortement d'utiliser new ou new[] à la place.
Mais même ceux-là, on peut généralement éviter de les utiliser.
En C++, un tableau, c'est std::vector<>, sauf si on a une bonne raison
d'utiliser autre chose.
Il faudrait donc écrire, dans la déclaration de ta classe, à la place
de "iNbArgs" et "theArgs" :
std::vector<void*> theArgs;
puis, dans ta fonction Set() :
theArgs.erase (theArgs.begin(), theArgs.end()); /* Vider le
tableau, si tu le juges nécessaire */
theArgs[0] = &aA;
theArgs.push_back (&aA);
theArgs.push_back (&aB);
Sauf que... Ça ne marche pas.
void CParams::Set(double aA, int aB, CObject aC)
"aA" est donc un objet de type "double", local à ta fonction. Au
moment où tu sors de la fonction, cet objet est détruit, et son
adresse, stockée dans le tableau, ne veut plus rien dire.
Il y a des moyens de contourner ce problème, en gérant plus finement
la durée de vie des objets, mais c'est casse-gueule.
Boost::any serait sans doute plus adapté qu'un "void*".
D'ailleurs, je ne comprends pas ta démarche : si la fonction chargée
de remplir le tableau, et la fonction qui l'utilise, connaissent
toutes les deux les types des éléments, pourquoi faire un tableau de
void* ?
Il serait tellement plus simple d'écrire :
class CParams
{
public:
struct LesElements
{
double aA;
int aB;
CObjet aC;
};
LesElements les_elements;
"calloc", c'est du C. Même si, stricto sensu, on peut les utiliser en C++, je te conseille fortement d'utiliser new ou new[] à la place.
Mais même ceux-là, on peut généralement éviter de les utiliser.
En C++, un tableau, c'est std::vector<>, sauf si on a une bonne raison d'utiliser autre chose.
Il faudrait donc écrire, dans la déclaration de ta classe, à la place de "iNbArgs" et "theArgs" : std::vector<void*> theArgs;
puis, dans ta fonction Set() :
theArgs.erase (theArgs.begin(), theArgs.end()); /* Vider le tableau, si tu le juges nécessaire */
theArgs[0] = &aA;
theArgs.push_back (&aA); theArgs.push_back (&aB);
Sauf que... Ça ne marche pas.
void CParams::Set(double aA, int aB, CObject aC)
"aA" est donc un objet de type "double", local à ta fonction. Au moment où tu sors de la fonction, cet objet est détruit, et son adresse, stockée dans le tableau, ne veut plus rien dire.
Il y a des moyens de contourner ce problème, en gérant plus finement la durée de vie des objets, mais c'est casse-gueule. Boost::any serait sans doute plus adapté qu'un "void*".
D'ailleurs, je ne comprends pas ta démarche : si la fonction chargée de remplir le tableau, et la fonction qui l'utilise, connaissent toutes les deux les types des éléments, pourquoi faire un tableau de void* ?
Il serait tellement plus simple d'écrire :
class CParams { public: struct LesElements { double aA; int aB; CObjet aC; }; LesElements les_elements;