PC SOFT

FORUMS PROFESSIONNELS
WINDEVWEBDEV et WINDEV Mobile

Accueil → WINDEV 2024 → Copier (Cloner) un tableau d'objet dans un autre
Copier (Cloner) un tableau d'objet dans un autre
Débuté par Valentin, 28 juin 2017 17:12 - 6 réponses
Posté le 28 juin 2017 - 17:12
Bonjour,

Je bloque depuis un moment, je n'arrive pas un cloner un tableau d'objet dans un autre. A chaque fois cela fais une copie par référence.

monObjet1 est une Classe
sMachaine est une chaîne


tab_Objet1 est un tableau de monObjet1 dynamique

monObjet2 est une Classe
LOCAL
t_monObjet1 est un tableau locallocal de monObjet1 dynamique


POUR i = 1 A 5
TableauAjoute(tab_Objet1, allouer monObjet1(Caract(i)))
FIN

cl_monObjet2 est un monObjet2
cl_monObjet2.t_monObjet1 <= tab_Objet1

// On fais un test en modifiant une valeur
cl_monObjet2.t_monObjet1[2].sMachaine = "Test"
// la valeur a été modifié dans l'autre tableau
Info(tab_Objet1[2].sMachaine)


Ai-je oublié quelque chose ?
Avez vous une solution ?


Merci d'avance
Membre enregistré
946 messages
Popularité : +102 (110 votes)
Posté le 29 juin 2017 - 16:48
Bonjour,
En effet c'est très très "louche". Pour essayer de comprendre j'ai effectué les tests suivants en Version Windev20:
1° Déclaration des deux variables en statique : tab_monObjet1 et cl_monObjet2
2° Initialisation de la première variable : ok, les variables de type chaine ont des adresses différentes
3° Initialisation de la seconde variable : ok, les variables de type chaine ont des adresses différentes

4a° copie avec la fonction "Transfert()" : ko, les variables de type chaine de destination de la copie sont modifiées.

4b° copie avec l'opérateur "<=" : ko, les variables de type chaine de destination de la copie sont modifiées et l'adresse de cl_monObjet2:t_monObjet21 est modifiée (pas dans le test 4a)

4c° copie avec les fonctions, Sérialise/Désérialise en mode binaire : ok et modifier tab_monObjet1 ne modifie pas cl_monObjet2:t_monObjet21

Essayez votre code en remplaçant la ligne "<=" par Sérialise/Désérialise en mode binaire

Code du test
i, j est un entier

tab_monObjet1 est un tableau de 5 monObjet1 // monObjet1 est une Classe
// sMachaine est une chaîne
// END
cl_monObjet2 est un monObjet2 // monObjet2 est une Classe
// t_monObjet21 est un tableau de 5 monObjet1
// END
BufferBin est un Buffer

//***************************************
// Affiche les adresses et les contenus
//***************************************
Trace("Etape #1 : variables non initialisées.")
Trace(ChaîneConstruit("tab_monObjet1 : 0x%1", NumériqueVersChaîne(&tab_monObjet1, "08X")))
Trace(ChaîneConstruit("cl_monObjet2:t_monObjet21 : 0x%1", NumériqueVersChaîne(&cl_monObjet2:t_monObjet21, "08X")))
FOR i=1 _TO_ 5
Trace(ChaîneConstruit("tab_monObjet1[%1]:sMachaine (%2) : 0x%3 ", ...
i, tab_monObjet1[i]:sMachaine, NumériqueVersChaîne(&tab_monObjet1[i]:sMachaine, "08X")))
END
FOR i=1 _TO_ 5
Trace(ChaîneConstruit("cl_monObjet2:t_monObjet21[%1]:sMachaine = (%2) : 0x%3",...
i, cl_monObjet2:t_monObjet21[i]:sMachaine, NumériqueVersChaîne(&cl_monObjet2:t_monObjet21[i]:sMachaine, "08X")))
END


//-----> Initialise les 5 tab_monObjet1[]:sMaChaine avec {A,..., F}
j = 1
FOR i = Asc("A") _TO_ Asc("E")
tab_monObjet1[j]:sMachaine = Caract(i)
j++
END
//***************************************
// Affiche les adresses et les contenus
//***************************************
Trace("Etape #2 : tab_monObjet1[j]:sMachaine initialisée.")
Trace(ChaîneConstruit("tab_monObjet1 : 0x%1", NumériqueVersChaîne(&tab_monObjet1, "08X")))
Trace(ChaîneConstruit("cl_monObjet2:t_monObjet21 : 0x%1", NumériqueVersChaîne(&cl_monObjet2:t_monObjet21, "08X")))
FOR i=1 _TO_ 5
Trace(ChaîneConstruit("tab_monObjet1[%1]:sMachaine (%2) : 0x%3 ", ...
i, tab_monObjet1[i]:sMachaine, NumériqueVersChaîne(&tab_monObjet1[i]:sMachaine, "08X")))
END
FOR i=1 _TO_ 5
Trace(ChaîneConstruit("cl_monObjet2:t_monObjet21[%1]:sMachaine = (%2) : 0x%3",...
i, cl_monObjet2:t_monObjet21[i]:sMachaine, NumériqueVersChaîne(&cl_monObjet2:t_monObjet21[i]:sMachaine, "08X")))
END


