Copie d'objet en référence

Résolu
codea Messages postés 94 Date d'inscription dimanche 9 mai 2004 Statut Membre Dernière intervention 6 août 2006 - 20 nov. 2005 à 15:59
 Renfield - 24 nov. 2005 à 11:42
Il y a déja un forum sur ce sujet mais qui hélas n'a pa été répondu.



Le problème est qu'en Vb, un objet passé en référence que l'on réafecte
a un nouvel objet modifiera également l'objet référencé. Exemple:



sub CopieObj(Byref Obj1 as cObject)

dim Obj2 as New cObject

Set Obj2=Obj1

'la modif de l'objet 2 va modifier aussi l'objet 1 , ce que je ne veux pas !

Obj2.value="test"

' On pourrait constater que Obj1.Value=Obj2.value ....



End sub



J'ai une classe a copier qui hélas a une complexité beacoup plus grande
et commencer a copier valeurs par valeurs serait bien long.



Qqun aurait une solution a ce problème ?


Rien ne sert de courir, il faut partir à point

Jean de la fontaine

31 réponses

crenaud76 Messages postés 4172 Date d'inscription mercredi 30 juillet 2003 Statut Membre Dernière intervention 9 juin 2006 28
21 nov. 2005 à 11:19
En VB6, les objets sont touours passé par référence, tout simplement parce que lorsque tu mets ceci ...

sub CopieObj(Byref Obj1 as cObject)
....
End sub

ou même ceci ...

sub CopieObj(Byval Obj1 as cObject)
....
End sub

VB ne transmet pas réellement Obj1 à la procédure CopieObj, il transmet un entier sur 32b représentant l'@ de l'objet en mémoire. Donc que tu mettes ByVal ou byRef, cela ne change rien ... LES OBJETS SONT TOUJOURS PASSE PAR REFERENCE.
pour faire une recopie de Obj1 vers Obj2, il faut passer par l'API RtlMoveMemory, déclarée comme ceci :

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
... et utilisée comme ceci ...

CopyMemory ObjPtr(Obj2), ObjPtr(Obj1), Ici la taille en mémoire de tes objets.

.. en lieu et place de la ligne

Set Obj2 = Obj1

Le seul Hic, c'ets si tes objets contiennent des string de longueur variable, tu va avoir des soucis pour connaitre la taille de tes objets !!!

CR
3
PCPT Messages postés 13272 Date d'inscription lundi 13 décembre 2004 Statut Membre Dernière intervention 3 février 2018 47
20 nov. 2005 à 16:56
salut,
remplace ton ByRef par ByVal
@+
PCPT [AFCK]
0
cs_CanisLupus Messages postés 3757 Date d'inscription mardi 23 septembre 2003 Statut Membre Dernière intervention 13 mars 2006 21
20 nov. 2005 à 17:03
Salut,
Quand tu fais un set obj2 = obj1, obj2 prend toutes les propriétés de obj1, y compris sa position et sa taille, tu vois où je veux en venir ?
Ton obj2 se colle donc par-dessus ton obj1, d'où l'illusion que l'objet de départ affiche la même chose que obj2.
Décale ton obj2 : obj2.top = obj1.top + obj1.height et tu verras qu'il y a une différence.

-------------------------------------------------
Dresseur de puces, .... normal pour un loup !?
0
PCPT Messages postés 13272 Date d'inscription lundi 13 décembre 2004 Statut Membre Dernière intervention 3 février 2018 47
20 nov. 2005 à 17:11
cObject me semble plus être une classe qu'un composant ;)
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
codea Messages postés 94 Date d'inscription dimanche 9 mai 2004 Statut Membre Dernière intervention 6 août 2006
20 nov. 2005 à 17:26
Effectivement comme le mentionne pcpt, cObject est une classe.



J'ai essayé ton truc pcpt, remplacer byref par byval, et ca donne le
même résultat, ca modifie quand même l'instance de la classe passée en
paramètres...



je retourne étudier le problème ... merci bcp quand même les gars ;o) , si vous avez d'autre idées... ne vous gênez pas ....




Rien ne sert de courir, il faut partir à point

