Determinare i Percorsi Reali di File e Programmi

Aprire Esplora risorse con Win+E. Navigare fino alla cartella desiderata nella struttura ad albero, per esempio Programmi, di cui si vuole determinare il percorso reale. Infine fare clic in un punto vuoto della Barra degli indirizzi di Esplora risorse. Windows visualizzerà il percorso reale al posto del nome logico, in questo caso apparirà C:\Program Files. Ora è possibile selezionare il percorso visualizzato e copiarlo negli Appunti di sistema con Ctrl+C per incollarlo dove necessario.

MAC Spoofing – Come Funziona

L’azione del MAC Spoofing consiste nel camuffamento del MAC della nostra scheda di rete e in pratica permette di modificare il MAC che viene trasmesso dal nostro dispositivo al Router a cui ci colleghiamo.
La seguente azione non andrà a modificare fisicamente il MAC scritto sulla EEPROM della scheda di rete ma solamente la sua “immagine”, cioè quella visibile dall’esterno.

Il MAC Spoofing non è sempre necessario – mi spiego meglio – se ci troviamo in una rete locale sicura, come per esempio la rete di casa nostra, effettuare il camuffamento del MAC address non ha senso, poiché non c’è nessuno che possa monitorarlo.
Questa tecnica invece è assai consigliata se ci troviamo in una rete non protetta, come quella di un Hotel in cui il gestore della rete potrebbe utilizzare il mostro indirizzo MAC in modo inappropriato.
Questa tecnica è di semplice attuazione e inoltre il MAC Spoofing può essere settato per essere eseguito in automatico all’avvio del PC.

Per iniziare rechiamoci nel terminale e con il comando
ip link show
facciamo una lista delle interfacce di rete collegate. Come possiamo notare in basso è riportato l’indirizzo MAC dell’interfaccia.

Ora andiamo a modificarlo. Per fare ciò dobbiamo scaricare un software aggiuntivo con i seguenti comandi
su
apt update
apt install macchanger
In questa fase apparirà una finestra molto utile che ci permette di impostare l’esecuzione automatica di macchanger rendendo il processo automatico. Ovviamente selezioniamo l’opzione <Sì> e proseguiamo.

Una volta fatto ciò utilizziamo il software appena installato con il comando:
ip link set {interfaccia} down
macchanger -r {interfaccia}
ip link set {interfaccia} up
per trovare il nome dell’interfaccia corrispondente a quella voluta affidiamoci al comando utilizzato per trovare il MAC, poiché esso ci fornisce dopo il numero dell’interfaccia anche il suo nome.
Così facendo modificheremo il MAC address della scheda di rete con uno generato casualmente dal software appena installato.

per essere certi dell’esecuzione del comando macchanger all’avvio della macchina andiamo ad aggiungerlo in uno script di avvio, quindi eseguiamo il seguente comando:
crontab -e
ci verrà aperto un file in cui inserire in coda al testo già presente la seguente stringa
@reboot machanger -r {interfaccia}
Ora possiamo tranquillamente riavviare il sistema e notare il cambio automatico del MAC address.

MAC Address – A Cosa Serve

Il MAC (Media Access Control) Address è un indirizzo univoco globale che identifica la scheda di rete di un qualsiasi dispositivo. Questo indirizzo, composto da 48bit, è rappresentato come un gruppo di sei coppie di cifre esadecimali. Qui ve ne riporto un esempio:

1c:3f:ad:03:75:df

le prime tre coppie di cifre identificano il produttore dell’hardware di rete in questione (es D-link, Netgear, Microsoft ecc…), mentre le seconde tre coppie sono a discrezione della casa produttrice dell’hardware stesso e per consuetudine identificano il modello della scheda di rete con il numero di serie.

Quando ci colleghiamo ad una rete l’AP o lo switch a cui ci connettiamo legge questo indirizzo, che è scritto su di una EEPROM saldata sulla scheda stessa, e lo utilizza per effettuare la connessione.

