4D v16.3

Pointeurs

Accueil

 
4D v16.3
Pointeurs

Pointeurs  


 

Les pointeurs sont des outils de programmation avancée.

Lorsque vous utilisez le langage de 4D, vous vous référez aux différents objets par l’intermédiaire de leur nom — en particulier les tables, champs, variables et tableaux. Pour appeler l’un d’entre eux, vous écrivez simplement son nom. Cependant, il est parfois utile de pouvoir appeler ou référencer ces éléments sans nécessairement connaître leur nom. C’est ce que permettent les pointeurs.

Le concept de pointeur n’est pas tellement éloigné de la vie courante. Vous vous référez souvent à des choses sans connaître leur identité exacte. Par exemple, vous dites à un ami “Allons-y avec ta voiture” au lieu de “Allons-y avec la voiture immatriculée 123 ABD 99”. Dans ce cas, vous faites référence à la voiture immatriculée 123 ABD 99 en utilisant l’expression “ta voiture”. Par analogie, l’expression “la voiture immatriculée 123 ABD 99” est le nom d’un objet, et “ta voiture” est un pointeur référençant (ou pointant vers) l’objet.

La capacité de se référer à quelque chose sans connaître son identité exacte est très utile. Si votre ami s’achetait une nouvelle voiture, l’expression “ta voiture” serait toujours exacte — ce serait toujours une voiture et vous pourriez toujours aller quelque part avec. Les pointeurs fonctionnent de la même manière. Par exemple, un pointeur peut pointer à un moment donné vers un champ numérique appelé Age, et plus tard vers une variable numérique appelée Ancien âge. Dans les deux cas, le pointeur référence des données numériques pouvant être utilisée dans des calculs. Vous pouvez utiliser des pointeurs pour référencer des tables, des champs, des variables, des tableaux et des éléments de tableaux.

Le tableau suivant vous fournit un exemple de chaque type :

ObjetRéférencementUtilisationAffectation
TablevpTble:=->[Table]TABLE DEFAUT(vpTble->)n/a
ChampvpChp:=->[Table]ChpALERTE(vpChp->)vpChp->:="Jean"
VariablevpVar:=->VariableALERTE(vpVar->) vpVar->:="Jean"
TableauvpT:=->TableauTRIER TABLEAU(vpT->;>) COPIER TABLEAU(Tab;vpT->)
Elém. tabl.vpElem:=->Tableau{1}ALERTE(vpElem->)vpElem->:="Jean"

Il est plus facile d’expliquer l’utilisation des pointeurs au travers d’un exemple. Cet exemple vous montre comment accéder à une variable par l’intermédiaire d’un pointeur. Nous commençons par créer la variable :

 MaVar:="Bonjour"

MaVar est désormais une variable contenant la chaîne “Bonjour”. Nous pouvons alors créer un pointeur vers MaVar :

 MonPointeur:=->MaVar

Le symbole -> signifie “pointer vers” (ce symbole est formé du caractère “tiret” (-) suivi du caractère “supérieur à”). Dans ce cas, il crée un pointeur qui référence ou “pointe vers” MaVar. Ce pointeur est assigné à MonPointeur via l’opérateur d’assignation.

MonPointeur est désormais une variable qui contient un pointeur vers MaVar. MonPointeur ne contient pas “Bonjour”, la valeur de MaVar, mais vous pouvez utiliser MonPointeur pour obtenir la valeur contenue dans MaVar. L’expression suivante retourne la valeur de MaVar :

 MonPointeur->

Dans ce cas, la chaîne “Bonjour” est retournée. Lorsque le symbole -> est placé derrière un pointeur, la valeur de l’objet vers lequel pointe le pointeur est récupérée. On dit alors qu’on dépointe le pointeur.

Il est important de comprendre que vous pouvez utiliser un pointeur suivi du symbole -> partout où vous auriez pu utiliser l’objet pointé lui-même. Vous pouvez placer l’expression MonPointeur-> partout où vous pourriez utiliser la variable originale MaVar.

Par exemple, l'instruction suivante affiche une boîte de dialogue d’alerte comportant le mot Bonjour :

 ALERT(MonPointeur->)

Vous pouvez également utiliser MonPointeur pour modifier la valeur de MaVar. Par exemple, l’instruction suivante stocke la chaîne “Au revoir” dans la variable MaVar :

 MonPointeur->:="Au revoir"

Si vous examinez les deux utilisations de l’expression MonPointeur-> ci-dessus, vous constatez que cette expression se comporte exactement comme si vous aviez utilisé MaVar à sa place. En résumé : les deux lignes suivantes effectuent la même opération — elles affichent une boîte de dialogue d’alerte contenant la valeur courante de la variable MaVar :

 ALERT(MonPointeur->)
 ALERT(MaVar)

