OVH Cloud OVH Cloud

Problème Accès Tableau de (void*)

1 réponse
Avatar
Stochastic
Bonjour

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

iNbArgs = 3

theArgs = (void **)calloc(iNbArgs, sizeof(void*))

theArgs[0] = &aA
theArgs[1] = &aB
theArgs[2] = &aC

// (*2

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

Stochastic

--
Stochastic

-----------------------------------------------------------------------
Voir theme: http://www.frbox.net/viewtopic-564675.htm

Envoyé de http://www.frbox.ne

1 réponse

Avatar
Fabien LE LEZ
On Tue, 2 May 2006 16:11:58 +0200, Stochastic
:

Voici alors ma fonction Set:


Plusieurs problèmes ici, dont une erreur manifeste.

void CParams::Set(double aA, int aB, CObject aC)

{
iNbArgs = 3;

theArgs = (void **)calloc(iNbArgs, sizeof(void*));


"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;

...
};