L’indirizzo in se non costituisce una minaccia vera e propria alla nostra sicurezza ma può essere usato per associare in maniera univoca la nostra attività di rete alla nostra macchina: in pratica qualcuno potrebbe tenere traccia delle nostre attività in un database e associarle al nostro device.
Facciamo un esempio esplicativo. Ipotizzando di trovarci in Hotel collegati ad un AP pubblico, se visitassimo un sito questo potrebbe essere associato al nostro MAC e costituirebbe una prova della nostra navigazione. Se invece noi camuffassimo il MAC del dispositivo anche se questo venisse associato ad una certa attività online, esso non combacerebbe con quello fisico della nostra scheda di rete per cui tale attività non sarebbe riconducibile a noi.

Come Scegliere un Proiettore

La nostra guida per scegliere il migliore proiettore è pensata per guidare gli utenti alla scelta di un modello affidabile e in linea con le loro esigenze tra i tanti disponibili sul mercato. In questo modo, evitano acquisti infelici dettati da un mero confronto tra prezzi e una inutile perdita di tempo e di denaro. Oltre a una classifica dei fattori da tenere maggiormente in considerazione al momento della scelta, ti offriamo la recensione dei cinque modelli che più ci hanno convinto quest’anno per rapporto tra qualità, prezzo e funzioni.

Risoluzione e alta definizione
Iniziamo a elencare le caratteristiche che la migliore marca di proiettori deve avere per venire incontro alle esigenze degli acquirenti. Al primo posto, per importanza, troviamo a nostro avviso la risoluzione supportata, decisiva nella qualità del risultato finale.
A cosa serve, infatti, acquistare un proiettore se poi ciò che trasmettiamo risulta sgranato e poco gradevole? Le risoluzioni più diffuse tra i proiettori sono tre. La SVGA, da 800 x 600 pixel, la XVGA da 1024 x 768 pixel e la SXGA da 1280 x 1024 pixel.
Se la prima risoluzione è adatta a chi voglia utilizzarlo per visualizzare presentazioni dal proprio computer o normali canali televisivi, le altre diventano via via sempre più indispensabili quando il contenuto video da mostrare sale di livello, come nel caso di videogiochi in alta definizione o film in HD.
Quando si tratta di ricreare nella propria casa un vero e proprio home theatre, quindi, occorre passare a modelli in grado di supportare l’alta definizione, come quelli HR ready a 720p e i FULL HD a 1080p, in grado di offrire una risoluzione da 1920 x 1080 pixel e al momento il massimo per quanto riguarda l’alta definizione domestica. Per dettagli sull’argomento è possibile vedere questa guida sui proiettori full hd su Videoproiettore.net.

Luminosità e rapporto di contrasto
Un altro fattore determinante nella scelta di un proiettore è legato alla luminosità che è in grado di generare. La potenza di emissione della luce è decisiva nel determinare quanto brillanti e vivide saranno le immagini proiettate. Uno molto efficiente in tal senso sarà in grado di proiettare immagini scintillanti anche in un ambiente non molto buio.
Il grado di luminosità di questi apparecchi si misura in ANSI (American National Standards Institute) Lumen. Un Ansi Lumen corrisponde al grado di luminosità di una candela. La luminosità è quindi un fattore particolarmente importante quando ci si trova in una stanza ampia, gremita e non perfettamente oscurata.
Anche il rapporto di contrasto è un dato utile nel determinare la qualità delle immagini riprodotte dal proiettore: più è alto, maggiore sarà la capacità del dispositivo di rendere le zone chiare e le zone scure dell’immagine video.

