CATEGORII DOCUMENTE |
Bulgara | Ceha slovaca | Croata | Engleza | Estona | Finlandeza | Franceza |
Germana | Italiana | Letona | Lituaniana | Maghiara | Olandeza | Poloneza |
Sarba | Slovena | Spaniola | Suedeza | Turca | Ucraineana |
DOCUMENTE SIMILARE |
|
Il C++ permette la definizione di nuovi tipi. I tipi definiti dal programmatore vengono detti 'Tipi definiti dall'utente' e possono essere utilizzati ovunque È richiesto un identificatore di tipo (con rispetto alle regole di visibilitÀ viste precedentemente). I nuovi tipi vengono definiti applicando dei costruttori di tipi ai tipi primitivi (quelli forniti dal linguaggio) o a tipi precedentemente definiti dall'utente.
I costruttori di tipo disponibili sono:
il costruttore di array: [ ]
il costruttore di aggregati: struct
il costruttore di unioni: union
il costruttore di tipi enumerati: enum
la keyword typedef
il costruttore di classi: class
Per adesso tralasceremo il costruttore di classi, ci occuperemo di esso in seguito in quanto alla base della programmazione in C++ e meritevole di una trattazione separata.
Per quanto visto precedentemente, una variabile puÒ contenere un solo valore alla volta; il costruttore di array [ ] permette di raccogliere sotto un solo nome piÙ variabili dello stesso tipo.
La dichiarazione
int Array[10];
introduce con il nome Array 10 variabili di tipo int; il tipo di Array È array di 10 int(eri).
La sintassi per la generica dichiarazione di un array È
<NomeTipo> <Identificatore>[ <NumeroDiElementi> ];
Al solito NomeTipo puÒ essere sia un tipo primitivo che uno definito dal programmatore tramite uno degli altri meccanismi, Identificatore È un nome scelto dal programmatore per identificare l'array, mentre NumeroDiElementi deve essere un intero positivo.
Il generico elemento dell'array viene selezionato con la notazione Identificatore[Espressione], dove Espressione puÒ essere una qualsiasi espressione che produca un valore intero; il primo elemento di un array È sempre Identificatore[0], e di conseguenza l'ultimo È Identificatore[NumeroDiElementi-1]:
float Pippo[10];
float Pluto;
Pippo[0] = 13.5; // Assegna 13.5 al primo elemento
Pluto = Pippo[9]; // Seleziona l'ultimo elemento di Pippo
// e lo assegna a Pluto
È anche possibile dichiarare array multidimensionali (detti array di array o piÙ in generale matrici) specificando piÙ indici:
long double Qui[3][4]; // una matrice 3 x 4
short Quo[2][10]; // 2 array di 10 short int
int SuperPippo[12][16][20]; // matrice 12 x 16 x 20
E’ anche possibile specificare i valori iniziali dei singoli elementi dell'array tramite una inizializzazione aggregata:
int Pippo[5] = ;
short Pluto[2][4] = ;
long Manetta[ ][3] = ;
La prima dichiarazione È piuttosto semplice, dichiara un array di 5 elementi e per ciascuno di essi indica il valore iniziale a partire dall'elemento 0. La seconda dichiarazione È identica alla prima se si tiene conto che il primo indice a variare È l'ultimo, cosÌ che gli elementi vengono inizializzati nell'ordine Pluto[0][0], Pluto[0][1], , Pluto[1][3]
Le ultime due dichiarazioni sono piÙ complesse in quanto non vengono specificati tutti gli indici degli array: in caso di inizializzazione aggregata il compilatore È in grado di determinare il numero di elementi relativi al primo indice in base al valore specificato per gli altri indici e al numero di valori forniti per l'inizializzazione, cosÌ che la terza dichiarazione introduce un array di 3 elementi e l'ultima una matrice 2 x 3. È possibile omettere solo il primo indice e solo in caso di inizializzazione aggregata.
Gli array consentono la memorizzazione di stringhe :
char Topolino[ ] = 'investigatore' ;
La dimensione dell'array È pari a quella della stringa 'investigatore' + 1, l'elemento in piÙ È dovuto al fatto che in C++ le stringhe di default sono tutte terminate dal carattere nullo (0) che il compilatore aggiunge automaticamente.
L'accesso agli elementi di Topolino avviene ancora tramite le regole viste sopra e non È possibile eseguire un assegnamento con la stessa metodologia dell'inizializzazione:
char Topolino[ ] = 'investigatore' ;
Topolino[4] = 't'; // assegna 't' al quinto elemento
Topolino[ ] = 'basso'; // errore
Topolino = 'basso'; // ancora errore
È possibile inizializzare un array di caratteri anche nei seguenti modi:
char Topolino[ ] = ;
char Pluto[5] = ;
In questi casi perÒ non si ottiene una stringa terminata da 0, ma semplici array di caratteri il cui numero di elementi È esattamente quello specificato.
Gli array permettono di raccogliere sotto un unico nome piÙ variabili omogenee e sono solitamente utilizzati quando bisogna operare su piÙ valori contemporaneamente (ad esempio per eseguire una ricerca); da solo comunque il meccanismo degli array non consente la definizione di un nuovo tipo.
Solitamente per rappresentare entitÀ complesse È necessario memorizzare informazioni di diversa natura; ad esempio per rappresentare una persona puÒ non bastare una stringa per il nome ed il cognome, ma potrebbe essere necessario memorizzare anche etÀ e codice fiscale.
Memorizzare tutte queste informazioni in un'unica stringa non È una buona idea poiché le singole informazioni non sono immediatamente disponibili, ma È necessario prima estrarle, inoltre nella rappresentazione verrebbero perse informazioni preziose quali il fatto che l'etÀ È sempre data da un intero positivo.
D'altra parte avere variabili distinte per le singole informazioni non È certamente una buona pratica, diventa difficile capire qual È la relazione tra le varie componenti. La soluzione consiste nel raccogliere le variabili che modellano i singoli aspetti in un'unica struttura che consenta ancora di accedere ai singoli elementi:
struct Persona ;
La precedente dichiarazione introduce un tipo struttura di nome Persona composto da tre campi: Nome, un array di 20 caratteri; Eta, un intero positivo; CodiceFiscale, un array di 16 caratteri.
La sintassi per la dichiarazione di una struttura È
struct <NomeTipo> ;
Si osservi che la parentesi graffa finale deve essere seguita da un punto e virgola, questo vale anche per le
unioni, le enumerazioni e per le classi.
I singoli campi di una variabile di tipo struttura sono selezionabili tramite l'operatore di selezione .
(punto), come mostrato nel seguente esempio:
struct Persona ;
Persona Pippo = ;
Persona AmiciDiPippo[2] = ;
// esempi di uso di strutture:
Pippo.Eta = 41;
unsigned short Var = Pippo.Eta;
strcpy(AmiciDiPippo[0].Nome, 'Topolino');
Innanzi tutto viene dichiarato il tipo Persona e quindi si dichiara la variabile Pippo di tale tipo; in particolare viene mostrato come inizializzare la variabile con una inizializzazione aggregata del tutto simile a quanto si fa per gli array, eccetto che i valori forniti devono essere compatibili con il tipo dei campi e dati nell'ordine di dichiarazione dei campi.
Viene mostrata anche la dichiarazione di un array i cui elementi sono di tipo struttura, e il modo in cui eseguire una inizializzazione fornendo i valori necessari all'inizializzazione dei singoli campi di ciascun elemento dell'array (nell'ordine coerente alle dichiarazioni).
Le righe successive mostrano come accedere ai campi di una variabile di tipo struttura, in particolare l'ultima riga assegna un nuovo valore al campo Nome del primo elemento dell'array tramite una funzione di libreria. Si noti che prima viene selezionato l'elemento dell'array e poi il campo Nome di tale elemento; analogamente se È la struttura a contenere un campo di tipo non primitivo, prima si seleziona il campo e poi si seleziona l'elemento del campo che ci interessa:
struct Data ;
struct Persona ;
Persona Pippo = ;
Pippo.Nome[0] = 'P';
Pippo.DataNascita.Giorno = 15;
unsigned short UnGiorno = Pippo.DataNascita.Giorno;
Per le strutture, a differenza degli array, È definito l'operatore di assegnamento:
struct Data ;
Data Oggi = ;
Data UnaData = ;
UnaData = Oggi;
CiÃ’ È possibile per le strutture solo perché, come vedremo, il compilatore le tratta come classi i cui membri sono tutti pubblici.
L'assegnamento È ovviamente possibile solo tra variabili dello stesso tipo struttura, ma quello che di solito sfugge È che due tipi struttura che differiscono solo per il nome sono considerati diversi:
// con riferimento al tipo Data visto sopra:
struct DT ;
Data Oggi = ;
DT Ieri;
Ieri = Oggi; // Errore di tipo!
Un costrutto sintatticamente simile alle strutture È quello delle unioni. Sintatticamente l'unica differenza È che nella dichiarazione di una unione viene utilizzata la keyword union anziché struct:
union TipoUnione ;
Come per i tipi struttura, la selezione di un dato campo di una variabile di tipo unione viene eseguita tramite l'operatore di selezione . (punto).
Vi È tuttavia una profonda differenza tra il comportamento di una struttura e quello di una unione: in una struttura i vari campi vengono memorizzati in indirizzi diversi e non si sovrappongono mai, in una unione invece tutti i campi vengono memorizzati a partire dallo stesso indirizzo.
CiÒ vuol dire che, mentre la quantitÀ di memoria occupata da una struttura È data dalla somma delle quantitÀ di memoria utilizzata dalle singole componenti, la quantitÀ di memoria utilizzata da una unione È data da quella della componente piÙ grande (Stringa nell'esempio precedente).
Dato che le componenti si sovrappongono, assegnare un valore ad una di esse vuol dire distruggere i valori memorizzati accedendo all'unione tramite una qualsiasi altra componente.
Le unioni vengono principalmente utilizzate per limitare l'uso di memoria memorizzando negli stessi indirizzi oggetti diversi in tempi diversi. C'È tuttavia un altro possibile utilizzo delle unioni, eseguire 'manualmente' alcune conversioni di tipo. Tuttavia tale pratica È assolutamente da evitare (almeno quando esiste una alternativa) poiché tali conversioni sono dipendenti dall'architettura su cui si opera e pertanto non portabili.
A volte puÒ essere utile poter definire un nuovo tipo estensionalmente, cioÈ elencando esplicitamente i valori che una variabile (o una costante) di quel tipo puÒ assumere. Tali tipi vengono detti enumerati e vengono definiti tramite la keyword enum con la seguente sintassi:
enum <NomeTipo> ;
Esempio:
enum Elemento ;
Elemento Atomo = Idrogeno;
Gli identificatori Idrogeno, Elio, Carbonio e Ossigeno costituiscono l'intervallo dei valori del tipo Elemento. Si osservi che come da sintassi, i valori di una enumerazione devono essere espressi tramite identificatori, non sono ammessi valori espressi in altri modi (interi, numeri in virgola mobile, costanti carattere), inoltre gli identificatori utilizzati per esprimere tali valori devono essere distinti da qualsiasi altro identificatore visibile nello scope dell'enumerazione onde evitare ambiguitÀ.
Il compilatore rappresenta internamente i tipi enumerazione associando a ciascun identificatore di valore una costante intera, cosÌ che un valore enumerazione puÒ essere utilizzato in luogo di un valore intero, ma non viceversa:
enum Elemento ;
Elemento Atomo = Idrogeno;
int Numero;
Numero = Carbonio; // Ok!
Atomo = 3; // Errore!
Nell'ultima riga dell'esempio si verifica un errore perché non esiste un operatore di conversione da int a Elemento, mentre essendo i valori enumerazione in pratica delle costanti intere, il compilatore È in grado di eseguire la conversione a int.
È possibile forzare il valore intero da associare ai valori di una enumerazione:
enum Elemento ;
Non È necessario specificare un valore per ogni identificatore dell'enumerazione, non ci sono limitazioni di segno e non È necessario usare valori distinti. Si puÒ utilizzare un identificatore dell'enumerazione precedentemente definito e non È necessario specificare un valore intero per ciascun identificatore dell'enumerazione.
La possibilitÀ di scegliere i valori da associare alle etichette (identificatori) dell'enumerazione fornisce un modo alternativo di definire costanti di tipo intero.
Esiste anche la possibilitÀ di dichiarare un alias per un altro tipo (non un nuovo tipo) utilizzando la parola chiave typedef:
typedef <Tipo> <Alias> ;
Il listato seguente mostra alcune possibili applicazioni:
typedef unsigned short int PiccoloIntero;
typedef long double ArrayDiReali[20];
typedef struct Complesso;
Il primo esempio mostra un caso molto semplice: creare un alias per un nome di tipo. Nel secondo caso invece viene mostrato come dichiarare un alias per un array di 20 long double. Infine il terzo esempio È il piÙ interessante perché mostra un modo alternativo di dichiarare un nuovo tipo; in realtÀ ad essere pignoli non viene introdotto un nuovo tipo: la definizione di tipo che precede l'identificatore Complesso dichiara una struttura anonima e poi l'uso di typedef crea un alias per quel tipo struttura.
È possibile dichiarare tipi anonimi solo per i costrutti struct, union e enum e sono utilizzabili quasi esclusivamente nelle dichiarazioni (come nel caso di typedef oppure nelle dichiarazioni di variabili e costanti). La keyword typedef È utile per creare abbreviazioni per espressioni di tipo complesse, soprattutto quando l'espressione di tipo coinvolge puntatori e funzioni.
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 699
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved