/* Pensate a come risolvere questo problema: dobbiamo sommare 3 coppie di
 * variabili di 3 tipi diversi: int,long,float. In C occorre scriversi 3
 * funzioni di somma, una per gli int, una per i long, e una per i float:
 *
 * int sommainteri(int a,int b) {...}
 * long sommalong(long c,long d) {...}
 * float sommafloat(float e,float f) {...}
 *
 * In seguito, nel programma, dobbiamo stare attenti ad usare la funzione
 * giusta a seconda del tipo da sommare:
 *
 * bau = sommafloat(miofloat1,miofloat2);
 * beu = sommalong(miolong1,miolong2);
 * bou = sommaint(mioint1,mioint2);
 *
 * Se poi le mie variabili si chiamano sbirulino, scarrafone, ecc., dovro'
 * anche andarmi a cercare ogni volta nel listato la dichiarazione per
 * ricordarmi il loro tipo, per usare la funzione giusta.
 * In C++, invece, grazie al polimorfismo, possiamo sovrapporre metodi
 * aventi lo stesso nome, purche' abbiano parametri diversi: in questo
 * modo, possiamo riscrivere i 3 metodi visti prima dandogli lo stesso nome:
 *
 * int somma(int a,int b) {...}
 * long somma(long c,long d) {...}
 * float somma(float a,float b) {...}
 *
 * Questa sovrapposizione (overloading), ci permette ora di scrivere in
 * modo molto piu' semplice il listato, usando somma() per tutti i casi:
 *
 * bau = somma(miofloat1,miofloat2);
 * beu = somma(miolong1,miolong2);
 * bou = somma(mioint1,mioint2);
 *
 * Questo approccio e' migliore dal punto di vista logico, infatti quando
 * programmiamo e sommiamo la variabile X con la variabile Y, spesso non
 * ci ricordiamo il tipo di queste ultime, non essendo fondamentale, ma
 * se dobbiamo usare funzioni diverse a seconda del tipo, allora siamo
 * costretti a far entrare nel nostro ragionamento anche questo, facendoci
 * distrarre. Se dovessimo usare degli operatori diversi a seconda del
 * tipo di numeri anche quando facciamo i conti a mente, ad esempio dovessimo
 * pensare: "1 piuintero 1 = 2", "1.00 piufloat 1.00 = 2.00", "1 menointero
 * 1 = 0", "1.00 menofloat 1.00 = 0.00", "1 perintero 1 = 1", "1.00 perfloat
 * 1.00 = 1.00", "1 divisointero 1 = 1", "1.00 divisofloat 1.00 = 1.00",
 * allora fare i conti della spesa diventerebbe difficile anche per un
 * professore di matematica.
 * Invece, grazie al polimorfismo, si puo' "scaricare" questo compito al
 * compilatore, lasciando a noi i problemi piu' seri.
 * Da notare che il tipo di valore restituito dal metodo (ritorno) non
 * conta quando il compilatore deve scegliere che overload chiamare: per
 * tale scopo sono presi in considerazione solo i parametri in entrata.
 *
 * Vediamo questo esempio:
 */

#include <iostream.h>    // Header necessario per usare CIN e COUT
			 // Questo e' un commento C++ ad una sola linea


/* Ecco i 3 metodi aventi lo stesso nome e parametri diversi, che grazie
 * al polimosfismo si overloadano (soprappongono): ogni volta verra'
 * chiamato automaticamente il metodo giusto a seconda del tipo.
*/

int somma(int a,int b)
{
	return(a+b);
}

// Ora la versione per i long

long somma(long c,long d)
{
	return(c+d);
}

// Infine la versione per i float

float somma(float e,float f)
{
	return(e+f);
}

///////////////////////////////////////////////////////////////////////////
//                            Il main...
///////////////////////////////////////////////////////////////////////////

int main(void)
{

 int mioint1 = 15;        // Variabile di tipo int
 int mioint2 = 50;        // Variabile di tipo int

 long miolong1 = 150000;  // variabile di tipo long
 long miolong2 = 1666000; // variabile di tipo long

 float miofloat1 = 3.02;  // Variabile di tipo float
 float miofloat2 = 32.24; // Variabile di tipo float


// Ora sommiamo coppie di variabili di 3 tipi diversi usando sempre somma()

 cout << mioint1 << " + " << mioint2 << " = ";
 cout << somma(mioint1,mioint2) << "\n";

 cout << miolong1 << " + " << miolong2 << " = ";
 cout << somma(miolong1,miolong2) << "\n";

 cout << miofloat1 << " + " << miofloat2 << " = ";
 cout << somma(miofloat1,miofloat2) << "\n";

 return 0;	// main() restituisce 0
}

/* L'overloading permette di accedere ad un unsieme di metodi simili (almeno
 * a livello logico) usando lo stesso nome.
 * Naturalmente un'altra comodita' del polimorfismo e' quella di aggiungere
 * dei parametri opzionali ad una funzione, ad esempio si puo' fare in
 * modo che un metodo "mettiorario" possa accettare l'ora sia come 3 interi,
 * ore,minuti,secondi, che come stringa di testo "HH:MM:SS", che come un
 * singolo intero che rappresenti il numero di secondi passati dalle 00:00,
 * e opzionalmente si possa immettere un testo. I casi possibili saranno:
 *
 * mettiorario(16,28,5);
 * mettiorario("16:28:05");
 * mettiorario(58805);
 * mettiorario(16,28,5, "oggi sono contento");
 * mettiorario("16:20:05", "oggi sono contento");
 * mettiorario(58805, "oggi sono contento");
 *
 * Come si vede, 6 funzioni tutte con lo stesso nome. La sua documentazione
 * sarebbe qualcosa di simile:
 *
 * -------------------------------------------------------------------------
 * mettiorario(ora, messaggio opzionale)
 *
 *              ora = uno di questi 3 formati:
 *
 *                    int,int,int       ; ore, minuti, secondi
 *                    "HH:MM:SS"        ; stringa
 *                    long              ; n. secondi dall'inizio del giorno.
 * -------------------------------------------------------------------------
 *
 * Il tutto e' molto semplice. Immaginatevi a dover documentare cio' con
 * 6 funzioni di nome diverso a seconda dei parametri da passare!
 */