Altre caratteristiche
Al momento di acquistare un proiettore si possono prendere in considerazione anche altre caratteristiche che potrebbero far pendere l’ago della bilancia verso un modello piuttosto che un altro.
Per esempio, è importante tenere conto della durata della lampada, un pezzo che prima o poi dovremo cambiare e che ci costerà parecchio. In genere si misura in ore.
Un altro fattore importante è la dimensione dell’immagine che si può ottenere, più che altro per abbinarla alla scelta dello schermo su cui proiettarla.
Ulteriori considerazioni da fare riguardano le dimensioni e il peso dell’apparecchio, soprattutto se abbiamo intenzione di spostarlo con frequenza, magari per esigenze di lavoro. In questo caso, potrebbe fare comodo anche un modello dotato di batteria integrata.

Proseguiamo la nostra guida con una serie di consigli d’acquisto che ti suggeriscono quale proiettore comprare. Nella nostra comparazione tra i migliori modelli venduti online, non ci siamo fatti abbagliare da offerte destinate a sparire nel tempo, ma abbiamo preso in considerazione tutte le caratteristiche più importanti e il rapporto qualità/prezzo.

Acer P1173
Ad aggiudicarsi il titolo di migliore proiettore è questo modello prodotto dal celebre marchio Acer. Difficile, infatti, trovare un prodotto di fascia media con così tanti pregi e altrettanto versatile. Tra gli acquirenti soddisfatti dell’acquisto ci sono infatti sia utenti che lo impiegano abitualmente per la visione di film a casa sia persone che lo utilizzano principalmente per lavoro, mostrando le loro presentazioni a un’ottima risoluzione e sfruttando il sistema audio integrato.
Il proiettore ha una risoluzione SVGA da 800 x 600 pixel e supporta tranquillamente l’alta definizione (anche il full HD). Grazie all’ampia disponibilità di porte, potrai collegarlo a una grande varietà di dispositivi, dal portatile al decoder, per visualizzare in grande documenti, film, video e tanto altro ancora.
Ha un’ottima luminosità da 3000 ANSI Lumen, con una durata della lampada – comoda da sostituire anche in proiettori fissati al soffitto – di 4500 ore. Lampada che, oltretutto, è meno costosa delle media.

BenQ MS504
Proseguiamo i nostri suggerimenti su come scegliere un buon proiettore con un modello dalle caratteristiche e dal costo molto simili al precedente. In questo caso, a far pendere la tua decisione verso un modello piuttosto che un altro saranno piccoli dettagli, come l’aspetto estetico, la preferenza per un brand piuttosto che un altro o qualche caratteristica in più o in meno.
Anche il proiettore BenQ ha una luminosità di 3000 ANSI Lumen, una risoluzione SVGA da 800 x 600 pixel e una durata della lampada da 4500 ore, che può aumentare sfruttando la modalità economica. Ha poi un rapporto di contrasto molto elevato, che ti permetterà di godere di tutte le sfumature: 13.000:1.
È possibile scegliere tra tre formati di visualizzazione: 6:9,4:3 e 1:1 e il full HD è pienamente supportato. Ha uno zoom molto buono ed è piuttosto silenzioso e non troppo ingombrante.
Viene fornito completo di telecomando ma purtroppo non di copri obiettivo.

Epson EB-S04
Il proiettore Epson garantisce all’utente il beneficio di una straordinaria qualità delle immagini grazie all’impiego dell’innovativa tecnologia LCD a tre chip che, rispetto a quella tradizionale DLP a un chip, aumenta notevolmente le prestazioni assicurando immagini più nitide e luminose, l’ideale per impressionare clienti e colleghi in ufficio o per godersi un film a casa come al cinema.
Ma non è questo l’unico vantaggio presente. La ricchezza delle connessioni, comprese porta HDMI e USB, ne fanno un dispositivo versatile in grado di visualizzare i contenuti in alta definizione e quelli presenti sulle varie memorie esterne.
L’app iProjection permette perfino di inviare i file da smartphone e tablet direttamente in modalità wireless, il massimo della tecnologia e della comodità.
Pratico da trasportare grazie alla borsa inclusa, vanta infine una notevole durata della lampada e del filtro che quindi non dovranno essere sostituiti spesso.

