4D v16.3

Ponteiros

Página Inicial

 
4D v16.3
Ponteiros

Ponteiros  


 

Ponteiros fornecem uma maneira avançada (em programação) para se referir a dados.

Quando você usa a linguagem, você acessa vários objetos, em particular, tabelas, campos, variáveis e arrays, simplesmente usando seus nomes. No entanto, é frequentemente útil se referir a esses elementos e acessá-los sem saber seus nomes. Isto é o que os ponteiros permitem que você faça.

O conceito por trás ponteiros não é incomum na vida cotidiana. Você freqüentemente se refere a algo sem saber sua identidade exata. Por exemplo, você poderia dizer a um amigo: "Vamos sair para um passeio no seu carro" em vez de "Vamos dar um passeio no carro com a placa ABC1234." Nesse caso, você está referenciando o carro com placa ABC1234 usando a frase "seu carro". A frase "carro com placa ABC1234" é como o nome de um objeto, e usando a frase "seu carro" é como usar um ponteiro para o objeto de referência.

Ser capaz de se referir a algo sem conhecer sua identidade exata é muito útil. Na verdade, seu amigo poderia comprar um carro novo, e a frase "seu carro" ainda seria suficiente, ainda seria um carro e você ainda poderia fazer um passeio nele. Os ponteiros funcionam da mesma maneira. Por exemplo, um ponteiro pode ao mesmo tempo se referir a um campo numérico chamado Idade, e mais tarde se referir a uma variável numérica chamada Terceira Idade. Em ambos os casos, o ponteiro referencia dados numéricos que podem ser usados em um cálculo.

Você pode usar ponteiros para tabelas de referência, campos, variáveis, matrizes e elementos de array. A tabela a seguir dá um exemplo de cada tipo de dado:

ObjetoReferenciamientoUtilizaçãoAtribuição
TabelavpTabela:=->[Tabela]DEFAULT TABLE(vpTabela->)n/a
CampovpCampo:=->[Tabela]CampoALERT(vpCampo->)vpCampo->:="João"
VariávelvpVar:=->VariávelALERT(vpVar->) vpVar->:="João"
ArrayvpArr:=->ArraySORT ARRAY(vpArr->;>) COPY ARRAY(Arr;vpArr->)
Elemento array vpElem:=->Array{1}ALERT (vpElem->)vpElem->:="João"

É mais fácil explicar o uso de ponteiros com um exemplo. Este exemplo mostra como acessar uma variável através de um ponteiro. Começamos criando uma variável:

 MinhaVar:="Olá"

MinhaVar agora é uma variável que contem a string "Olá". Agora podemos criar um ponteiro para MinhaVar:

 MeuPonteiro:=->MinhaVar

O símbolo -> significa "obter um ponteiro para." Esse símbolo é formado por um hífen seguido de um sinal de "maior que". Neste caso, torna-se o ponteiro que referencia ou "aponta para" MinhaVar. Esse ponteiro é atribuído a MeuPonteiro com o operador de atribuição.

MeuPonteiro agora é uma variável que contém um ponteiro para MinhaVar. MeuPonteiro não contém "Olá", que é o valor em MinhaVar, mas você pode usar MeuPonteiro para obter este valor. A seguinte expressão retorna o valor em MinhaVar:

 MeuPonteiro->

Neste caso, ele retorna a string "Olá". O símbolo ->, quando seguido de um ponteiro, faz referência ao objeto apontado. Isso é chamado dereferenciamento.

É importante compreender que você pode usar um ponteiro seguido do símbolo -> em  qualquer lugar que você pudesse ter usado o objeto que o ponteiro aponta. Isso significa que você pode usar a expressão MeuPonteiro-> em qualquer lugar que você poderia usar a variável original MinhaVar.

Por exemplo, a seguinte linha exibe uma caixa de alerta com a palavra Olá nela:

 ALERT(MeuPonteiro->)

Você também pode usar MeuPonteiro para alterar os dados em MinhaVar. Por exemplo, as instrução seguinte armazena "Tchau" na variável MinhaVar:

 MeuPonteiro->="Tchau"

Se você examinar os dois usos da expressão MeuPonteiro-> você verá que ela age como se você tivesse usado MinhaVar. Em resumo, as duas linhas seguintes executam a mesma ação - as duas exibem uma caixa de alerta contendo o valor atual da variável MinhaVar:

 ALERT(MeuPonteiro->)
 ALERT(MinhaVar)