Les deux lignes suivantes effectuent la même opération ; elles assignent la chaîne "Au revoir" à MaVar :

 MonPointeur->:="Au revoir"
 MaVar:="Au revoir"

Ce paragraphe décrit l’utilisation d’un pointeur pour référencer un bouton. Un bouton (du point de vue du langage) n’est rien d’autre qu’une variable. Bien que les exemples de ce paragraphe utilisent des pointeurs pour référencer des boutons, les concepts présentés s’appliquent à l’utilisation de tout type d’objet pouvant être référencé par un pointeur.

Imaginons que vous disposiez dans vos formulaires d’un certain nombre de boutons devant être actifs ou inactifs. Chaque bouton est associé à une condition qui peut être VRAI ou FAUX. La condition indique s’il faut désactiver ou activer le bouton. Vous pouvez utiliser un test comme celui-ci chaque fois que vous devez désactiver ou activer le bouton :

 If(Condition) ` Si la condition est VRAIE…
    OBJECT SET ENABLED(MonBouton;True` activer le bouton
 Else ` Dans l’autre cas…
    OBJECT SET ENABLED(MonBouton;False` désactiver le bouton
 End if

Vous pouvez avoir besoin, pour chaque bouton que vous avez créé, d’utiliser un test similaire, dans lequel seul le nom du bouton change. Afin d’être plus efficace, vous pouvez créer un pointeur pour référencer chaque bouton puis utiliser une sous-routine pour le test lui-même.