Excelvan DVB-T
Scendendo leggermente di prezzo rispetto ai modelli precedenti incontriamo questo buon proiettore, che vanta prestazioni inferiori rispetto a quanto visto finora ma comunque sufficienti per la maggior parte degli usi.
La sua risoluzione nativa si attesta sugli 800 x 480 pixel, ma offre supporto per 780p e 1080p. La luminosità è di 2400 ANSI Lumen e anche il rapporto di contrasto è più basso, 1500:1.
Il proiettore ha un’ottima dotazione di uscite, con ben due HDMI, due uscite USB 2.0 (con supporto ad hard disk) e una VGA. Permette di visualizzare 16,7 milioni di colori e ha una lampada in grado di sostenere 50000 ore di utilizzo prima di dover essere sostituita.
Le immagini rimangono ben nitide anche variando sensibilmente la distanza (senza esagerare né in vicinanza che in lontananza) e si comporta bene anche in assenza di uno schermo professionale su cui effettuare le proiezioni.

Philips Picopix PPX3614
Abbiamo deciso di chiudere la nostra personale top 5 dei migliori proiettori dell’anno con un modello di fascia leggermente più alta (prezzo incluso), apprezzato soprattutto per la funzione Wi-Fi che permette di fare a meno di molti, fastidiosi cavi. Ti basta una connessione Wi-Fi per navigare in rete con il browser integrato e visualizzare sul grande schermo tutti i contenuti che ti interessano.
Inoltre, il lettore MP4 integrato permette di riprodurre tutti i formati audio e video più comuni. In questo modo, Philips Picopix è assolutamente indipendente da altri dispositivi e può estrarre i contenuti da visualizzare da chiavette USB, da vari tipi di schede di memoria e addirittura da una sua memoria integrata da 2 GB.
Il proiettore è dotato anche di una batteria integrata che permette di utilizzarlo senza bisogno di collegarlo a una presa elettrica per un massimo di due ore.
In definitiva, uno strumento molto versatile, con una buona qualità video sia in quanto a luminosità che a contrasto. Peccato per la ventola un po’ troppo rumorosa.

Epson EB-S03
Il modello qui recensito è uno dei più venduti dell’anno, sicuramente anche per merito di una certa facilità d’installazione e d’utilizzo. Alcune funzioni come la correzione trapezoidale verticale, infatti, vengono gestite autonomamente dallo strumento senza bisogno di un nostro intervento diretto.
Il proiettore Epson ha un’ottima dotazione di porte, mettendo a disposizione dell’utente sia l’HDMI che l’RCA, nonché una uscita USB attraverso la quale leggere i contenuti di una normale chiavetta.
La risoluzione SVGA da 800 x 600 risulta più che dignitosa sia per la visione di film che per chi ama cimentarsi con i videogiochi con uno schermo da cinema. La luminosità è piuttosto buona – 2700 ANSI Lumen –, così come il rapporto di contrasto a 10.000:1 e la durata della lampada stimata a 5000 ore, che diventano 6000 utilizzando la modalità a risparmio energetico.
Viene fornito completo di borsa per il trasporto, telecomando con batterie incluse e un valido manuale di istruzioni.

Overloading degli Operatori in C++

