Punteros

4D - Documentation   Français   English   German   Español   English   4D v11 SQL, Comandos por temas   4D v11 SQL, Lista alfabética de comandos   4D v11 SQL, Constantes por temas   Regresar   Anterior   Siguiente

versión 2004.1 (Modificado)


Los punteros ofrecen una forma avanzada (en programación) para referirse a datos.

Cuando utiliza el lenguaje, accede a diferentes objetos —en particular tablas, campos, variables, y arrays—simplemente utilizando sus nombres. Sin embargo, con frecuencia es útil hacer referencia a estos elementos y acceder a ellos sin conocer sus nombres. Esto es lo que los punteros le permiten hacer.

El concepto detrás de los punteros no es desconocido en la vida diaria. Con frecuencia usted se refiere a algo sin saber su identidad exacta. Por ejemplo, podría decirle a un amigo, "Vamos a pasear en tu coche" en lugar de "Vamos a pasear en el coche de matrícula 123ABD." En este caso, está haciendo referencia al coche de matrícula 123ABD utilizando la frase "tu coche." La frase "coche de matrícula 123ABD" es como el nombre de un objeto, y utilizar la frase "tu coche" es como utilizar un puntero para referenciar el objeto.

La capacidad de referirse a algo sin conocer su identidad exacta es muy útil. De hecho, su amigo compra un coche nuevo, la frase "tu coche" seguiría siendo correcta—seguiría siendo un coche y usted podría ir de paseo en él. Los punteros funcionan de la misma manera. Por ejemplo, un puntero podría en un momento referirse un campo numérico llamado Edad, y más tarde referirse a una variable numérica llamada Edad antigua. En ambos casos, el puntero hace referencia a un dato numérico que puede ser utilizado en un cálculo.

Puede utilizar punteros para referenciar tablas, campos, variables, arrays, y elementos de Array. La siguiente tabla la da un ejemplo de cada tipo de dato:

ObjetoReferenciamientoUtilizaciónAsignación
TablavpTabla:=->[Tabla]DEFAULT TABLE(vpTabla->)n/a
CampovpCampo:=->[Tabla]CampoALERT(vpCampo->)vpCampo->:="Juan"
VariablevpVar:=->VariableALERT(vpVar->) vpVar->:="Juan"
ArrayvpArr:=->ArraySORT ARRAY(vpArr->;>) COPY ARRAY(Arr;vpArr->)
Elemento array vpElem:=->Array{1}ALERT (vpElem->)vpElem->:="Juan"

Utilizar punteros: un ejemplo


Es más fácil explicar el uso de punteros a través de un ejemplo. Este ejemplo muestra cómo acceder a una variable a través de un puntero. Comenzamos creando una variable:

   MiVar:="Hola"

MiVar es ahora una variable que contiene la cadena "Hola". Ahora podemos crear un puntero a MiVar:

   MiPuntero:=->MiVar

El símbolo -> significa "puntero a." Este símbolo está formado por un guión seguido por un signo "mayor que". En este caso, crea un puntero que referencia o "apunta a" MiVar. Este puntero se asigna a MiPuntero con el operador de asignación.

MiPuntero es ahora una variable que contiene un puntero a MiVar. MiPuntero no contiene "Hola", el valor de MiVar, pero puede utilizar MiPuntero para obtener este valor. La siguiente expresión devuelve el valor en MiVar:

   MiPuntero->

En este caso, devuelve la cadena "Hola". El símbolo -> , cuando está ubicado detrás de un puntero, hace referencia al objeto al que se apunta. Esto se llama desreferenciación.

Es importante entender que puede utilizar un puntero seguido por el símbolo -> en todas las partes donde pueda utilizar el objeto al que el puntero apunta. Esto significa que puede utilizar la expresión

MiPuntero
-> en todas las partes donde podría utilizar la variable original MiVar.

Por ejemplo, la siguiente instrucción muestra una caja de diálogo de alerta con la palabra Hola:

   ALERT(MiPuntero->)

Igualmente puede utilizar MiPuntero para cambiar los datos en MiVar. Por ejemplo, la siguiente instrucción guarda la cadena "Hasta luego" en la variable MiVar:

   MiPuntero->:="Hasta luego"

Si examina los dos usos de la expresión

MiPuntero
->, verá que actúa como si hubiera utilizado MiVar en su lugar. En resumen, los siguientes dos tipos de líneas realizan la misma acción—ambos muestran una caja de alerta que contiene el valor actual en la variable MiVar:

   ALERT(MiPuntero->)
   ALERT(MVar)

