Jump to content
Sign in to follow this  
fredericopissarra

Um exemplo polimórfico, em C

Recommended Posts

A turma da OOP acredita que lidar com coisas como polimorfismo é impossível em linguagens "estruturadas". Eis um exemplo de como fazer uma lista de encadeamento simples, em C, com elementos de diversos "tipos"...

Considere a palavra-reservada struct: Ela existe para juntar vários tipos em um único container e de forma ordenada. Assim, se definirmos um nó genérico como:
 

typedef struct node_s {
  struct node_s *next;
} node_T; // _T porque _t não deve ser usado!

Podemos definir uma estrutura de controle para uma lista como:

// Usado para inicializar uma estrutura de lista vazia.
#define EMPTY_LIST { NULL, NULL }

typedef struct list_s {
  node_T *head, *tail;
} list_T;

Podemos agora usar a regra de que todo elemento que será colocado nessa lista deve definir, primeiro, um ponteiro do tipo node_T que aponte para o próximo item da lista... Por exemplo, suponha que eu queira criar uma lista de vetores 3D (x,y,z). Posso definir os elementos como:
 

struct vec3d_element_s {
  node_T *next;  // isso TEM que estar aqui!

  // nosso vetor:
  double x, y, z;
};

Eis uma rotina que adiciona elementos no início de uma lista:

// note que elemp é ponteiro para void, aceita qualquer ponteiro!
void addhead( list_T *lstp, void *elemp )
{
  node_T *p = elemp;

  p->next = lstp->head;
  lstp->head = p;  // o elemento é a nova 'cabeça' da lista.

  // Se a lista estiver previamente vazia, temos um novo 'rabo'.
  if ( ! lstp->tail )
    lstp->tail = p;
}

Note que, junto com a definição da estrutura de lista, defini um macro EMPTY_LIST. Isso permite o seguinte uso:

// define uma lista vazia.
list_T list = EMPTY_LIST;
struct vec3d_element_s *elemp; // ponteiro para nosso novo elemento.

elemp = malloc( sizeof *elemp ); // aloca elemento.
elemp->x = 0.0;    // inicializa dados do elemento.
elemp->y = 1.0;
elemp->z = sqrt(2.0);

// adiciona elemento na lista:
addhead( &list, elemp );

Note que nossa lista aceita QUALQUER estrutura que tenha, como seu primeiro membro, um ponteiro para node_T nomeado de next. Poderíamos fazer algo assim:

enum vec_type { V2D, V3D, V4D };

struct vec_element_s {
  node_T *next;
  enum vec_type vtype;

  double v[0]; // yep... tamanho 0!
};
...
list_T list = EMPTY_LIST;
...
// Aloca vetor 2D, inicializa-o e coloca na lista:
struct vec_element_s *v2d;
v2d = malloc( sizeof *v2d + 2*sizeof( double ) );
v2d->vtype = V2D;
v2d->v[0] = 1.0;
v2d->v[1] = 2.0;
addhead( &list, v2d );

// Aloca vetor 3D, inicializa-o e coloca na lista.
struct vec_element_s *v3d;
v3d = malloc( sizeof *v3d + 3*sizeof( double ) );
v3d->vtype = V3D;
v3d->v[0] = 1.0;
v3d->v[1] = 2.0;
v3d->v[1] = 3.0;
addhead( &list, v2d );

// percorre a lista e faz algo com os elementos:
node_T *p;

p = list.head;
while ( p )
{
  doSomething( p );
  p = p->next;
}

Na hora de percorrer a lista podemos usar o membro vtype para dedicir o tamanho do array v. Mas, note que a lista não se importa com o tipo do elemento, desde que ele tenha o ponteiro next como primeiro item.

  • Curtir 1

Share this post


Link to post
Share on other sites

PS; É claro... se quiser adicionar elementos no final da lista:
 

void addtail( list_T *lstp, void *elemp )
{
  node_T *p = elemp;
  
  // esse será o último elemento!
  p->next = NULL;

  if ( ! lstp->tail )  // lista vazia?
  {
    lstp->head = lstp->tail = p;
    return;
  }

  // ajusta o nó tail atual para o novo nó.
  lstp->tail->next = p;
  lstp->tail = p;
}

 

  • Curtir 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...