Ogni linguaggio di programmazione e` concepito per soddisfare determinati requisiti; i linguaggi procedurali (come il C) sono stati concepiti per realizzare applicazioni che non richiedano nel tempo piu` di poche modifiche. Al contrario i linguaggi a oggetti hanno come obiettivo l’estendibilita`, il programmatore e` in grado di estendere il linguaggio per adattarlo al problema da risolvere, in tal modo diviene piu` semplice modificare programmi creati precedentemente perche` via via che il problema cambia, il linguaggio si adatta. Famoso in tal senso e` stato FORTH, un linguaggio totalmente estensibile (senza alcuna limitazione), tuttavia nel caso di FORTH questa grande liberta` si rivelo` controproducente perche` spesso solo gli ideatori di un programma erano in grado di comprendene il codice.
Anche il C++ puo` essere esteso, solo che per evitare i problemi di FORTH vengono posti dei limiti: l’estensione del linguaggio avviene introducendo nuove classi, definendo nuove funzioni e (vedremo ora) eseguendo l’overloading degli operatori; queste modifiche devono tuttavia sottostare a precise regole, ovvero essere sintatticamente corrette per il vecchio linguaggio (in pratica devono seguire le regole precedentemente viste e quelle che vedremo adesso).

Le prime regole

Cosi` come la definizione di classe deve soddisfare precise regole sintattiche e semantiche, cosi` l’overloading di un operatore deve soddisfare un opportuno insieme di requisiti:

Non e` possibile definire nuovi operatori, si puo` solamente eseguire l’overloading di uno per cui esiste gia` un simbolo nel linguaggio. Possiamo ad esempio definire un nuovo operatore *, ma non possiamo definire un operatore **.
Questa regola ha lo scopo di prevenire possibili ambiguita`.
Non e` possibile modificare la precedenza di un operatore e non e` possibile modificarne l’arieta` o l’associativita`, un operatore unario rimarra`sempre unario, uno binario dovra` applicarsi sempre a due operandi; analogamente uno associativo a sinistra rimmarra sempre associativo a sinistra.
Non e` concessa la possibilita` di eseguire l’overloading di alcuni operatori, ad esempio l’operatore ternario ? :, l’operatore sizeof e gli operatori di cast e in particolare l’operatore .* e l’operatore punto (per la selezione dei campi di una struttura).
E` possibile ridefinire un operatore sia come funzione globale che come funzione membro, i seguenti operatori devono tuttavia essere sempre funzioni membro non statiche: operatore di assegnamento ( = ), operatore di sottoscrizione ( [ ] ) e l’operatore ->.
A parte queste poche restrizioni non esistono molti altri limiti, possiamo ridefinire anche l’operatore virgola ( , ) e persino l’operatore chiamata di funzione ( () ); inoltre non c’e` alcuna restrizione riguardo il contenuto del corpo di un operatore: un operatore altro non e` che un tipo particolare di funzione e tutto cio` che puo` essere fatto in una funzione puo` essere fatto anche in un operatore.
Un operatore e` indicato dalla keyword operator seguita dal simbolo dell’operatore, per eseguirne l’overloading come funzione globale bisogna utilizzare la seguente sintassi:
< ReturnType > operator@( < ArgumentList > ) { < Body > }