Las dos líneas siguientes realizan la misma acción— ambas asignan la cadena "Hasta luego" a MiVar:


   MiPuntero->:="Hasta luego"
   MiVar:="Hasta luego"

Utilizar punteros a botones


Esta sección describe cómo utilizar un puntero para referenciar un botón. Un botón es (desde el punto de vista del lenguaje) nada más que una variable. Aunque los ejemplos en esta sección utilizan los punteros para referenciar botones, los conceptos que se presentan aplican al uso de todos los tipos de objetos que pueden ser referenciados por un puntero.

Digamos que tiene un número de botones en sus formularios que necesitan ser activados o desactivados. Cada botón tiene una condición asociada que es TRUE o FALSE. La condición indica si hay que desactivar o activar el botón. Puede utilizar una prueba como esta cada vez que necesite activar o desactivar el botón:

   If (Condición) ` Si la condición es TRUE…
      ENABLE BUTTON (MiBoton) ` activar el botón
   Else ` De lo contrario…
      DISABLE BUTTON (MiBoton) ` desactivar el botón
   End if

Puede necesitar utilizar una prueba similar para cada botón que creó, en la cual sólo cambia el nombre del botón. Para ser más eficientes, puede utilizar un puntero para hacer referencia a cada botón y luego utilizar una subrutina para la prueba.

Debe utilizar punteros si utiliza una subrutina, porque no es posible hacer referencia a las variables de los botones de otra manera. Por ejemplo, he aquí un método de proyecto llamado DEFINIR_BOTON, el cual hace referencia a un botón con un puntero:

      ` Método de proyecto DEFINIR_BOTON
      ` DEFINIR_BOTON ( Puntero ; Booleano )
      ` DEFINIR_BOTON ( -> Botón ; Activado o Desactivado )
      `
      ` $1 – Puntero a un botón
      ` $2 – Booleano. Si TRUE, activa el botón. Si FALSE, desactiva el botón

   If ($2) ` Si la condición es TRUE…
      ENABLE BUTTON($1->) ` activar el botón
   Else ` De lo contrario…
      DISABLE BUTTON($1->) ` desactivar el botón
   End if

Puede llamar al método de proyecto DEFINIR_BOTON de esta manera:

      ` ...
   DEFINIR_BOTON (->bValidar;True)
      ` ...
   DEFINIR_BOTON (->bValidar;False)
      ` ...
   DEFINIR_BOTON (->bValidar;([Empleados]Apellido#"")
      ` ...
   For ($vlRadioBoton;1;20)
      $vpRadioBoton:=Get pointer("r"+String($vlRadioBoton))
      DEFINIR_BOTON ($vpRadioBoton;False)
   End for

Utilizar punteros a tablas


En todas las partes donde el lenguaje requiera una tabla, puede utilizar un puntero desreferenciado hacia la tabla.

Para crear un puntero hacia una tabla, escriba una instrucción como esta:

   TablaPtr:=->[cualquier tabla]

Igualmente puede obtener un puntero a una tabla utilizando el comando Table. Por ejemplo:

   TablaPtr:=Table(20)

Puede utilizar el puntero desreferenciado en comandos, de esta forma:

   DEFAULT TABLE(TablaPtr->)

Utilizar punteros a los campos


En todas las partes donde el lenguaje requiera campo, puede utilizar un puntero desrefenciado para referenciar el campo. Puede crear un puntero a un campo utilizando una línea como esta:

   CampoPtr:=->[unaTabla]EsteCampo

Igualmente puede obtener un puntero a un campo utilizando el comando Field. Por ejemplo:

   CampoPtr:=Field(1; 2)

Puede utilizar el puntero desreferenciado en comandos, como este:

   FONT(CampoPtr->; "Arial")

Utilizar punteros a variables


El ejemplo al comienzo de esta sección ilustra la utilización de un puntero a una variable:

   MiVar:="Hola"
   MiPuntero:=->MiVar

Puede utilizar punteros a variables interprocesos, de proceso y, a partir de la versión 2004.1, a variables locales.

Cuando utilice punteros a variables de proceso o a variables locales, debe asegurarse que la variable a la que se apunta esté definida cuando se utilice el puntero. Recuerde que las variables locales se borran cuando el método que las creó completa su ejecución y las variables proceso se borran al final del proceso que las creó. Cuando un puntero llama una variable que no existe, se produce un error de sintaxis en modo interpretado (variable no definida) pero puede generar un error más serio en modo compilado.