Jean de la fontaine
0
cs_CanisLupus Messages postés 3757 Date d'inscription mardi 23 septembre 2003 Statut Membre Dernière intervention 13 mars 2006 21
20 nov. 2005 à 17:31
Tu as raison pcpt. Mais c'est le même principe, enfin faudrait savoir si c'est du vb6 ou du vb.net, les comportements ne sont pas tout à fait les mêmes.

-------------------------------------------------
Dresseur de puces, .... normal pour un loup !?
0
codea Messages postés 94 Date d'inscription dimanche 9 mai 2004 Statut Membre Dernière intervention 6 août 2006
20 nov. 2005 à 17:32
Je me demande si y aurait pas moyen d'utiliser un memCopy ... pour
faire un genre de propriété .clone d'une instance de classe... ?

Rien ne sert de courir, il faut partir à point

Jean de la fontaine
0
codea Messages postés 94 Date d'inscription dimanche 9 mai 2004 Statut Membre Dernière intervention 6 août 2006
20 nov. 2005 à 17:33
C'est du VB6
Rien ne sert de courir, il faut partir à point

Jean de la fontaine
0
PCPT Messages postés 13272 Date d'inscription lundi 13 décembre 2004 Statut Membre Dernière intervention 3 février 2018 47
20 nov. 2005 à 18:26
re,
il faut un ByVal, par logique.
il y a celà dit un 2e point important : comment initialises-tu ta classe?
c'est à dire....

dim aCC as new cCC
Set aCC = Picture3

ou l'Initialize ne contient rien de particulier?

là où je veux en venir, c'est que selon ta classe par elle-même, il est possible que tu aies à déclarer

sub CopieObj(ByVal Obj1 as cObject)
dim Obj2 as New Obj1
Set Obj2=Obj1
Obj2.value="test"
End sub

.... à voir.....
PCPT [AFCK]
0
cs_CanisLupus Messages postés 3757 Date d'inscription mardi 23 septembre 2003 Statut Membre Dernière intervention 13 mars 2006 21
20 nov. 2005 à 18:41
Je rajouterai que si dim Obj2 as New Obj1 possible, pas besoin de Set Obj2=Obj1

-------------------------------------------------
Dresseur de puces, .... normal pour un loup !?
0
codea Messages postés 94 Date d'inscription dimanche 9 mai 2004 Statut Membre Dernière intervention 6 août 2006
20 nov. 2005 à 18:42
Espérant que ca aide a mieux comprendre... moi je comprends pas ...

et quand je fais :

sub CopieObj(ByVal Obj1 as cObject)

dim Obj2 as New Obj1

Set Obj2=Obj1

Obj2.value="test"

End sub

ca me retoutne déclaration d'un objet de type non défini par L'utilisateur


Initialisation de ma classe:

Fonction initialisation:



Public Sub Nouvel_Horaire()

ReDim Preserve horaire(m_Hr_Count)

Set horaire(m_Hr_Count) = New cHoraire

CurHr = m_Hr_Count

m_Hr_Count = m_Hr_Count + 1

End Sub



'CAS #1 CRÉER UN HORAIRE, AVEC LES FONCTIONS DE LA CLASSE

horaire(CurHr).Attribuer_Commandes cmds, Val(cmbHeuristique.Text)



'CAS #2 : UTILISER UN HORAIRE EXISTANT AFIN DE L'AMÉLIORER

Private Sub mnuTabuSearch_Click()

Dim Optimise As New cOptimisation

Dim HoraireAOptimiser As cHoraire

Set HoraireAOptimiser = horaire(CurHr)

Nouvel_Horaire

Set horaire(CurHr) = Optimise.Optimise(HoraireAOptimiser, eFouilleLocale)

Ens Sub



'CONTENU DE LA CLASSE HORAIRE:

'=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Private m_Commandes As cCommandes 'copie locale

Private mvarNb_Total_Commandes As Integer 'copie locale

Private mvarNb_Jours_Horizon As Integer 'copie locale

Private m_WorkCenters As New cWorkCenters

Private m_Tardivete As Single

Private Setup As New cSetup

Public Property Get Tardivete() As Single

Dim Dp As Single

Dim Fd As Single

m_Tardivete = 0

For i = 0 To m_Commandes.Count

Dp = m_Commandes.Commande(i).Date_promise

