In primo luogo #define è una direttiva del preprocessore, mentre enum è una vera e propria parola chiave del linguaggio; oltre ad essere più pulito "stilisticamente" l'utilizzo di enum al posto di diversi #define rende più semplice il lavoro con codice di altri. Ad esempio supponiamo di avere un metodo che accetta un argomento di tipo int "operation" i cui valori validi sono definiti con dei #define:
codice:
//Nel file di header:
#define OPERATION_COPY 1
#define OPERATION_DELETE 2
int test(int operation);
//eccetera
//Nel file cpp:
int test(int operation)
{
switch(operation)
{
case OPERATION_COPY:
//...
break;
case OPERATION_DELETE:
//...
break;
//...
default:
throw std::runtime_error("Invalid \"operation\" argument.");
}
}
Un altro programmatore come può sapere che i valori validi da passare ad "operation" sono proprio quelli definiti dai due #define in questione? Se poi i #define sono inseriti in qualche file di header, magari anche annidiato in un altro, le cose si complicano ancor di più.
Esaminiamo invece lo stesso codice riscritto usando gli enum:
Ora considera lo stesso codice riscritto con l'uso di enum:
codice:
//Nel file di header:
enum operations
{
op_copy 1
op_delete 2
int test(int operation);
//eccetera
//Nel file cpp:
int test(operations operation)
{
switch(operation)
{
case operations::op_copy:
//...
break;
case operations::op_delete:
//...
break;
//...
default:
throw std::runtime_error("Invalid \"operation\" argument.");
}
}
Ad un altro programmatore risulteranno subito evidenti i valori accettati dalla funzione, senza contare che gli enum possono essere nidificati in classi e namespace e che in tal modo si evita di incorrere in problemi derivanti dal fatto che il precompilatore effettua una sostituzione "stupida" ed indiscriminata degli identificatori corrispondenti a quelli indicati nei #define.