Nota sobre variables locales: los punteros a variables locales le permiten ahorrar variables de proceso en muchos casos. Los punteros a variables locales sólo pueden utilizarse dentro del mismo proceso.

En el depurador, cuando visualiza un puntero a una variable local que ha sido declarada en otro método, el nombre del método original está entre paréntesis, después del puntero. Por ejemplo, si escribe en Metodo1:

   $MiVar:="Buenos días"
   Metodo2(->$MiVar)

En Metodo2, el depurador mostrará $1 de esta manera:

$1 ->$MiVar (Metodo1)

El valor de $1 será:

$MiVar (Metodo1) "Buenos días"

Utilizar punteros a elementos Array


Puede crear un puntero a un elemento Array. Por ejemplo, las líneas siguientes crean un Array y asignan a una variable llamada ElemPtr un puntero al primer elemento Array :

   ARRAY REAL(unArray; 10) ` Crea un array
   ElemPtr:=->unArray{1} ` Crea un puntero al elemento de array

Puede utilizar el puntero desreferenciado para asignar un valor al elemento, como este:

   ElemPtr->:=8

Utilizar punteros a arrays


Puede crear un puntero a un Array. Por ejemplo, las líneas siguientes crean un Array y asignan a una variable llamada ArrPtr un puntero al Array:

   ARRAY REAL(unArray; 10) ` Crea un array
   ArrPtr := ->unArray ` Crea un puntero al array

Es importante entender que el puntero apunta al Array; no a un elemento del Array. Por ejemplo, puede utilizar el puntero desreferenciado de esta manera:

   SORT ARRAY(ArrPtr->; >) ` Ordenar el array

Si necesita hacer referencia al cuarto elemento en el Array utilizando el puntero, puede hacer esto:

   ArrPtr->{4} := 84

Utilizar un array de punteros


Con frecuencia es útil tener un Array de punteros que referencian a un grupo de objetos relacionados.

Un ejemplo de utilización de un grupo de objetos es una rejilla de variables en un formulario. Cada variable en la rejilla está numerada secuencialmente, por ejemplo: Var1,Var2,…, Var10. Con frecuencia usted necesita referenciar estas variables indirectamente con un número. Si crea un Array de punteros e inicializa los punteros hacia cada variable, entonces puede referenciar fácilmente las variables. Por ejemplo, para crear un Array e inicializar cada elemento, puede utilizar las siguientes líneas:

   ARRAY POINTER(apPunteros; 10)   ` Crear un array de 10 punteros
   For ($i; 1; 10)   ` Bucle una vez por variable
      apPunteros{$i}:=Get pointer("Var"+String($i))   ` Inicializar el elemento array
   End for

La función Get pointer devuelve un puntero al objeto llamado.

Para referenciar una de las variables, utilice los elementos Array. Por ejemplo, para llenar las variables con las siguientes diez fechas (asumiendo que las variables son tipo Fecha), puede utilizar las siguientes líneas:

   For ($i; 1; 10) ` Bucle una vez por cada variable
      apPunteros{$i}->:=Current date+$i ` Asignar las fechas
   End for

Definir un botón utilizando un puntero


Si tiene un grupo homogéneo de botones radio en un formulario, con frecuencia necesita definirlos rápidamente. No es eficiente referenciar directamente cada uno de ellos por su nombre. Imagine que tiene un grupo de botones radio llamados Boton1, Boton2,…, Boton5.

En un grupo de botones radio, sólo se selecciona un botón. El número de botón seleccionado puede guardarse en un campo numérico. Por ejemplo, si el campo llamado [Preferencias]Estado contiene 3, entonces el Boton3 se selecciona. En su método de formulario, puede utilizar el siguiente código para definir el botón:

   Case of
      :(Form event=On Load)
            ` ...
         Case of
            : ([Preferencias]Estado = 1)
               Boton1:=1
            : ([Preferencias]Estado = 2)
               Boton2:=1
            : ([Preferencias]Estado = 3)
               Boton3:=1
            : ([Preferencias]Estado = 4)
               Boton4:=1
            : ([Preferencias]Estado = 5)
               Boton5:=1
         End case
            ` ...
   End case