As duas linhas seguintes executam a mesma ação, atribuem a string "Tchau" a MinhaVar:

 MeuPonteiro->:="Tchau"
 MinhaVar:="Tchau"

Esta seção descreve como usar um ponteiro para um botão de referência. Um botão é (do ponto de vista da linguagem), nada mais do que uma variável. Embora os exemplos nesta seção usem ponteiros para os botões de referência, os conceitos aqui apresentados são aplicáveis à utilização de todos os tipos de objetos que pode ser referenciados por um ponteiro.

Digamos que você tenha uma quantidade de botões nos formulários que precisam ser ativados ou desativados. Cada botão tem uma condição associada a ele, VERDADEIRO ou FALSO. A condição diz para desativar ou ativar o botão. Você pode usar um teste como este cada vez que você precise para ativar ou desativar o botão:

 If(condição) `Se a condição é VERDADEIRA…
    OBJECT SET ENABLED(MeuBotao;True` ativa o botão
 Else ` Caso contrário…
    OBJECT SET ENABLED(Meubotao;False` desativa o botão
 End if

Você precisaria usar um teste semelhante para cada botão que você definiu, apenas mudando o nome do botão. Para ser mais eficiente, você pode usar um ponteiro de referência para cada botão e então usar uma sub-rotina para o teste em si.