ReturnType e` il tipo restituito (non ci sono restrizioni); @ indica un qualsiasi simbolo di operatore valido; ArgumentList e` la lista di parametri (tipo e nome) che l’operatore riceve, i parametri sono due per un operatore binario (il primo e` quello che compare a sinistra dell’operatore quando esso viene applicato) mentre e` uno solo per un operatore unario. Infine Body e` la sequenza di istruzioni che costituiscono il corpo dell’operatore.
Ecco un esempio di overloading di un operatore come funzione globale:

struct Complex {
float Re;
float Im;
};

Complex operator+(const Complex& A, const Complex& B) {
Complex Result;
Result.Re = A.Re + B.Re;
Result.Im = A.Im + B.Im;
return Result;
}

Si tratta sicuramente di un caso molto semplice, che fa capire che in fondo un operatore altro non e` che una funzione. Il funzionamento del codice e` chiaro e non mi dilunghero` oltre; si noti solo che i parametri sono passati per riferimento, non e` obligatorio, ma solitamente e` bene passare i parametri in questo modo (eventualmente utilizzando const come nell’esempio).
Definito l’operatore, e` possibile utilizzarlo secondo l’usuale sintassi riservata agli operatori, ovvero come nel seguente esempio:

Complex A, B;
/* … */
Complex C = A + B;

L’esempio richiede che sia definito su Complex il costruttore di copia, ma come gia` sapete il compilatore e` in grado di fornirne uno di default. Detto questo il precedente esempio viene tradotto (dal compilatore) in

Complex A, B;
/* … */
Complex C(operator+(A, B));

Volendo potete utilizzare gli operatori come funzioni, esattamente come li traduce il compilatore (cioe` scrivendo Complex C = operator+(A, B) o Complex C(operator+(A, B))), ma non e` una buona pratica in quanto annulla il vantaggio ottenuto ridefinendo l’operatore.
Quando un operatore viene ridefinito come funzione membro il primo parametro e` sempre l’istanza della classe su cui viene eseguito e non bisogna indicarlo nella lista di argomenti, un operatore binario quindi come funzione globale riceve due parametri ma come funzione membro ne riceve solo uno (il secondo operando); analogamente un operatore unario come funzione globale prende un solo argomento, ma come funzione membro ha la lista di argomenti vuota.
Riprendiamo il nostro esempio di prima ampliandolo con nuovi operatori:

class Complex {
public:
Complex(float re, float im);
Complex operator-() const; // – unario
Complex operator+(const Complex& B) const;
const Complex & operator=(const Complex& B);

private:
float Re;
float Im;
};

Complex::Complex(float re, float im = 0.0) {
Re = re;
Im = im;
}

Complex Complex::operator-() const {
return Complex(-Re, -Im);
}

Complex Complex::operator+(const Complex& B) const {
return Complex(Re+B.Re, Im+B.Im);
}

const Complex& Complex::operator=(const Complex& B) {
Re = B.Re;
Im = B.Im;
return B;
}

La classe Complex ridefinisce tre operatori. Il primo e` il -(meno) unario, il compilatore capisce che si tratta del meno unario dalla lista di argomenti vuota, il meno binario invece, come funzione membro, deve avere un parametro. Successivamente viene ridefinito l’operatore + (somma), si noti la differenza rispetto alla versione globale. Infine viene ridefinito l’operatore di assegnamento che come detto sopra deve essere una funzione membro non statica; si noti che a differenza dei primi due questo operatore ritorna un riferimento, in tal modo possiamo concatenare piu` assegnamenti evitando la creazione di inutili temporanei, l’uso di const assicura che il risultato non venga utilizzato per modificare l’oggetto. Infine, altra osservazione, l’ultimo operatore non e` dichiarato const in quanto modifica l’oggetto su cui e` applicato (quello cui si assegna), se la semantica che volete attribuirgli consente di dichiararlo const fatelo, ma nel caso dell’operatore di assegnamento (e in generale di tutti) e` consigliabile mantenere la coerenza semantica (cioe` ridefinirlo sempre come operatore di assegnamento, e non ad esempio come operatore di uguaglianza).
Ecco alcuni esempi di applicazione dei precedenti operatori e la loro rispettiva traduzione in chiamate di funzioni (A, B e C sono variabili di tipo Complex):

B = -A; // B.operator=(A.operator-());
C = A+B; // C.operator=(A.operator+(B));
C = A+(-B); // C.operator=(A.operator+(B.operator-()))
C = A-B; // errore!
// complex& Complex::operator-(Complex&)
// non definito.

L’ultimo esempio e` errato poiche` quello che si vuole utilizzare e` il meno binario, e tale operatore non e` stato definito.
Passiamo ora ad esaminare con maggiore dettaglio alcuni operatori che solitamente svolgono ruoli piu` difficili da capire.

L’operatore di assegnamento

L’assegnamento e` un operatore molto particolare, la sua semantica classica e` quella di modificare il valore dell’oggetto cui e` applicato con quello ricevuto come parametro e restituire poi tale valore al fine di consentire espressioni del tipo:

