Class function & TList.sort [Résolu]

Messages postés
1015
Date d'inscription
samedi 25 octobre 2003
Dernière intervention
29 août 2013
- - Dernière réponse : Guillemouze
Messages postés
1015
Date d'inscription
samedi 25 octobre 2003
Dernière intervention
29 août 2013
- 27 oct. 2006 à 13:44
salut tout le monde, je viens de rencontrer un probleme plutot etrange, voire depitant :$
j'ai essayé de faire un TObjectList.sort avec class function commme fonction de comparaison. lors de l'appel de cet tri, j'ai une erreur de pointeur. Et lorsque je met un point d'arret sur la fonction de comparaison, il me met que l'adresse de Item2 est $4 . Encore plus etrange, la valeur de self correspond a un element de ma liste a trier ! Est ce que quelqu'un aurit une idée du pourquoi du comment?!!!

voici un "a peu pres" de mon code

type
    TMaListe = class(TObjectList)
       class function compare(item1, item2: pointer): integer;
    end;
   
    TMesObjetsDeListe = class
    public
       cmpChamp: integer;
    end;

class function TMaListe.compare(item1, item2: pointer): integer;
begin
    //ici : item1 est bien en element de ma liste, item2 est $4, self est un element de ma liste !!!
    result := compareValue(TMesObjetsDeListe(item1).cmpChamp, TMesObjetsDeListe(item2).cmpChamp);
end;

Dans une autre unité

procedure UneAutreClasse.UneProcedure;
var
    maListe: TMaListe;
begin
  //creation et remplissage de la liste
  ...
  maListe.sort(@TMaListe.compare);
  ...
end;

Merci de votre aide
Afficher la suite 

Votre réponse

17 réponses

Meilleure réponse
Messages postés
900
Date d'inscription
vendredi 3 novembre 2000
Dernière intervention
30 juillet 2009
3
Merci
<TECH>
en fait il te met sur la pile (du pc) les parametres et l'adresse de l'objet ainsi que de la methode au lieu de mettre seulement l'adresse la function et les parametres. c'est du a ton erreur de type.

A mon avis, comme t'as une erreur de type, ce qui devrait etre les parametres sont en fait l'adresse de l'object(self) et l'adresse de ta methode ($4).
</TECH>

c'est pour cela qu'il fat declarer ta function EN DEHORS de ta class et cela marchera.

Essaie stp.

(TIPS: note que si tu veux, la function qui est en dehors de la class peut très bien appeler une methode de class de ta list)

Merci cs_Loda 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 101 internautes ce mois-ci

Commenter la réponse de cs_Loda
Messages postés
4580
Date d'inscription
samedi 19 janvier 2002
Dernière intervention
9 janvier 2013
3
Merci
D'un côté tu écris :
TListSortCompare = function (Item1, Item2: Pointer): Integer;
Et de l'autre, tu déclares une méthode :
    TMaListe = class(TObjectList)
       class function compare(item1, item2: pointer): integer;
    end;

C'est bien pour cela que ça fonctionne quand tu sors la fonction de la classe.
Attention à ne pas confondre une fonction ou une procédure avec une méthode !!!
Donc, quand tu écris également : "donc j'ai fait une fonction qui a le meme prototype", là je dis non, ce n'est pas pareil.

May Delphi be with you !
<hr color="#008000" />
Pensez à cliquer sur Réponse acceptée lorsque la réponse vous convient.

Merci cs_Delphiprog 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 101 internautes ce mois-ci

Commenter la réponse de cs_Delphiprog
Messages postés
4580
Date d'inscription
samedi 19 janvier 2002
Dernière intervention
9 janvier 2013
3
Merci
Non Guillemouze, ça n'a rien à voir avec le passage de paramètres.
 Pour info, Delphi se charge du mode de passage des paramètres. Les trois premiers paramètres étant passés par les registres (EAX, EDX et ECX) et les autres étant passés sur la pile.