Un caso particular debe ser probado para cada botón radio. El método puede ser muy largo si tiene muchos botones radio en su formulario. Afortunadamente, puede utilizar punteros para solucionar este problema. Puede utilizar el comando Get pointer para devolver un puntero a un botón radio. El siguiente ejemplo utiliza un apuntador de este tipo para referenciar al botón radio seleccionado. Este es el código mejorado:

   Case of
      :(Form event=On Load)
            ` ...
         $vpRadio:=Get pointer("Boton"+String([Preferencias]Estado))
         $vpRadio->:=1
            ` ...
   End case

El número del botón radio tratado debe ser almacenado en el campo [Preferencias]

Estado
. Puede hacerlo en el método de formulario para el evento On Clicked:

[Preferencias]Estado:=Boton1+(Boton2*2)+(Boton3*3)+(Boton4*4)+(Boton5*5)

Pasar punteros a métodos


Puede pasar un puntero como un parámetro a un método. Dentro del método, puede modificar el objeto referenciado por el puntero. Por ejemplo, el siguiente método, TOME DOS, toma dos parámetros que son punteros. Esto cambia el objeto referenciado por el primer parámetro a caracteres en mayúsculas, y el objeto referenciado por el segundo parámetro a caracteres en minúsculas. Este es el método:

      ` Método de proyecto TOME DOS
      ` $1 – Puntero a un campo o variable tipo cadena. Pasa la cadena a mayúsculas.
      ` $2 – Puntero a un campo o variable tipo cadena. Pasa la cadena a minúsculas.
   $1->:=Uppercase($1->)
   $2->:=Lowercase($2->)

La siguiente instrucción utiliza el método TOME DOS para cambiar un campo a caracteres en mayúsculas y cambiar una variable a caracteres en minúsculas:

   TOME DOS (->[Mi Tabla]Mi Campo; ->MiVar)

Si el campo [Mi Tabla]Mi Campo contiene la cadena "gómez", cambiaría a la cadena "GÓMEZ". Si la variable MiVar contiene la cadena "HOLA", cambiaría a la cadena "hola".

En el método TOME DOS, y de hecho, cada vez que utiliza punteros, es importante que los tipos de datos de los objetos referenciados sea correcto. En el ejemplo anterior, los punteros deben apuntar a un objeto que contenga una cadena o un texto.

Punteros a punteros


Si en realidad le gusta complicar la cosas, puede utilizar punteros para referenciar otros punteros. Considere este ejemplo:

   MiVar := "Hola"
   PunteroUno := ->MiVar
   PunteroDos := ->PunteroUno
   (PunteroDos->)-> := "Hasta luego"
   ALERT((Puntero Dos->)->)

Este ejemplo muestra una caja de diálogo de alerta con la palabra "Hasta luego".

Esta es una explicación de cada línea del ejemplo:

MiVar:="Hola"

Esta línea asigna la cadena "Hola" en la variable MiVar.

PunteroUno:=->MiVar

PunteroUno ahora contiene un puntero a MiVar.

PunteroDos:=->PunteroUno

PunteroDos (una nueva variable) contiene un puntero a PunteroUno, el que apunta a MiVar.

(PunteroDos->)->:="Hasta luego"

PunteroDos-> referencia el contenido de PunteroUno, el cual referencia a MiVar.

Por lo tanto (PunteroDos->)-> referencia el contenido de MiVar. De manera que en este caso, MiVar se asigna a "Hasta luego".

ALERT ((PunteroDos->)->)

El mismo procedimiento: PunteroDos-> referencia el contenido de PunteroUno, que a su vez referencia a MiVar. Por lo tanto (PunteroDos->)-> referencia el contenido de MiVar. De esta manera, la caja de diálogo de alerta muestra el contenido de MiVar.

La siguiente línea coloca "Hola" en MiVar:

   (PunteroDos->)->:="Hola"

La línea siguiente obtiene "Hola" de MiVar y la asigna a NuevaVar:

   NuevaVar:=(PunteroDos->)->

Importante: el desreferenciamiento múltiple requiere paréntesis.

Ver también

Arrays, Arrays y punteros, Condiciones y bucles, Constantes, Convenciones, Métodos, Operadores, Tipos de datos, Variables.


4D - Documentation   Français   English   German   Español   English   4D v11 SQL, Comandos por temas   4D v11 SQL, Lista alfabética de comandos   4D v11 SQL, Constantes por temas   Regresar   Anterior   Siguiente