back to top

Il polimorfismo in C++

Una delle caratteristiche più interessanti del linguaggio C++ è la possibilità di servirsi del meccanismo del polimorfismo, che garantisce un sensibile miglioramento nella semplicità e soprattutto nella flessibilità della programmazione.

Vedremo infatti come, in un qualunque contesto operativo, il polimorfismo offra la possibilità di definire i tipi di dati trattati dal programma (a patto che facciano riferimento ad una base comune) non a priori in fase di prograqmmazione ma successivamente, ed in modo del tutto indipendente, all’atto di ciascuna esecuzione.

Per utilizzare al meglio tale meccanismo facciamo un breve ripasso degli strumenti operativi necessari: in particolare la classe e la derivazione tra classi.

Creare una classe

Le classi costituiscono uno degli strumenti più utili per la programmazione in diversi linguaggi, tra cui il C++. Per classe si intende un insieme di dati (detti dati membro) propri della classe e di funzioni (dette metodi) per gestire tali dati.

Il codice di un’ipotetica classe di prova di nome Classe_Prova risulterebbe simile a questo:

public class Classe_Prova
{
    //dati membro
    //metodi
}
Si può pensare ad una classe come alla rappresentazione di una categoria, ovvero di un insieme di oggetti o di individui accomunati da caratteristiche simili. Ad esempio è possibile realizzare una classe casa, una classe impiegato o una classe studente, ciascuna contraddistinta da particolari dati e metodi.

L’analogia tra lo strumento di programmazione rappresentato dalla classe e l’idea di categoria logica, di insieme di oggetti o soggetti simili, può essere ulteriormente estesa.

Classi base e classi derivate

Osserviamo infatti che tra insiemi diversi possono esistere particolari relazioni. L’insieme delle abitazioni, ad esempio, comprende l’insieme degli appartamenti, che ne è sottoinsieme. Si può dire dunque che ogni appartamento è anche una casa.

Si identifica in questo modo, una relazione di tipo “is-a” (letteralmente “è un/una”). Tale rapporto tra le due categorie trova una corrispondenza immediata a livello di programmazione con la definizioni di classi base e classi derivate.

Il processo di derivazione consente infatti alla classe derivata di ottenere tutti i dati e i metodi della classe base, potendone inoltre aggiungere di propri, più specifici, che non sono appartenenti alla classe base.

La relazione infatti non è simmetrica: si può dire, ad esempio, che ogni appartamento sia un’abitazione ma non che ogni abitazione sia un appartamento.

Impostare il codice di una classe base e della relativa classe derivata (in questo caso proprio Abitazione e Appartamento) risulta piuttosto semplice:

public class Abitazione
{
    //dati membro
    //metodi
}
public class Appartamento: public Abitazione
{
    //dati membro specifici della classe Appartamento
    //metodi specifici della classe Appartamento
}
Si ha inoltre a disposizione la possibilità anche di derivare più classi da un’unica classe comune (ad esempio Appartamento e Villa possono derivare da Abitazione) oppure, caratteristica decisamente peculiare del C++, non comune neppure a linguaggi diffusamente utilizzati come Java, una classe derivata può derivare da più classi base.

Ad esempio la classe Avvocato potrebbe derivare sia da Persona che da Libero Professionista, considerando che riassume le caratteristiche di entrambi i gruppi (il problema della derivazione di classi e della derivazione o ereditarietà multipla sono trattati più diffusamente nell’articolo “Il meccanismo di ereditarietà“, in questa stessa sezione).

Utilizzo del polimorfismo

Passiamo ora, sulla base del concetto di classe e della comprensione della pratica di derivazione di classi, ad esaminare nel dettaglio il meccanismo del polimorfismo.

Ad esempio, per comprenderne il funzionamento, immaginiamo che siano state programmate le classi Abitazione, Appartamento e Villa già citate precedentemente.

Tali classi, molto probabilmente, serviranno all’interno del programma principale per creare oggetti (ovvero elementi specifici della classe, ad esempio un determinato appartamento).

Appartamento *app=new Appartamento();
Abitazione *abitaz=new Abitazione();
In questo caso si creano rispettivamente un nuovo oggetto di tipo Appartamento di nome app e un nuovo oggetto di tipo Abitazione di nome abitaz. Tramite il polimorfismo è possibile anche utilizzare un’istruzione di questo tipo:

Abitazione *ab=new Appartamento();
In questo caso viene creato un oggetto di tipo Appartamento di nome ab, nonostante il puntatore faccia riferimento alla classe base Abitazione e non in modo specifico alla classe Appartamento (che deriva però da Abitazione).

Il polimorfismo garantisce dunque, in sostanza, la possibilità di creare un oggetto di classe derivata anche tramite un riferimento (o puntatore) ad oggetto di classe base.

Tale possibilità comporta una semplicità, ma soprattutto una flessibilità nella scrittura del codice decisamente maggiore. Immaginiamo ad esempio di voler scrivere un programma in grado di costruire un archivio di dati riguardanti abitazioni generiche, sia appartamenti che ville.

Non ci è possibile conoscere il numero esatto di appartamenti e ville all’atto della scrittura del programma, che deve invece potersi adattare ai dati forniti in input dall’utente durante l’esecuzione.

Il problema può essere semplicemente risolto tramite il polimorfismo. Dichiariamo infatti un puntatore ad un oggetto di classe base (in questo caso Abitazione) che verrà di volta in volta, secondo le richieste dell’utente, associato ad un oggetto di tipo Appartamento o ad un oggetto di tipo Abitazione.

Ecco un piccolo programma di esempio, che si serve delle funzioni cin e cout (presenti nella libreria iostream.h, che va richiamata per mezzo della parola chiave include) per gestire rispettivamente l’input e l’output dei dati rispetto all’utente. Se l’utilizzatore del programma digita “1” come comando viene creato un oggetto di tipo Appartamento, se digita “2” un oggetto di tipo Villa (“\n” indica il carattere di fine riga o a capo):

#include <iostream.h>
int valore_scelta;
Abitazione *ab;
cout<<"1-> Appartamento, 2-> Villa\n";
cin>>valore_scelta;
if (valore_scelta==1) ab=new Appartamento();
if (valore_scelta==2) ab=new Villa();

Pubblicitร 

Leggi anche...

Radice quadrata in C: vediamo come calcolarla in diversi modi

La radice quadrata è un'operazione matematica piuttosto comune (in...

Sperimentare la sequenza di Collatz in C++

Vediamo come verificare la congettura di Collatz con C++....

Calcolare la radice quadrata con Python

In Python è possibile calcolare la radice quadrata usando...

12 film che ogni programmatore dovrebbe guardare (per trovare ispirazione e creatività)

Molti ragazzi hanno deciso di intraprendere una carriera da...

Cartonizzare una foto con Python e la libreria OpenCV

La cartoonization è una procedura grafica che consente di...

Creare flowchart (diagrammi di flusso) online: 5 strumenti gratuiti

Hai bisogno di realizzare una flow chart ma non...
Pubblicitร