//-----> Initialise les 5 cl_monObjet2:t_monObjet21[j]:sMachaine avec {v,...,z}
j = 1
FOR i = Asc("v") _TO_ Asc("z")
cl_monObjet2:t_monObjet21[j]:sMachaine = Caract(i)
j++
END
//***************************************
// Affiche les adresses et les contenus
//***************************************
Trace("Etape #3 : cl_monObjet2:t_monObjet21[j]:sMachaine initialisée.")
Trace(ChaîneConstruit("tab_monObjet1 : 0x%1", NumériqueVersChaîne(&tab_monObjet1, "08X")))
Trace(ChaîneConstruit("cl_monObjet2:t_monObjet21 : 0x%1", NumériqueVersChaîne(&cl_monObjet2:t_monObjet21, "08X")))
FOR i=1 _TO_ 5
Trace(ChaîneConstruit("tab_monObjet1[%1]:sMachaine (%2) : 0x%3 ", ...
i, tab_monObjet1[i]:sMachaine, NumériqueVersChaîne(&tab_monObjet1[i]:sMachaine, "08X")))
END
FOR i=1 _TO_ 5
Trace(ChaîneConstruit("cl_monObjet2:t_monObjet21[%1]:sMachaine = (%2) : 0x%3",...
i, cl_monObjet2:t_monObjet21[i]:sMachaine, NumériqueVersChaîne(&cl_monObjet2:t_monObjet21[i]:sMachaine, "08X")))
END


//-----> copie tab_monObjet1 dans cl_monObjet2:t_monObjet21
//4a° transfert( &cl_monObjet2:t_monObjet21, &tab_monObjet1, 5*20) // BAD
//4b° cl_monObjet2.t_monObjet21 <= tab_monObjet1 // BAD
//4c° Sérialise(tab_monObjet1, BufferBin, psdBinaire); Désérialise(cl_monObjet2:t_monObjet21, BufferBin, psdBinaire) // OK

//***************************************
// Affiche les adresses et les contenus
//***************************************
Trace("Etape #4 : Copie effectuée.")
Trace(ChaîneConstruit("tab_monObjet1 : 0x%1", NumériqueVersChaîne(&tab_monObjet1, "08X")))
Trace(ChaîneConstruit("cl_monObjet2:t_monObjet21 : 0x%1", NumériqueVersChaîne(&cl_monObjet2:t_monObjet21, "08X")))
FOR i=1 _TO_ 5
Trace(ChaîneConstruit("tab_monObjet1[%1]:sMachaine (%2) : 0x%3 ", ...
i, tab_monObjet1[i]:sMachaine, NumériqueVersChaîne(&tab_monObjet1[i]:sMachaine, "08X")))
END
FOR i=1 _TO_ 5
Trace(ChaîneConstruit("cl_monObjet2:t_monObjet21[%1]:sMachaine = (%2) : 0x%3",...
i, cl_monObjet2:t_monObjet21[i]:sMachaine, NumériqueVersChaîne(&cl_monObjet2:t_monObjet21[i]:sMachaine, "08X")))
END
Posté le 30 juin 2017 - 10:44
Bonjour

Au vu de votre code, c'est tout à fait normal comme comportement.
Il faut bien comprendre ce que vous manipulez.
Vous déclarez des tableaux d'objets dynamiques, autrement dit, vous déclarez des tableaux de pointeurs.
Donc, quand vous faite cl_monObjet2.t_monObjet1 <= tab_Objet1, vous copiez les pointeurs.
Vous avez donc 2 tableaux distincts (leurs adresses sont différentes) avec le même contenu (les même pointeurs).
Il est donc logique que si vous modifiez le contenu d'un des objets pointé, cette modification se voit dans les 2 tableaux.

Et donc pour avoir le comportement que vous recherchez, retirez le mot 'dynamique' à la déclaration du tableau dans la classe. Il vous restera à choisir une méthode pour régler le problème du paramètre du constructeur de monObjet1.

Bon dev.

Laurent M.
Membre enregistré
20 messages
Posté le 30 juin 2017 - 13:59
Bonjour,

Merci pour vos réponses.
Du coup tout s'explique et cela fonctionne à merveille.

Merci

