-- Introduzione
-- Obiettivi
Implementazione pratica
-- Dichiarazione di classe
Ereditarietà

Progetto Yed
Tecniche di programmazione ad oggetti con il linguaggio C.

Definizione dei metodi

Nel linguaggio C, una struttura ha lo scopo generico di contenere dati legati fra loro e correlati ad una particolare " entità " logica; fra questi dati, però, non sono previste referenze dirette ad una funzione, cioè ad un entità in grado di manipolarli in qualche modo. Dunque, inserire un prototipo di una funzione all'interno di una struttura ci è impossibile.
Quello che però ci è possibile inserire è un puntatore generico; e che cos'è un prototipo di una funzione, se non la definizione di un simbolo? Che cos'è l'implementazione di una funzione, se non la sequenza di operazioni da compiersi dopo un salto condizionato di memoria ( JSR ) eseguito verso quel simbolo? Che cosa fa il linker , fra le tante cose che fa, se non assegnare al simbolo una ben precisa locazione di memoria nell'area di indirizzamento dati del processo? Che cos'è un'invocazione di una funzione, se non il salto condizionato a tale simbolo?
Riprendiamo il nostro esempio: abbiamo già creato un puntatore ad una funzione all'interno della nostra interfaccia nella classe simulata. è giunto dunque il momento di realizzare l'implementazione di tale interfaccia. Quindi, una strada possibile sta nel creare, dopo il nostro header
yedprova.h che contiene la dichiarazione della nostra classe simulata, un file chiamato yedprova.c che conterrà le implementazioni dei metodi all'interno della nostra classe simulata. Questo file potrebbe assumere dunque la seguente forma:

#include "yedstd.h"
#include "yedprova.h"

int metodo(void *pVWork)
  {
  Cprova *this=pvWork;

  printf("Invocazione metodo: elemento interno [%d]\n",
         this->PRIVATE(foo_priv));
  return 0;
  }

Analizziamo in dettaglio l'esempio, soprattutto le linee colorate.
Come si può vedere, è stata implementata una funzione, chiamata metodo, che ha lo stesso identico prototipo della funzione il cui puntatore è stato dichiarato all'interno della dichiarazione dell'interfaccia della classe simulata Cprova. Il nome di questa funzione è lo stesso del nome assegnato al puntatore alla funzione all'interno di Cprova. Questa omonimia non è casuale, ma non è un vincolo; per chiarezza, è bene rispettarla.
Il puntatore in input al metodo, void *pvWork, viene successivamente assegnato ad una istanza locale della classe simulata Cprova ; questa operazione è fondamentale, per una serie di ragioni.
Un oggetto che istanzia una classe nel mondo C++ possiede una caratteristica intrinseca meravigliosamente utile e funzionale: il puntatore this. Quel puntatore non è altro che il puntatore all'oggetto stesso, che è trasparente al compilatore C++ nell'accesso al contenuto dell'oggetto, ma che in realtà è sempre intrinsecamente presente in tutte le operazioni che coinvolgono i dati dell'oggetto all'interno del metodo. Ribaltando nel dominio C, non possiediamo tale puntatore in maniera immediata nella nostra classe simulata, ma dato che ne ho un bisogno imprescindibile, si è scelto di acquisirlo direttamente come parametro passato al metodo. Quindi, nella scrittura dei metodi della nostra classe simulata è sempre necessario inserire fra i parametri in input un parametro puntatore void, che sarà il puntatore all'oggetto in fase di invocazione del metodo , perchè altrimenti il metodo non è in grado di crearsi il proprio puntatore this. Vediamo di chiarire il tutto con un piccolo esempio:

#include "yedstd.h"
#include "yedprova.h"

....
Cprova *cWrk;
....
cWrk->metodo(cWrk);
....

Il metodo riceve in input il puntatore cWrk, che diventa il proprio puntatore this .
Tramite il puntatore this, è facile accedere, tramite il passaggio PRIVATE(x), allo stato corrente dell'oggetto.
La soluzione utilizzata per creare questo puntatore this è da intendersi come provvisoria, perchè lo scenario ideale è indubbiamente la eliminazione del passaggio del puntatore in input al metodo, proprio come l'invocazione di un metodo nel mondo C++. Il tutto, però, nell'ottica della necessità assoluta di tale puntatore nel mondo C, anche per preservare l'integrità dei dati di un oggetto in applicazioni multithreading.

 


Copyright (C) - Giulio A. - ynoxia(at)gmail(dot)com