Une méthode est une procédure d'un objet. En résumé :
TMethod = procedure of object ;
C'est le "of object" qui permet de faire la différence.

May Delphi be with you !
<hr color ="#008000" />
Pensez à cliquer sur Réponse acceptée lorsque la réponse vous convient.

Merci cs_Delphiprog 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 101 internautes ce mois-ci

Commenter la réponse de cs_Delphiprog
Messages postés
900
Date d'inscription
vendredi 3 novembre 2000
Dernière intervention
30 juillet 2009
3
Merci
non, sauf que tu peux mettre la function global dans une autre unite que la class.

Merci cs_Loda 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 101 internautes ce mois-ci

Commenter la réponse de cs_Loda
Messages postés
4580
Date d'inscription
samedi 19 janvier 2002
Dernière intervention
9 janvier 2013
0
Merci
Les méthodes de classe ne doivent jamais faire référence à des variables ou propriétés d'une classe qu'elles n'ont pas instancié.
La solution consiste à retirer le mot "class" dans le cas présent..
Note aussi que dans ton code ci-dessus, tu crées une relation de forte dépendance  entre les classes TMaListe et TMesObjetsDeListe en transtypant Item1 et Item2. D'un point de vue conceptuel, ce n'est jamais souhaitable.

May Delphi be with you !
<hr color="#008000" />
Pensez à cliquer sur Réponse acceptée lorsque la réponse vous convient.
Commenter la réponse de cs_Delphiprog
Messages postés
1015
Date d'inscription
samedi 25 octobre 2003
Dernière intervention
29 août 2013
0
Merci
oui mais je sais que Tmaliste contient uniquement des objets de la classe Tmesobjetsdeliste.

en ce qui concerne la fonction de classe, elle ne depend nulement de variables ou proprietes de la classe. je souhaite mettre la fonction dans la classe car c'est une fonction qui est fortement liée a celle ci.
Commenter la réponse de Guillemouze
Messages postés
900
Date d'inscription
vendredi 3 novembre 2000
Dernière intervention
30 juillet 2009
0
Merci
salut,