Valentin
Message modifié, 30 juin 2017 - 14:00
Membre enregistré
20 messages
Posté le 08 août 2017 - 09:30
Bonjour, je reviens vers vous car j'ai un problème légèrement similaire.

Donc j'ai ce bout de code (Qui me sers juste pour des tests) qui s’exécute différemment entre 2 projets.

gtab_t_MesMembres est un tableau de 0 cl_Stat_Membre
gtab_t_MesMembres2 est un tableau de 0 cl_Stat_Membre

i est un entier
POUR i = 1 A 5
TableauAjoute(gtab_t_MesMembres,allouer cl_Stat_Membre(" " + i," " + i,"Membre"))
TableauAjoute(gtab_t_MesMembres[i].t_TabSousMembre,allouer cl_Stat_Membre("1" + i,"1" + i,"SousMembre"))
TableauAjoute(gtab_t_MesMembres[i].t_TabSousMembre,allouer cl_Stat_Membre("2" + i,"2" + i,"SousMembre"))
TableauAjoute(gtab_t_MesMembres[i].t_TabSousMembre,allouer cl_Stat_Membre("3" + i,"3" + i,"SousMembre"))
FIN
gtab_t_MesMembres2 <= gtab_t_MesMembres

gtab_t_MesMembres[1].sCleMembre = "Test"
gtab_t_MesMembres[1].t_TabSousMembre[1].sCleMembre = "Test SOUS"


Dans le Premier projet, le comportement voulu, c'est à dire que les tableaux gtab_t_MesMembres et gtab_t_MesMembres2 sont bien indépendant (Il ne point pas sur les mêmes adresses). (Voir image) :

http://hpics.li/ba4a0bb

Mais dans le 2ième projet, les 2 tableaux sont liés. Je ne comprend pas pourquoi... . (Voir image) :

http://hpics.li/ce99623

La classe cl_Stat_Membre est identique dans les 2 projets. Le code a été copié/coller.

Le premier projet est un projet de test où il n'y a pas grand chose.
Le deuxième projet est un projet migré de la version 15 et utilisant le GDS.

Je doute que ces informations change quelque chose sur l’exécution du code mais on ne sais jamais

Merci d'avance pour votre aide.
Posté le 08 août 2017 - 10:49
Bonjour,
Dans la description du projet, onglet Compilation, il y a une option nommée
Tableaux : l'affectation copie le contenu.

Peut-être que les deux projets n'ont pas le même paramétrage.

Frédéric.

"Monsieur LEMAITRE" a écrit dans le message de groupe de discussion :
20172059d0bbcc687b4cc4ab51680be777b0@news.pcsoft.fr...

Bonjour, je reviens vers vous car j'ai un problème légèrement similaire.

Donc j'ai ce bout de code (Qui me sers juste pour des tests) qui s’exécute
différemment entre 2 projets.

gtab_t_MesMembres est un tableau de 0 cl_Stat_Membre
gtab_t_MesMembres2 est un tableau de 0 cl_Stat_Membre

i est un entier
POUR i = 1 A 5
TableauAjoute(gtab_t_MesMembres,allouer cl_Stat_Membre(" " + i," " +
i,"Membre"))
TableauAjoute(gtab_t_MesMembres[i].t_TabSousMembre,allouer
cl_Stat_Membre("1" + i,"1" + i,"SousMembre"))
TableauAjoute(gtab_t_MesMembres[i].t_TabSousMembre,allouer
cl_Stat_Membre("2" + i,"2" + i,"SousMembre"))
TableauAjoute(gtab_t_MesMembres[i].t_TabSousMembre,allouer
cl_Stat_Membre("3" + i,"3" + i,"SousMembre"))
FIN
gtab_t_MesMembres2 <= gtab_t_MesMembres

gtab_t_MesMembres[1].sCleMembre = "Test"
gtab_t_MesMembres[1].t_TabSousMembre[1].sCleMembre = "Test SOUS"


Dans le Premier projet, le comportement voulu, c'est à dire que les tableaux
gtab_t_MesMembres et gtab_t_MesMembres2 sont bien indépendant (Il ne point
pas sur les mêmes adresses). (Voir image) :

http://hpics.li/ba4a0bb

Mais dans le 2ième projet, les 2 tableaux sont liés. Je ne comprend pas
pourquoi... . (Voir image) :

http://hpics.li/ce99623

La classe cl_Stat_Membre est identique dans les 2 projets. Le code a été
copié/coller.

Le premier projet est un projet de test où il n'y a pas grand chose.
Le deuxième projet est un projet migré de la version 15 et utilisant le GDS.

Je doute que ces informations change quelque chose sur l’exécution du code
mais on ne sais jamais

Merci d'avance pour votre aide.
Membre enregistré
20 messages
Posté le 08 août 2017 - 16:32
Bonjour,

Merci pour votre message, c'était bien ça !

Cordialement