Fd = m_Commandes.Commande(i).Date_Fin

If Dp < Fd Then

m_Tardivete = m_Tardivete + (Fd - Dp)

End If

Next i

Tardivete = Round(m_Tardivete, 2)

End Property

Public Property Let NB_JOURS_HORIZON(ByVal vData As Integer)

mvarNb_Jours_Horizon = vData

End Property



Public Property Get NB_JOURS_HORIZON() As Integer

NB_JOURS_HORIZON = mvarNb_Jours_Horizon

End Property



Public Property Let Nb_Total_Commandes(ByVal vData As Integer)

mvarNb_Total_Commandes = vData

End Property

Public Property Get Nb_Total_Commandes() As Integer

Nb_Total_Commandes = mvarNb_Total_Commandes

End Property

Public Property Get machines() As cWorkCenters

Set machines = m_WorkCenters

End Property



Public Sub Add_DB_Commandes()



'FONCTION QUI N'EST PAS UTILISÉE EN CE MOMENT

Mydata.cListCmd

With Mydata.rscListCmd

'on parcours toutes les commandes

Do Until .EOF = True

Mydata.cListOpByCmd !IdCmd

m_Commandes.Add_Text !CmdId,
!CmdQte, !CmdDate_Promise, !CmdDate_Release, Mydata.rscListOpByCmd

Mydata.rscListOpByCmd.Close

.MoveNext

Loop

.Close

End With

End Sub

Public Sub Attribuer_Commandes(ByRef cmds As cCommandes, ByVal Heuristic As Integer)

Dim i, j As Integer

'CRÉATION DE LA TABLE DES TEMPS DE SETUP POUR LES COULEURS

'ON ATTRIBUE LES COMMANDES A L'HORAIRE

mvarNb_Total_Commandes = cmds.Count

Set m_Commandes = cmds

'ON ATTACHE TOUTES LES OPERATIONS SUR LES MACHINES

Dim Affecte As New cAffectation

Attribuer_Machines

Set m_WorkCenters = Affecte.AffectationDynamique(cmds, Heuristic)

End Sub

Public Property Get Commande(ByVal i As Integer) As cCommande

Set Commande = m_Commandes.Commande(i)

End Property

Public Property Get commandes() As cCommandes

Set commandes = m_Commandes

End Property

Public Sub Attribuer_Machines()

m_WorkCenters.Add_BD_WC

End Sub



'

'

'=-=-=-=-=-=-==-=-=-=-=-=-==-=-=-=-=-=-==-=-=-=-=-

' CALCUL DES CRITERES DE PERFORMANCE

'=-=-=-=-=-=-==-=-=-=-=-=-==-=-=-=-=-=-==-=-=-=-=-



Public Property Get Nb_Retards() As Integer

m_Tardivete = 0

For i = 0 To m_Commandes.Count

If m_Commandes.Commande(i).Date_promise < m_Commandes.Commande(i).Date_Fin Then


m_Tardivete = m_Tardivete + m_Commandes.Commande(i).Date_Fin -
m_Commandes.Commande(i).Date_promise

Nb_Retards = Nb_Retards + 1

End If

Next i

End Property



'

'

Public Property Get FlowTime() As Single

For i = 0 To m_Commandes.Count


FlowTime = FlowTime + m_Commandes.Commande(i).Operations_Worktime -
m_Commandes.Commande(i).Date_Release

Next i

End Property



'

'

Public Property Get EndofScheduleTime() As Single

Dim table()

Dim sort As New cSort

ReDim table(m_Commandes.Count)

For i = 0 To m_Commandes.Count

table(i) = m_Commandes.Commande(i).Date_Fin

Next i

sort.FastQuickSort table

EndofScheduleTime = table(m_Commandes.Count)

End Property

Public Property Get FactEtroitesse() As Single

FactEtroitesse = 1 - Round((m_Commandes.MoyenneDP / EndofScheduleTime), 2)

End Property

Public Property Get AvgWip() As Single

AvgWip = FlowTime / EndofScheduleTime

End Property

Public Property Get EtendueDP() As Single

Dim i As Integer

Dim Max As Single, min As Single

Dim math As New cMath

Dim MyDates()