Você deve usar ponteiros se você usar uma sub-rotina, porque você não pode se referir a variáveis do botão de outra forma. Por exemplo, abaixo é um método de projeto chamado SET BUTTON, que faz referência a um botão com um ponteiro:

  ` Método de projeto DEFINIR BOTÃO
  ` DEFINIR BOTÃO ( Ponteiro; Booleano )
  ` DEFINIR BOTÃO ( -> Botão ; Ativar ou Desativar )
  `
  ` $1 – Ponteiro a um botão
  ` $2 – Booleano. Se TRUE, ativar o botão. Se FALSE, desativar o botão
 
 If($ 2`Se a condição é TRUE…
    OBJECT SET ENABLED($1->;True` ativar o botão
 Else ` Caso contrário…
    OBJECT SET ENABLED($1->;False` desativar o botão
 End if

Você pode chamar o método de projeto SET BUTTON assim:

  ` ...
 SET BUTTON(->bValidate;True)
  ` ...
 SET BUTTON(->bValidate;False)
  ` ...
 SET BUTTON(->bValidate;([Empregado]Sobrenome#"")
  ` ...
 For($vlRadioButton;1;20)
    $vpRadioButton:=Get pointer("r"+String($vlRadioButton))
    SET BUTTON($vpRadioButton;False)
 End for

Em qualquer lugar que a linguagem espera ver uma tabela, você pode usar um ponteiro para a tabela.
Você cria um ponteiro para uma tabela usando um código como este:

 TabelaPtr:=->[qualquer tabela]

Você também pode obter um ponteiro para uma tabela usando o comando Table. Por exemplo:

 TabelaPtr:=Table(20)

Você pode usar o ponteiro em comandos, como este:

 DEFAULT TABLE(TabelaPtr->)

Em qualquer lugar que a linguagem espere ver um campo, você pode usar um ponteiro para fazer referência ao campo. Você cria um ponteiro para um campo usando uma linha como esta:

 CampoPtr:=->[umaTabela]EsteCampo

Você também pode obter um ponteiro para um campo usando o comando Field. Por exemplo:

 CampoPtr:=Field(1;2)

Você pode usar o ponteiro em comandos, como este:

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

O exemplo no início desta seção ilustra o uso de um ponteiro para uma variável:

 MinhaVar:="Olá"
 MeuPonteiro:=->MinhaVar

Você pode usar ponteiros para variáveis interprocesso, processo e, a partir da versão 2004.1, para variáveis locais.

Quando você usa ponteiros para variáveis processo ou locais, você deve ter certeza que a variável apontada já está definida quando o ponteiro for usado. Tenha em mente que as variáveis locais são apagadas quando o método que a criou já completou a sua execução e as variáveis do processo são eliminadas no final do processo que as criou. Quando um ponteiro chama uma variável que não existe mais, isso gera um erro de sintaxe no modo interpretado (variável não definida), mas pode gerar um erro mais grave no modo compilado.

Nota sobre as variáveis locais: Ponteiros para as variáveis locais permite que você salve as variáveis do processo, em muitos casos. Ponteiros para as variáveis locais só podem ser utilizados dentro do mesmo processo.

No depurador, quando você exibir um ponteiro para uma variável local que tenha sido declarada em outro método, o nome do método original está indicado entre parênteses, após o ponteiro. Por exemplo, se você escrever em Metodo1:

 $MinhaVar="Olá Mundo!"
 Metodo2(->$MinhaVar)

Em Metodo2, o depurador irá exibir $1 desta maneira:
$1 ->$MinhaVar (Metodo1)

O valor de $1 será:
$MinhaVar (Metodo1) "Olá Mundo"

Você pode criar um ponteiro para um elemento do array. Por exemplo, as seguintes linhas criam uma matriz e atribuem um ponteiro para o primeiro elemento de uma variável chamada ElemPtr:

 ARRAY REAL(umArray;10) ` Cria um array
 ElemPtr:=->umArray{1} `Cria um ponteiro para o elemento do array

Você pode usar o ponteiro para atribuir um valor ao elemento, assim:

 ElemPtr->:=8

Você pode criar um ponteiro para um array. Por exemplo, as seguintes linhas criam um array e atribuem um ponteiro para o array para uma variável chamada ArrPtr:

 ARRAY REAL(umArray;10) ` Cria um array
 ArrPtr:=->umArray `Cria um ponteiro para o array

É importante compreender que o ponteiro aponta para o array, que não aponta para um elemento do array. Por exemplo, você pode usar o ponteiro das linhas anteriores, como este:

 SORT ARRAY(ArrPtr->;>) `Ordena o array

Se você precisa se referir ao quarto elemento na matriz, usando o ponteiro, você pode fazer isso:

 ArrPtr->{4}:=84

Muitas vezes, é útil ter um array de ponteiros que fazem referência a um grupo de objetos relacionados.

Um exemplo de um grupo de objetos é uma grade de variáveis em um formulário. Cada variável na grade é numerada sequencialmente, por exemplo: Var1,Var2,…, Var10. Você muitas vezes vai precisar de referenciar essas variáveis indiretamente com um número. Se você criar um array de ponteiros, e inicializar os ponteiros para apontar para cada variável, você pode fazer referência, então, facilmente às variáveis. Por exemplo, para criar uma matriz e inicializar cada elemento, você pode usar as seguintes linhas:

 ARRAY POINTER(apPointers;10) `Cria um array para armazenar 10 ponteiros
 For($i;1;10) `Loop para cada variável, uma vez
    apPointers{$i}:=Get pointer("Var"+String($i)) `Inicializa o array
 End for

A função Get pointer retorna um ponteiro ponteiro para o objeto chamado.

Para fazer referência a qualquer das variáveis, você usa os elementos do array. Por exemplo, para preencher as variáveis com as datas dos próximos dez dias (assumindo que elas são variáveis do tipo data), você pode usar as seguintes linhas:

 For($i;1;10) ` Loop para cada variável, uma vez
    apPointers{$i}->:=Current date+$i  `Atribuir as datas
 End for

Se você tem um grupo de botões de rádio relacionados em um formulário, muitas vezes você precisa colocá-los rapidamente. É ineficiente fazer referência a cada um deles pelo nome. Digamos que você tem um grupo de botões de rádio chamados Botão1, Botão2,…, Botão5.

Em um grupo de botões de rádio, apenas um botão de rádio está ligado. O número do botão que está ligado pode ser armazenado em um campo numérico. Por exemplo, se o campo chamado [Preferencias]Estado contém 3, então Botão3 é selecionado. No seu método de formulário, você poderia usar o seguinte código para definir o botão:

 Case of
    :(Form event=On Load)
  ` ...
       Case of
          :([Preferencias]Estado=1)
             Botão1:=1
          :([Preferencias]Estado=2)
             Botão2:=1
          :([Preferencias]Estado=3)
             Botão3:=1
          :([Preferencias]Estado=4)
             Botão4:=1
          :([Preferencias]Estado=5)
             Botão5:=1
       End case
  ` ...
 End case

Um caso distinto deve ser testado para cada botão de rádio. Este poderia ser um método muito longo se você tiver muitos botões no formulário. Felizmente, você pode usar ponteiros para resolver este problema. Você pode usar o comando Get pointer para retornar um ponteiro para um botão de rádio. O exemplo a seguir usa como referência um ponteiro para o botão que deve ser definido. Aqui está o código melhorado:

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

O número do botão de rádio de referência deve ser armazenado no campo chamado [Preferencias]Estado. Você pode fazer isso no método de formulário para o evento On Clicked:

 [Preferencias]Estado:=Botão1+(Botão2*2)+(Botão3*3)+(Botão4*4)+(Botão5*5)

Você pode passar um ponteiro como um parâmetro para um método. Dentro do método, você pode modificar o objeto referenciado pelo ponteiro. Por exemplo, o método a seguir, TAKE TWO, tem dois parâmetros que são ponteiros. Ele muda o objeto referenciado pelo primeiro parâmetro para caracteres maiúsculos, e o objeto referenciado pelo segundo parâmetro para caracteres minúsculos. Aqui está o método:

  ` Método de projeto TAKE TWO
  ` $1 – Ponteiro para um campo string ou variável. Alterar para maiúsculas.
  ` $2 – Ponteiro para um campo string ou variável. Alterar para minúsculas.
 $1->:=Uppercase($1->)
 $2->:=Lowercase($2->)

A linha a seguir usa o método TAKE TWO para alterar um campo para caracteres maiúsculos e mudar uma variável para caracteres minúsculos:

 TAKE TWO(->[Minha Tabela]Meu Campo;->MinhaVar)

Se o campo [Minha Tabela] Meu Campo continha a string "jones", ele teria de ser alterado para a string de "JONES". Se a variável MinhaVar continha a string "OLÁ", seria alterada para "olá"

No método TAKE TWO, e de fato, sempre que você usar ponteiros, é importante que o tipo de dados do objeto a ser referenciado seja correto. No exemplo anterior, os ponteiros devem apontar para um objeto que contém uma seqüência de caracteres ou texto.

Se você realmente gosta de complicar as coisas, você pode usar ponteiros para fazer referência a outros ponteiros. Veja este exemplo:

 MinhaVar:="Olá"
 PonteiroUm:=->MinhaVar
 PonteiroDois:=->PonteiroUm
 (PonteiroDois->)->:="Até logo"
 ALERT((Ponteiro Dois->)->)

Exibe uma caixa de alerta com a palavra "Tchau" nela.

Aqui está uma explicação de cada linha do exemplo:

  • MinhaVar:="Olá"
    --> Esta linha coloca a string "Olá" na variável MinhaVar.
  • PonteiroUm:=->MinhaVar
    --> PonteiroUm agora contém um ponteiro a MinhaVar.
  • PonteroDois:=->PonteiroUm
    --> PonteiroDois (uma nova variável) contém um ponteiro a PonteiroUm, o que apunta a MinhaVar.
  • (PonteiroDois->)->:="Tchau"
    --> PonteiroDois-> referencia o conteúdo de PonteiroUm, o qual referencia a MinhaVar.

Portanto (PonteiroDois->)-> referencia o conteúdo de MinhaVar. De modo que neste caso, MinhaVar é atribuída a "Tchau".

  • ALERT ((PonteiroDois->)->)
    --> O mesmo procedimento: PonteiroDois-> referencia o conteúdo de PonteiroUm, que por sua vez referencia a MinhaVar. Portanto (PonteiroDois->)-> referencia o conteúdo de MinhaVar. Desta maneira, a caixa de diálogo de alerta mostra o conteúdo de MinhaVar.

A linha seguinte coloca "Olá" em MinhaVar:

 (PonteiroDois->)->:="Olá"

A linha seguinte obtém "ola" de MinhaVar e atribui a NovaVar:

 NovaVar:=(PonteiroDois->)->

Importante: o desreferenciamiento múltiplo requer parêntesis.



Ver também 

Arrays
Arrays e ponteiros
Constantes
Controle de fluxo
Convenções
Métodos
Operadores
Tipos de dados
Variáveis

 
PROPRIEDADES 

Produto: 4D
Tema: Apresentação da linguagem

 
HISTÓRIA 

 
ARTICLE USAGE

Manual de linguagem 4D ( 4D v16)
Manual de linguagem 4D ( 4D v16.1)
Manual de linguagem 4D ( 4D v16.2)
Manual de linguagem 4D ( 4D v16.3)