Vous devez utiliser des pointeurs si vous appelez une sous-routine, car il n’est pas possible de faire référence autrement aux variables des boutons. Par exemple, voici une méthode projet nommée FIXER_BOUTON, qui référence un bouton avec un pointeur :

  ` Méthode projet FIXER_BOUTON
  ` FIXER_BOUTON ( Pointeur ; Booléen )
  ` FIXER_BOUTON ( -> Bouton ; Activé ou Désactivé )
  `
  ` $1 – Pointeur vers un bouton
  ` $2 – Booléen. Si VRAI, active le bouton. Si FAUX, désactive le bouton
 
 If($2` Si la condition est VRAIE…
    OBJECT SET ENABLED($1->;True` activer le bouton
 Else ` Si ce n'est pas le cas…
    OBJECT SET ENABLED($1->;False` désactiver le bouton
 End if

Vous pouvez appeler la méthode projet FIXER_BOUTON de la manière suivante :

  ` ...
 FIXER_BOUTON(->bValider;True)
  ` ...
 FIXER_BOUTON(->bValider;False)
  ` ...
 FIXER_BOUTON(->bValider;([Employés]Nom#"")
  ` ...
 For($vlRadioBouton;1;20)
    $vpRadioBouton:=Get pointer("r"+String($vlRadioBouton))
    FIXER_BOUTON($vpRadioBouton;False)
 End for

Partout où le langage requiert un nom de table, vous pouvez utiliser un pointeur dépointé vers une table.
Pour créer un pointeur vers une table, écrivez une instruction du type :

 TablePtr:=->[touteTable]

Vous pouvez également récupérer un pointeur vers une table à l’aide de la fonction Table. Par exemple :

 TablePtr:=Table(20)

Vous pouvez utiliser le pointeur dépointé dans vos commandes, comme ceci :

 DEFAULT TABLE(TablePtr->)

Partout où le langage requiert un nom de champ, vous pouvez utiliser un pointeur dépointé vers un champ.
Pour créer un pointeur vers un champ, écrivez une ligne d'instruction du type :

 ChampPtr:=->[uneTable]CeChamp

Vous pouvez également récupérer un pointeur vers un champ à l’aide de la fonction Field. Par exemple :

 ChampPtr:=Field(1;2)

Vous pouvez utiliser le pointeur dépointé avec les commandes, comme ceci :

 OBJECT SET FONT(ChampPtr->;"Arial")

L'exemple fourni au début de cette section illustre l'utilisation d'un pointeur vers une variable :

 MaVar:="Bonjour" ` Création de la variable MaVar
 MonPointeur:=->MaVar

Vous pouvez faire pointer des pointeurs vers des variables interprocess, process et, à compter de la version 2004.1 de 4D, vers des variables locales.

Lorsque vous utilisez des pointeurs vers des variables locales ou des variables process, vous devez veiller à ce que la variable pointée soit bien définie au moment de l’utilisation du pointeur. Rappelons que les variables locales sont supprimées à la fin de l’exécution de la méthode qui les a créées et les variables process à la fin du process dans lequel elles ont été créées. L’appel d’un pointeur vers une variable qui n’existe plus provoque une erreur de syntaxe en mode interprété (variable indéfinie) mais peut générer une erreur plus conséquente en mode compilé.

Note sur les variables locales : Les pointeurs vers des variables locales permettent dans de nombreux cas d’économiser des variables process. Les pointeurs vers des variables locales peuvent être utilisés uniquement à l’intérieur d’un même process.
Dans le débogueur, lorsque vous affichez un pointeur vers une variable locale déclarée dans une autre méthode, le nom de la méthode d’origine est indiquée entre parenthèses, derrière le pointeur. Par exemple, si vous écrivez dans Méthode1 :

 $MaVar:="Bonjour"
 Méthode2(->$MaVar)

Dans Méthode2, le débogueur affichera $1 de la façon suivante :

$1 ->$MaVar (Méthode1)

La valeur de $1 sera :

$MaVar(Méthode1)"Bonjour"

Vous pouvez créer un pointeur vers un élément de tableau. Par exemple, les lignes d'instruction suivantes créent un tableau et assignent à une variable appelée ElémPtr un pointeur vers le premier élément :

 ARRAY REAL(unTableau;10` Créer un tableau
 ElémPtr:=->unTableau{1} ` Créer un pointeur vers l’élément de tableau

Vous pouvez alors utiliser le pointeur dépointé pour assigner une valeur à l’élément, comme ceci :

 ElémPtr->:=8

Vous pouvez créer un pointeur vers un tableau. Par exemple, les lignes d'instruction suivantes créent un tableau et assignent à la variable nommée TabPtr un pointeur vers le tableau :

 ARRAY REAL(unTableau;10` Créer un tableau
 TabPtr:=->unTableau ` Créer un pointeur vers le tableau

Il est important de comprendre que ce pointeur pointe vers le tableau, et non vers un élément du tableau. Par exemple, vous pourriez utiliser le pointeur dépointé de la manière suivante :

 SORT ARRAY(TabPtr->;>) ` Tri du tableau

Si vous devez vous référer au quatrième élément du tableau à l’aide du pointeur, vous pouvez écrire :

 TabPtr->{4}:=84

Il est souvent utile de disposer d’un tableau de pointeurs référençant un groupe d’objets homogène.

Un exemple d'utilisation typique d’un tel groupe d’objets est une grille de variables dans un formulaire. Chaque variable dans la grille est numérotée de manière séquentielle, par exemple : Var1, Var2,…, Var10. Vous devez souvent vous référer à ces variables, de manière indirecte — par leur numéro. Si vous créez un tableau de pointeurs et faites pointer les pointeurs vers chaque variable, il est alors facile de référencer les variables. Par exemple, pour créer un tableau et initialiser chaque élément, vous pouvez écrire :

 ARRAY POINTER(tabPointeurs;10` Créer un tableau de 10 pointeurs
 For($i;1;10) ` Boucle une fois par variable
    tabPointeurs{$i}:=Get pointer("Var"+String($i))
  ` Initialiser chaque élément du tableau
 End for

La fonction Get pointer retourne un pointeur vers l'objet passé en paramètre.

Pour référencer une des variables, il suffit d’appeler les éléments du tableau. Par exemple, pour remplir les variables avec les dix prochains jours (en supposant que les variables soient de type Date), vous pourriez écrire :

 For($i;1;10) ` Boucle une fois par variable
    tabPointeurs{$i}->:=Current date+$i  ` Assigner les jours
 End for

Si vous disposez d’un groupe homogène de boutons radio dans un formulaire, vous devrez souvent pouvoir définir rapidement leur état. La solution consistant à référencer chacun d’entre eux par son nom n’est pas très pratique. Imaginons que vous disposiez d'un groupe de cinq boutons radio libellés Bouton1, Bouton2,…, Bouton5.

Dans un groupe de boutons radio, seul l’un d’entre eux est sélectionné. Le numéro du bouton sélectionné peut être stocké dans un champ numérique. Par exemple, si le champ [Préférences]EtatBouton contient 3, alors Bouton3 est sélectionné. Dans la méthode formulaire, vous pouvez utiliser le code suivant pour paramétrer les boutons :

 Case of
    :(Form event=On Load)
  ` ...
       Case of
          :([Préférences]EtatBouton=1)
             Bouton1:=1
          :([Préférences]EtatBouton=2)
             Bouton2:=1
          :([Préférences]EtatBouton=3)
             Bouton3:=1
          :([Préférences]EtatBouton=4)
             Bouton4:=1
          :([Préférences]EtatBouton=5)
             Bouton5:=1
       End case
  ` ...
 End case

Un cas particulier doit être testé pour chaque bouton radio. La méthode peut être très longue si le formulaire contient de nombreux boutons radio. Heureusement, vous pouvez utiliser des pointeurs pour résoudre ce problème.
La fonction Get pointer vous permet de retourner un pointeur vers un bouton radio. L’exemple suivant utilise un pointeur de ce type pour référencer le bouton radio devant être sélectionné. Voici la méthode optimisée :

 Case of
    :(Form event=On Load)
  ` ...
       $vpRadio:=Get pointer("Bouton"+String([Préférences]EtatBouton))
       $vpRadio->:=1
  ` ...
 End case

Le numéro du bouton radio traité doit être stocké dans le champ [Préférences]EtatBouton. Cette opération peut être effectuée dans la méthode formulaire, pour l'événement formulaire Sur clic :

 [Préférences]EtatBouton:=Bouton1+(Bouton2*2)+(Bouton3*3)+(Bouton4*4)+(Bouton5*5)

Vous pouvez passer un pointeur en tant que paramètre d’une méthode. A l’intérieur de la méthode, vous pouvez modifier l’objet référencé par le pointeur. Par exemple, la méthode suivante, RECOIT DEUX, reçoit deux paramètres qui sont des pointeurs. Elle passe l’objet référencé par le premier paramètre en caractères majuscules, et l’objet référencé par le second paramètre en caractères minuscules :

  ` Méthode projet RECOIT DEUX
  ` $1 – Pointeur vers un champ ou une variable de type Chaîne. Passe la chaîne en majuscules.
  ` $2 – Pointeur vers un champ ou une variable de type Chaîne. Passe la chaîne en minuscules.
 $1->:=Uppercase($1->)
 $2->:=Lowercase($2->)

L'instruction suivante emploie la méthode RECOIT DEUX pour passer un champ en caractères majuscules et une variable en caractères minuscules :

 RECOIT DEUX(->[MaTable]MonChamp;->MaVar)

Si le champ, [MaTable]MonChamp, contenait la chaîne "dupont", celle-ci deviendrait "DUPONT". Si la variable MaVar contenait la chaîne "BONJOUR", celle-ci deviendrait "bonjour".

Dans la méthode RECOIT DEUX (et, en fait, à chaque fois que vous utilisez des pointeurs), il est important que les types de données des objets référencés soient corrects. Dans l’exemple précédent, les pointeurs doivent pointer vers des objets contenant une chaîne ou un texte.

Si vous aimez compliquer les choses à l'extrême (bien que cela ne soit pas nécessaire dans 4D), vous pouvez utiliser des pointeurs pour référencer d'autres pointeurs. Examinons l’exemple suivant :

 MaVar:="Bonjour"
 PointeurUn:=->MaVar
 PointeurDeux:=->PointeurUn
 (PointeurDeux->)->:="Au revoir"
 ALERT((PointeurDeux->)->)

Cet exemple affiche une boîte de dialogue d’alerte contenant “Au revoir”.

Voici la description de chaque ligne de l’exemple :

  • MaVar := "Bonjour"
    --> Cette ligne place simplement la chaîne "Bonjour" dans la variable MaVar.
  • PointeurUn := ->MaVar
    --> PointeurUn contient désormais un pointeur vers MaVar.
  • PointeurDeux :=->PointeurUn
    --> PointeurDeux (une nouvelle variable) contient un pointeur vers PointeurUn, qui, elle, pointe vers MaVar.
  • (PointeurDeux->)-> := "Au revoir"
    --> PointeurDeux-> référence le contenu de PointeurUn, qui elle-même référence MaVar. Par conséquent, (PointeurDeux->)-> référence le contenu de MaVar. Donc, dans ce cas, la valeur "Au revoir" est assignée à la MaVar.
  • ALERTE ((PointeurDeux->)->)
    --> C'est ici la même chose que précédemment : PointeurDeux-> référence le contenu de PointeurUn, qui elle-même référence MaVar. Par conséquent, (PointeurDeux->)-> référence le contenu de MaVar. Donc, dans ce cas, la boîte de dialogue d'alerte affiche le contenu de maVar.

La ligne suivante place la valeur "Bonjour" dans MaVar :

 (PointeurDeux->)->:="Bonjour"

La ligne suivante récupère "Bonjour" à partir de MaVar et la place dans NouvelleVar :

 NouvelleVar:=(PointeurDeux->)->

Important : Vous devez utiliser des parenthèses lors des déréférencements multiples.



Voir aussi  

Conditions et boucles
Constantes
Identifiants
Méthodes
Opérateurs
Présentation des tableaux
Tableaux et pointeurs
Types de données
Variables

 
PROPRIÉTÉS 

Produit : 4D
Thème : Présentation du langage

 
HISTORIQUE 

 
UTILISATION DE L'ARTICLE

4D - Langage ( 4D v16)
4D - Langage ( 4D v16.1)
4D - Langage ( 4D v16.2)
4D - Langage ( 4D v16.3)