ReDim MyDates(m_Commandes.Count)

For i = 0 To m_Commandes.Count

MyDates(i) = m_Commandes.Commande(i).Date_promise

Next i

Max = math.MiniMax(e_Max, MyDates)

min = math.MiniMax(e_Min, MyDates)

Set math = Nothing

EtendueDP = ((Max - min)) / EndofScheduleTime

End Property

Private Sub Class_Initialize()

mvarNb_Total_Commandes = 0

mvarNb_Jours_Horizon = 0

End Sub










Rien ne sert de courir, il faut partir à point

Jean de la fontaine
0
PCPT Messages postés 13272 Date d'inscription lundi 13 décembre 2004 Statut Membre Dernière intervention 3 février 2018 47
20 nov. 2005 à 18:49
sur ta Form principal (... en question), quelles sont tes déclarations de classes.
et dans ta classe cObjet, quel est le contenu de Public Sub Initialize()
0
codea Messages postés 94 Date d'inscription dimanche 9 mai 2004 Statut Membre Dernière intervention 6 août 2006
20 nov. 2005 à 18:58
ben en fait, je c pas si le post que j'ai mis précédemment était affiché quand tu me poses ta question , mais voila

dans un module

Global horaire() As cHoraire



et ma classe objet bien ... tu l'as plus haut



je crois que je vais me résoudre a faire avec ...


Rien ne sert de courir, il faut partir à point

Jean de la fontaine
0
PCPT Messages postés 13272 Date d'inscription lundi 13 décembre 2004 Statut Membre Dernière intervention 3 février 2018 47
20 nov. 2005 à 19:07
il était affiché.
ma question a pour but de savoir comment tu utilises ta classe.
j'ai lu ton code, çà ne me répond pas....

voici un exemple avec un composant


Option Explicit
'
'
Private Sub Form_Load()
Picture1.Picture = LoadPicture ("C:\tmp.jpg")
End Sub
'
'
Private Sub Command1_Click()
Set Picture2 = Picture1
End Sub
'
'
Private Sub Command2_Click()
Picture2.Picture = Nothing
End Sub


<SMALL> Coloration syntaxique automatique [AFCK]</SMALL>


ici, Cmd1 affiche entre autre l'image de Pic1 dans Pic2.
mais au Cmd2_Click, seul Pic2 se vide. en aucun cas Pic1 n'est altérée.
0
codea Messages postés 94 Date d'inscription dimanche 9 mai 2004 Statut Membre Dernière intervention 6 août 2006
20 nov. 2005 à 21:05
petit exemple qui démontre ce que j'essaie de dire ! ...



si on suit l'évolution de la variable c à l'aide d'un espion, elle est
quand même modifiée par la fonction Modifier, et ne le devrait pas
puisque l'on fait un passage byval ... je voudrais que la fonction
Modifier ne modifie pas la valeur de la varaible c dans le FormLoad



--=-

COPIER DANS FORM1

-=-

Private Sub Form_Load()

Dim c As New cTest

c.modify = 1

Modifier c

End Sub



Private Sub Modifier(ByVal myvar As Object)

myvar.modify = 100

End Sub



--=-

COPIER DANS UN NOUVEAU MODULE DE CLASSE APPELÉ CTEST

--=-=

Private m_var As Integer



Public Property Let modify(v As Integer)

m_var = v

End Property



Public Property Get modify() As Integer

modify = m_var

End Property










Rien ne sert de courir, il faut partir à point

Jean de la fontaine
0
PCPT Messages postés 13272 Date d'inscription lundi 13 décembre 2004 Statut Membre Dernière intervention 3 février 2018 47
20 nov. 2005 à 22:19
re,
mais ton exemple est totalement normal et c'est un cas de figure ou le ByVal/ByRef n'intervient pas.

peut-être ai-je mal compris.....


'=-=-=-
'COPIER DANS FORM1
'=-==-
'
'
Option Explicit
'
Dim b As New CTEST
Dim c As New CTEST
'
'
Private Sub Form_Load()
Me.Show

Set b = New CTEST
Debug.Print "b est initialisée et contient " & b.modify

b.modify = 1
Debug.Print "b est modifiée par PROP et contient " & b.modify