A = B = C = < Valore >

che e` equivalente a

A = (B = (C = < Valore >));

Non lo si confonda con il costruttore di copia: il costruttore e` utilizzato per costruire un nuovo oggetto inizializzandolo con il valore di un altro, l’assegnamento viene utilizzato su oggetti gia` costruiti.

Complex C = B; // Costruttore di copia
/* … */
C = D; // Assegnamento

Un’altra particolarita` di questo operatore lo rende simile al costruttore (oltre al fatto che deve essere una funzione membro): se in una classe non ne viene definito uno nella forma X::operator=(X&), il compilatore ne fornisce uno che esegue la copia bit a bit. Lo standard stabilisce che sia il costruttore di copia che l’operatore di assegnamento forniti dal compilatore debbano eseguire non una copia bit a bit, ma una inizializzazione o assegnamento a livello di membri chiamando il costruttore di copia o l’operatore di assegnamento relativi al tipo di quel membro. In ogni caso comunque e necessario definire esplicitamente sia l’operatore di assegnamento che il costruttore di copia ogni qual volta la classe contenga puntatori, onde evitare spiacevoli condivisioni di memoria.
Notate infine che, come per le funzioni, anche per un operatore e` possibile avere piu` versioni overloaded; in particolare una classe puo` dichiarare piu` operatori di assegnamento, ma e` quello di cui sopra che il compilatore fornisce quando manca.

L’operatore di sottoscrizione

Un altro operatore un po’ particolare e` quello di sottoscrizione [ ]. Si tratta di un operatore binario il cui primo operando e` l’argomento che appare a sinistra di [, mentre il secondo e` quello che si trova tra le parentesi quadre. La semantica classica associata a questo operatore prevede che il primo argomento sia un puntatore, mentre il secondo argomento deve essere un intero senza segno. Il risultato dell’espressione Arg1[Arg2] e` dato da *(Arg1+Arg2) cioe` il valore contenuto all’indirizzo Arg1+Arg2. Questo operatore puo` essere ridefinito unicamente come funzione membro non statica e ovviamente non e` tenuto a sottostare al significato classico dell’operatore fornito dal linguaggio. Il problema principale che si riscontra nella definizione di questo operatore e` fare in modo che sia possibile utilizzare indici multipli, ovvero poter scrivere Arg1[Arg2][Arg3]; il trucco per riuscire in cio` consiste semplicemente nel restituire un riferimento al tipo di Arg1, ovvero seguire il seguente prototipo:

X& X::operator[](T Arg2);

dove T puo` essere anche un riferimento o un puntatore.
Restituendo un riferimento l’espressione Arg1[Arg2][Arg3] viene tradotta in Arg1.operator[](Arg2).operator[](Arg3).
Il seguente codice mostra un esempio di overloading di questo operatore:

class TArray {
public:
TArray(unsigned int Size);
~TArray();
int operator[](unsigned int Index);

private:
int* Array;
unsigned int ArraySize;
};

TArray::TArray(unsigned int Size) {
ArraySize = Size;
Array = new int[Size];
}

TArray::~TArray() {
delete[] Array;
}

int TArray::operator[](unsigned int Index) {
if (Index < Size) return Array[Index];
else /* Errore */
}

Si tratta di una classe che incapsula il concetto di array per effettuare dei controlli sull’indice, evitando cosi` accessi fuori limite. La gestione della situazione di errore e` stata appositamente omessa, vedremo meglio come gestire queste situazioni quando parleremo di eccezioni.
Notate che l’operatore di sottoscrizione restituisce un int e non e` pertanto possibile usare indicizzazioni multiple, d’altronde la classe e` stata concepita unicamente per realizzare array monodimensionali di interi; una soluzione migliore, piu` flessibile e generale avrebbe richiesto l’uso dei template che saranno argomento del successivo capitolo.