d'abord cela serrait une bonne idée de déclarer des type pointeur:
(c'est plus propre)
type PMesObjetsDeListe = ^TMesObjetsDeListe;
TMaListe.compare(item1, item2: PMesObjetsDeListe ): integer;

ensuite, comment as-tu déclarer .sort?
selon les sympthome, c'est du a un problpme avec ton type function.

si tu fait:
Type TCompareFct = function(item1,item2 : PMesObjetsDeListe ) of object;
function TMaListe.compare(item1, item2: PMesObjetsDeListe ): integer;
(sans le class)
et
sort(fct : TCompareFct )

cela devrait marcher.

bon code,
Commenter la réponse de cs_Loda
Messages postés
1015
Date d'inscription
samedi 25 octobre 2003
Dernière intervention
29 août 2013
0
Merci
la fonction sort est celle de tlist !
procedure Sort(Compare: TListSortCompare);
et
type TListSortCompare = function (Item1, Item2: Pointer): Integer;

donc j'ai fait une fonction qui a le meme prototype.
Commenter la réponse de Guillemouze
Messages postés
900
Date d'inscription
vendredi 3 novembre 2000
Dernière intervention
30 juillet 2009
0
Merci
pardon j'avais pas fait gaffe,

alors ca vient de là. tu ne peut pas lui passer une function de class ou une methode. c'est tout. dsl.

donc tu doit declarer ta function EN DEHORS de ta class.
Commenter la réponse de cs_Loda
Messages postés
1015
Date d'inscription
samedi 25 octobre 2003
Dernière intervention
29 août 2013
0
Merci
c'est ce que je me suis dit, mais ca marche presque.
le comportement est quand meme etrange. le fait que self et item1 correspondent bien a des valeurs de ma liste est une pure coincidence, ou bien il y aurait peut etre une once de solution qui pointe son nez?
Commenter la réponse de Guillemouze
Messages postés
900
Date d'inscription
vendredi 3 novembre 2000
Dernière intervention
30 juillet 2009
0
Merci
PS:

vire le @. il n'est pas necessaire ici.

maListe.sort(TMaListe.compare);
Commenter la réponse de cs_Loda
Messages postés
1015
Date d'inscription
samedi 25 octobre 2003
Dernière intervention
29 août 2013
0
Merci
oui mais si c'est une methode de classe, donc elle n'a pas d'adresse d'instance ni de champs. donc ca "pourrait" etre possible.
bien sur que si je sors ma fonction, cela marche sans probleme, c'est ce que j'ai fait, mais j'aurai preferé la mettre à l'interieur de ma classe
Commenter la réponse de Guillemouze
Messages postés
1015
Date d'inscription
samedi 25 octobre 2003
Dernière intervention
29 août 2013
0
Merci
donc c'est vraiment pas possible :s

la difference entre une procedure/fonction et une methode est donc le passage des parametres sur la pile? si j'ai bien compris, quand on appele une fonction, la pile contient
paramX
...
param1
param0
et quand on appele une methode, c'est :
paramX
...
param1
param0
PtrVersLInstanceDeLaClasse(=self)
?

en tout cas, merci pour toutes ces precisions :)
Commenter la réponse de Guillemouze
Messages postés
1015
Date d'inscription
samedi 25 octobre 2003
Dernière intervention
29 août 2013
0
Merci
ah ok merci.
dans ce cas la est tu en mesure de me donner plus d'infos sur l'impact du "of object"?
et donc comment se fait il que dans ma class function, mes 2 parametres se retrouvent dans self et le 1erParametre.
Commenter la réponse de Guillemouze
Messages postés
900
Date d'inscription
vendredi 3 novembre 2000
Dernière intervention
30 juillet 2009
0
Merci
dans system.pas tu trouve:
type
TProc = procedure;

TMethod = record
Code, Data: Pointer;
end;

tu vois bien que la différence entre une procedure et une methde c'est qu'une methode est accompagnée de l'adresse de l'object. c'est pour cela que tu le trouve a la place d'un des parametres. Note que c'est juste le symtome d'une erreur. te creusses pas trop avec ça. l'important c'est que cela marche.


proposition de solution intermetiaire:


TMaClass = class

// met ton code ici:
class function CompareByXxx(Item1,Itemn2 : Pointer) : Integer;

end;

// passe cette function a ton List.sort :
procedure CompareByXxx(Item1,Item2 : Pointer) : INteger;
begin
Result := TMaClass.CompareByXxx(Item1,Item2);
end;

bon code,
Commenter la réponse de cs_Loda
Messages postés
1015
Date d'inscription
samedi 25 octobre 2003
Dernière intervention
29 août 2013
0
Merci
mwais, mais dans ce cas la il n'y a pas grande difference avec l'implementation directe de la comparaison dans la fonction globale.

donc merci a vous loda et delphiprog pour toute cette aide, je vais laisser uniquement une fonction globale.
Commenter la réponse de Guillemouze
Messages postés
1015
Date d'inscription
samedi 25 octobre 2003
Dernière intervention
29 août 2013
0
Merci
c'est vrai que ca peut etre interessant, pour une compilation plus rapide. petit exemple

unit u1;
interface
type
    C1 = class
       class function triC1(item1, item2: pointer): integer;
    end;

implementation

class function C1.triC1(item1, item2: pointer): integer;
begin
   blablabla
end;
....
unit u20;
.... // idem pour 20 unit differents

unit fctTri;
interface
    function fctTriC1(item1, item2:pointer): integer;
    ...
    function fctTriC20(item1, item2:pointer): integer;

implementation

uses U1, ..., U20; //uses dans implementation => moins de recompilation

function fctTriC1(item1, item2:pointer): integer;
    result := C1.triC1(item1, item2);
end;
...
Commenter la réponse de Guillemouze

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.