Set c = b
Debug.Print "c est initialisée et contient " & c.modify

Modifier c
Debug.Print "c est modifiée par SUB et contient " & c.modify
End Sub
'
'
Private Sub Modifier(ByVal myvar As Object)
myvar.modify = 100
End Sub
'
'
Private Sub Form_Unload(Cancel As Integer)
Set b = Nothing
Set c = Nothing
End Sub

'=-=-=-
'COPIER DANS UN NOUVEAU MODULE DE CLASSE APPELÉ CTEST
'=-=-=-=
'
'
Option Explicit
'
Private m_var As Integer
'
'
Public Property Let modify(v As Integer)
m_var = v
End Property
'
'
Public Property Get modify() As Integer
modify = m_var
End Property


<SMALL> Coloration syntaxique automatique [AFCK]</SMALL>


PCPT [AFCK]
0
codea Messages postés 94 Date d'inscription dimanche 9 mai 2004 Statut Membre Dernière intervention 6 août 2006
20 nov. 2005 à 22:30
On s'entend :o)



mais comment faire pour que c devienne une copie, et que b ne soit pas
modifié si c est modifié ? C'est ce que je cherche a faire depuis le
début !



ps: merci pour ton dévouement à mon problème depuis le matin ... :o) ... (je suis au québec en passant comme ca)



@+

Rien ne sert de courir, il faut partir à point

Jean de la fontaine
0
PCPT Messages postés 13272 Date d'inscription lundi 13 décembre 2004 Statut Membre Dernière intervention 3 février 2018 47
20 nov. 2005 à 22:42
exact !

je viens d'ajouter Debug.Print "b vérifie?? " & b.modify en fin de Form_Load... = 100
déception!!!
je continue sur cet exemple
(bonjour Québec)
0
PCPT Messages postés 13272 Date d'inscription lundi 13 décembre 2004 Statut Membre Dernière intervention 3 février 2018 47
20 nov. 2005 à 23:06
j'avoue rester perplexe.....

voici une solution, mais sans doute non valable pour la vraie classe!


Private Sub Form_Load()
Me.Show

Set b = New CTEST
Debug.Print "b est initialisée et contient " & b.modify

b.modify = 1
Debug.Print "b est modifiée par PROP et contient " & b.modify

Set c = New CTEST
Debug.Print "c est initialisée et contient " & c.modify

c.modify = b.modify
Debug.Print "c est modifiée par PROP et contient " & c.modify

Modifier c
Debug.Print "c est modifiée par SUB et contient " & c.modify

Debug.Print "b vérifie?? " & b.modify
End Sub
'
'
Private Sub Modifier(ByRef MyVar As CTEST)
MyVar.modify = 100
End Sub


<SMALL> Coloration syntaxique automatique [AFCK]</SMALL>


apparemment, dès que l'objet est lié, seul un Nothing le dé-lie...
j'ai aussi essayé en passant par une 3e Var en locale (sub) détruite avant l'affichage final, pareil!
0
codea Messages postés 94 Date d'inscription dimanche 9 mai 2004 Statut Membre Dernière intervention 6 août 2006
21 nov. 2005 à 03:07
Je sais ... je deviens dingue avec cette histoire de copie... rien a y faire ...

le problème c le set je crois ... y faudrais un autre mot clef du genre
copy .... p-e que cela serait possible mais avec un memCopy appelé avec
une dll api ... mais ca serait un peu complexe a réaliser ... ensuite
le truc devient une propritété .clone de la classe qui fonctionne avec
le memCopy ... mais c riducule ... dans la Doc de Vb ils parlent du Set
pour réaliser une référence sur un objet existant ... le new pour créer
un nouvel objet .... et rien pour copier un objet déja existant dans un
autre objet sans référence ...



Finalement, avec une classe un peu complexe (constituée de plusieurs
classes) ils serait vraiment pratique de pouvoir la copier sans avoir a
copier "Manuellement par affectation " toute les valeurs dans la
nouvelle classe... je suis surpris que personne n'ait encore rien
trouvé la dessus ? ... ou du moins j'ai rien trouvé d'évident a ce
sujet !!!...




Rien ne sert de courir, il faut partir à point

Jean de la fontaine
0
Rejoignez-nous