Copertina
Autore Herbert Schildt
Titolo La guida completa C++
EdizioneMcGraw-Hill, Milano, 1999 , pag. 976, dim. 170x240x57 mm , Isbn 88-386-4067-X
OriginaleC++: The Complete Reference [1998]
Classe informatica
PrimaPagina


al sito dell'editore

per l'acquisto

 

| << |  <  |  >  | >> |

Indice

Prefazione                                           XV

PARTE PRIMA - LE BASI DEL C++: IL LINGUAGGIO C        1


Capitolo 1 - Una panoramica sul linguaggio C          3

1.1 Le origini del linguaggio C                       3
1.2 Il C è un linguaggio di medio livello             4
1.3 Il C è un linguaggio strutturato                  5
1.4 Il C è un linguaggio per programmatori            7
1.5 L'aspetto di un programma C                       9
1.6 La libreria e il linker                          lO
1.7 Compilazione separata                            12
1.8 Le estensioni di file: .c e .cpp                 12

Capitolo 2 - Le espressioni                          15

2.1 I cinque tipi di dati principali                 15
2.2 Modificare i tipi principali                     16
2.3 Nomi degli identificatori                        18
2.4 Le variabili                                     19
2.5 I modificatori di accesso                        25
2.6 Specificatori di classe di memorizzazione        27
2.7 Inizializzazione delle variabili                 34
2.8 Le costanti                                      35
2.9 Gli operatori                                    38
2.10 Le espressioni                                  56

Capitolo 3 - Le istruzioni                           61

3.1 La verità e la falsità in C e C++                62
3.2 Le istruzioni di selezione                       62
3.3 Le istruzioni di iterazione                      74
3.4 La dichiarazione di variabili nelle
    istruzioni di selezione e iterazione             85
3.5 Le istruzioni di salto                           86
3.6 Le espressioni                                   92
3.7 I blocchi                                        93

Capitolo 4 - Gli array e le stringhe                 95

4.1 Gli array monodimensionali                       95
4.2 La generazione di un puntatore a un array        97
4.3 Come passare un array monodimensionale
    a una funzione                                   98
4.4 Le stringhe                                      99
4.5 Gli array bidimensionali                        102
4.6 Gli array multidimensionali                     108
4.7 L'indicizzazione dei puntatori                  109
4.8 L'inizializzazione degli array                  111
4.9 L'esempio del tris (tic-tac-toe)                114

Capitolo 5 - I puntatori                            119

5.1 Che cosa sono i puntatori?                      119
5.2 Variabili puntatore                             120
5.3 Gli operatori per i puntatori                   121
5.4 Espressioni con puntatori                       122
5.5 Puntatori e array                               127
5.6 Indirizzamento multilivello                     129
5.7 Inizializzazione di puntatori                   131
5.8 Puntatori a funzioni                            133
5.9 Le funzioni di allocazione dinamica del C       136
5.10 Problemi con i puntatori                       138

Capitolo 6 - Le funzioni                            143

6.1 La forma generale di una funzione               143
6.2 Regole di visibilità delle funzioni             144
6.3 Gli argomenti delle funzioni                    145
6.4 Gli argomenti di main(): argc e argv            150
6.5 L'istruzione retum                              154
6.6 Ricorsione                                      160
6.7 Prototipi di funzioni                           162
6.8 Dichiarazione di elenchi di parametri
    di lunghezza variabile                          165
6.9 Dichiarazione di parametri con metodi
    vecchi e nuovi                                  165
6.10 Elementi implementativi                        166

Capitolo 7 - Strutture, unioni, enumerazioni e
             tipi definiti dall'utente              169

7.1 Le strutture                                    170
7.2 Gli array di strutture                          174
7.3 Il passaggio di strutture alle funzioni         175
7.4 I puntatori a strutture                         177
7.5 Gli arraye strutture all'interno
    di altre strutture                              181
7.6 I campi bit                                     182
7.7 Le unioni                                       185
7.8 Le enumerazioni                                 188
7.9 Uso di sizeof per assicurare
    la trasportabi1ità del codice                   191
7.10 La parola riservata typedef                    193

Capitolo 8 - Operazioni di I/O da console           195

8.1 Un'importante nota applicativa                  196
8.2 La lettura e la scrittura di caratteri          196
8.3 La lettura e la scrittura di stringhe           199
8.4 Le operazioni di I/O formattato da console      202
8.5 La funzione printf()                            203
8.6 La funzione scanf()                             211

Capitolo 9 - Operazioni di I/O da file              219

9.1 Operazioni di I/O C e C++                       219
9.2 Stream e file                                   220
9.3 Gli stream                                      220
9.4 I file                                          221
9.5 Principi di funzionamento del file system       222
9.6 fread() e fwrite()                              235
9.7 fseek() e operazioni di I/O ad accesso diretto  237
9.8 fprint() e fscanf()                             239
9.9 Gli stream standard                             240

Capitolo 10 - Il preprocessore e i commenti         245

10.1 Il preprocessore                               245
10.2 La direttiva #define                           246
10.3 La direttiva #error                            249
10.4 La direttiva #include                          250
10.5 Le direttive per compilazioni condizionali     250
10.6 La direttiva #undef                            254
10.7 Uso di defined                                 255
10.8 La direttiva #line                             256
10.9 La direttiva #pragma                           256
10.10 Gli operatori del preprocessore # e ##        257
10.11 Le macro predefinite                          258
10.12 I commenti                                    259


PARTE SECONDA - IL LINGUAGGIO C++                   261


Capitolo 11 - Panoramica del linguaggio C++         263

11.1 Le origini del C++                             263
11.2 Che cos'è la programmazione a oggetti          265
11.3 Elementi di base del linguaggio C++            268
11.4 C++ vecchio stile e C++ moderno                275
11.5 Introduzione alle classi C++                   279
11.6 L'overloading delle funzioni                   284
11.7 L'overloading degli operatori                  287
11.8 L'ereditarietà                                 288
11.9 I costruttori e i distruttori                  293
11.10 Le parole riservate del C++                   297
11.11 Laforma generale di un programma C++          297

Capitolo 12 - Le classi e gli oggetti               299

12.1 Le classi                                      299
12.2 Le strutture e le classi                       303
12.3 Le unioni e le classi                          305
12.4 Le funzioni friend                             307
12.5 Le classi friend                               312
12.6 Le funzioni inline                             313
12.7 Definizione di funzioni inline
     all'interno di una classe                      316
12.8 I costruttori parametrizzati                   317
12.9 I membri static di una classe                  320
12.10 Quando vengono eseguiti i costruttori
      e i distruttori?                              327
12.11 L'operatore di risoluzione del campo
      d'azione                                      329
12.12 La nidificazione delle classi                 330
12.13 Le classi locali                              330
12.14 Il passaggio di oggetti a funzioni            331
12.15 La restituzione di oggetti                    334
12.16 L'assegnamento di oggetti                     335

Capitolo 13 - Gli array, i puntatori, gli indirizzi
              e gli operatori di allocazione
              dinamica                              337

13.1 Gli array di oggetti                           337
13.2 I puntatori a oggetti                          341
13.3 Verifiche di tipo sui puntatori C++            343
13.4 Il puntatore this                              343
13.5 I puntatori a tipi derivati                    345
13.6 I puntatori ai membri di una classe            348
13.7 Gli indirizzi                                  351
13.8 Questione di stile                             359
13.9 Gli operatori di allocazione dinamica del C++  360

Capitolo 14 - Overloading di funzioni, costruttori
              di copie e argomenti standard         371

14.1 Overloading delle funzioni                     371
14.2 Overloading delle funzioni costruttore         373
14.3 I costruttori di copie                         377
14.4 Ricerca dell'indirizzo di una funzione
     modificata tramite overloading                 381
14.5 L'anacronismo della parola riservata overload  383
14.6 Gli argomenti standard delle funzioni          383
14.7 Overloading di funzioni e ambiguità            390

Capitolo 15 - Overloading degli operatori           395

15.1 Creazione di una funzione operator membro      396
15.2 Overloading di operatori tramite
     funzioni friend                                403
15.3 Overloading di new e delete                    409
15.4 Overloading di alcuni operatori particolari    418
15.5 Overloading dell'operatore virgola             425

Capitolo 16 - L'ereditarietà                        429

16.1 Controllo dell'accesso alla classe base        429
16.2 Ereditarietà dei membri protected              432
16.3 Ereditarietà da più classi base                436
16.4 Costruttori, distruttori ed ereditarietà       437
16.5 Accesso alle classi                            445
16.6 Classi base virtuali                           448

Capitolo 17 - Funzioni virtuali e polimorfismo      453

17.1 Le funzioni virtuali                           453
17.2 L'attributo virtual viene ereditato            458
17.3 Le funzioni virtuali sono gerarchiche          459
17.4 Le funzioni virtuali pure                      462
17.5 Uso delle funzioni virtuali                    464
17.6 Il binding anticipato e il binding ritardato   467

Capitolo 18 - I template                            469

18.1 Funzioni generiche                             469
18.2 Uso delle funzioni generiche                   478
18.3 Classi generiche                               482
18.4 Le parole riservate typename ed export         493
18.5 La potenza deitemp1ate                         494

Capitolo 19 - Gestione delle eccezioni              497

19.1 Principi di gestione delle eccezioni           497
19.2 Gestione delle eccezioni per classi derivate   506
19.3 Opzioni della gestione delle eccezioni         507
19.4 Le funzioni terminate() e unexpected()         513
19.5 La funzione uncaughcexception()                515
19.6 Le classi exception e bad_xception             515
19.7 Applicazioni della gestione delle eccezioni    516

Capitolo 20 - Il sistema di I/0 C++: le basi        519

20.1 Operazioni di I/O C++ vecchie e nuove          520
20.2 Gli stream del C++                             520
20.3 Le classi per stream C++                       520
20.4 Operazioni di I/O formattato                   522
20.5 Overloading di « e »                           535
20.6 Creazione di funzioni di manipolazione         544

Capitolo 21 - Operazioni di I/0 su file in C++      549

21.1 L'header  e le classi per i file      549
21.2 L'apertura e la chiusura di un file            550
21.3 La lettura e la scrittura di un file di testo  553
21.4 Le operazioni di I/O binarie e non formattate  555
21.5 Altre forme della funzione get()               561
21.6 La funzione getline()                          561
21.7 Rilevamento della fine del file                563
21.8 La funzione ignore()                           565
21.9 Le funzioni peek() e putback()                 566
21.10 La funzione flush()                           566
21.11 L'accesso diretto ai file                     566
21.12 Lo stato delle operazioni di I/O              571
21.13 Personalizzazione delle operazioni
      di I/O sui file                               573

Capitolo 22 - L'identificazione run-time dei tipi
              e gli operatori cast                  577

22.1 L'identificazione run-time dei tipi (RTTI)     577
22.2 Gli operatori di conversione cast              587
22.3 L'operatore dynamic_cast                       587

Capitolo 23 - Namespace, funzioni di conversione
              e altri argomenti avanzati            599

23.1 I namespace                                    599
23.2 Lo spazio dei nomi std                         609
23.3 Creazione di funzioni di conversione           611
23.4 Funzioni membro const e mutable                614
23.5 Funzioni membro volatile                       617
23.6 Costruttori espliciti                          617
23.7 Uso della parola riservata asm                 619
23.8 Specifiche di linking                          620
23.9 Operazioni di I/O su array                     621
23.10 Uso di array dinamici                         626
23.11 Uso di I/O binario con stream basati su array 628
23.12 Riepilogo delle differenze esistenti
      fra C e C++                                   628

Capitolo 24 - Introduzione alla libreria STL        631

24.1 Introduzione all'uso della libreria STL        632
24.2 Le classi container                            635
24.3 Funzionamento generale                         636
24.4 I vettori                                      637
24.5 Le liste                                       647
24.6 Le mappe                                       658
24.7 Gli algoritmi                                  664
24.8 Uso degli oggetti funzione                     674
24.9 La classe string                               682
24.10 Commenti finali sulla libreria STL            694

PARTE TERZA - LA LIBRERIA DI FUNZIONI STANDARD      695

[...]

PARTE QUARTA - LA LIBRERIA DI CLASSI STANDARD
               DEL C++                              775

[...]

PARTE QUINTA -  APPLICAZIONI C++                    907


Indice analitico                                    969

 

 

| << |  <  |  >  | >> |

Pagina 1

Parte prima
LE BASI DEL C++: IL LINGUAGGIO C



In questo volume la descrizione del linguaggio C++ viene suddivisa in due parti. La Parte prima si occupa delle funzionalità che il C++ ha in comune con il suo progenitore, il C. Infatti il linguaggio C rappresenta un sottoinsieme del C++. La Parte seconda descrive le funzionalità specifiche del C++. Insieme, queste due parti, descrivono dunque il linguaggio C++. Come forse molti sanno, il C++ si basa sul linguaggio C. In pratica si può dire che il C++ include l'intero linguaggio C e (tranne lievi eccezioni), tutti i programmi C sono anche programmi C++. Quando fu inventato il linguaggio C++, venne impiegato come base il linguaggio C al quale vennero aggiunte molte nuove funzionalità ed estensioni con lo scopo di garantire il supporto della programmazione orientata agli oggetti (OOP). Questo non significa che gli aspetti che il C++ ha in comune con il C siano stati abbandonati ma, a maggior ragione, il C standard ANSI/ISO costituisce il documento di partenza per lo Standard Internazionale per il C++. Pertanto, la conoscenza del linguaggio C++ implica una conoscenza del linguaggio C.

In un volume come questa Guida completa, il fatto di suddividere il linguaggio C++ in due parti (le basi C e le funzionalità specifiche del C++) consente di ottenere tre vantaggi.

1. Si delinea con chiarezza la linea di demarcazione esistente fra C e C++.

2. I lettori che già conoscono il linguaggio C potranno facilmente trovare informazioni specifiche sul linguaggio C++.

3. Viene fornito un modo per discutere quelle funzionalità del linguaggio C++ che sono più legate al sottoinsieme costituito dal linguaggio C.

Comprendere la linea di divisione esistente fra C e C++ è importante poiché si tratta in entrambi i casi di linguaggi molto utilizzati e dunque è molto probabile che prima o poi venga richiesto di scrivere o eseguire la manutenzione di codice C e C++. Quando si lavora in C si deve sapere esattamente dove finisce il C e dove inizia il C++. Molti programmatori C++ si troveranno talvolta a scrivere codice che deve rientrare nei limiti stabiliti dal "sottoinsieme C". Questo accade particolarmente nel campo della programmazione di sistemi e della manutenzione di applicazioni preesistenti. Conoscere la differenza fra C e C++ è parte integrante della propria esperienza di programmatore C++ professionale.

Una buona comprensione del linguaggio C è insostituibile anche quando si deve convertire del codice C in C++. Per svolgere l'operazione in modo professionale, è necessario conoscere in modo approfondito anche il linguaggio C. Ad esempio, senza una conoscenza approfondita del sistema di I/O del C è impossibile convertire in modo efficiente dal C al C++ un programma che esegua notevoli operazioni di I/O.

| << |  <  |  >  | >> |

Pagina 3

Capitolo 1
Una panoramica sul linguaggio C



Conoscere il C++ significa conoscere le forze che hanno portato alla sua creazione, le idee che gli hanno dato il suo aspetto e i "caratteri" che ha ereditato. Pertanto la storia del C++ non può che partire dal C. Questo capitolo presenta una panoramica del linguaggio di programmazione C, le sue origini, il suo utilizzo e la sua filosofia. Poiché il C++ si basa sul C, questo capitolo presenta anche un'importante prospettiva storica sulle radici del C++. Molti degli elementi che hanno reso il linguaggio C++ quello che è hanno la loro origine nel linguaggio C.


1.1 Le origini del linguaggio C

Il C fu inventato e implementato per la prima volta da Dennis Ritchie su un sistema DEC PDP-11 che impiegava il sistema operativo Unix. Il C è il risultato di un processo di sviluppo che è partito da un linguaggio chiamato BCPL. Il BCPL, sviluppato da Martin Richards, influenzò un linguaggio chiamato B, inventato da Ken Thompson. Il B portò allo sviluppo del C negli anni '70.

Per molti anni, lo standard de facto del C fu la versione fornita con il sistema operativo Unix versione 5. Il linguaggio fu descritto per la prima volta nel volume The C Programming Language di Brian Kernighan e Dennis Ritchie. Nell'estate del 1983 venne nominato un comitato con lo scopo di creare uno standard ANSI (American National Standards Institute) che definisse il linguaggio C una volta per tutte. Il processo di standardizzazione richiese sei anni (molto più del previsto). Lo standard ANSI C fu infine adottato nel dicembre del 1989 e le prime copie si resero disponibili all'inizio del 1990. Lo standard venne anche adottato dall'ISO (Intemational Standards Organization) ed ora è chiamato Standard C ANSI/ISO. Per semplicità si userà semplicemente il termine Standard C. Oggi, tutti i principali compilatori C/C++ seguono lo Standard C. Inoltre, lo Standard C è anche alla base dello Standard C++.


1.2 Il C è un linguaggio di medio livello.

Il C è considerato da molti un linguaggio di medio livello. Questo non significa che il C sia meno potente, più difficile da utilizzare o meno evoluto rispetto a un linguaggio ad alto livello come il BASIC o il Pascal, né che il C abbia la natura complicata del linguaggio Assembler (con tutti i problemi derivanti). Piuttosto, significa che il C è un linguaggio che riunisce i migliori elementi dei linguaggi ad alto livello con le possibilità di controllo e la flessibilità del linguaggio Assembler. La Tabella 1.1 mostra la posizione del C nello spettro dei linguaggi per computer.

Essendo un linguaggio di medio livello, il C consente la manipolazione di bit, byte e indirizzi, gli elementi su cui si basa il funzionamento di un computer.

Nonostante ciò, il codice C è anche molto trasportabile. Con trasportabilità si intende la facilità di adattare su un sistema un software scritto per un altro computer o sistema operativo. Ad esempio, se è possibile convertire con facilità un programma scritto per il DOS in modo che possa essere utilizzato sotto Windows, significa che tale programma è trasportabile.

[...]

La peculiarità del C consiste nella possibilità di manipolare direttamente i bit, i byte, le word e i puntatori. Questo lo rende adatto alla programmazione di software di sistema, in cui queste operazioni sono molto comuni.

Un altro aspetto importante del C è la presenza di solo 32 parole chiave (27 derivanti dallo standard "de facto" Kernighan e Ritchie e 5 aggiunte dal comitato di standardizzazione ANSI), che sono i comandi che formano il linguaggio C. Normalmente i linguaggi di alto livello hanno molte più parole chiave. Come confronto, si può ricordare che la maggior parte delle versioni di BASIC conta più di 100 parole chiave!

| << |  <  |  >  | >> |

Pagina 263

Capitolo 11
Panoramica del linguaggio C++



Questo capitolo presenta una panoramica dei concetti di base che hanno condotto allo sviluppo del C++. Il C++ è un linguaggio di programmazione a oggetti le cui funzionalità sono strettamente correlate fra loro. In molti casi, questa correlazione rende difficile descrivere una funzionalità del C++ senza menzionarne nel contempo anche altre. In molte situazioni, le funzionalità a oggetti del C++ sono così correlate fra loro che per trattare una funzionalità è necessario che il lettore sia a conoscenza di una o più funzionalità correlate. Per risolvere questo problema, questo capitolo presenta una rapida panoramica degli aspetti più importanti del C++, la sua storia, le sue funzionalità principali e le differenze esistenti fra il C++ tradizionale e quello definito dallo standard. I capitoli successivi di questa parte della guida esaminano più in dettaglio il C++.


11.1 Le origini del C++

Il linguaggio C++ nacque come estensione del C. Le estensioni del C++ sono state inizialmente sviluppate da Bjarne Stroustrup nel 1979 presso i laboratori Bell di Murray Hill nel New Jersey. Inizialmente il nuovo linguaggio fu chiamato semplicemente "C con classi". Nel 1983 questo nome venne cambiato in C++.

Anche se il linguaggio C è stato uno dei linguaggi di programmazione professionali più apprezzati e ampiamente utilizzati al mondo, l'invenzione del C++ fu dettata dalla necessità di raggiungere maggiori livelli di complessità. Nel trascorrere degli anni, i programmi per computer sono diventati sempre più estesi e complessi. Anche se il C è un linguaggio di programmazione eccellente, anch'esso ha i propri limiti. In C, quando un programma supera le 25.000 o le 100.000 righe di codice, diviene così complesso che risulta difficile considerarlo nella sua totalità. Il C++ consente di superare questa barriera. L'essenza del C++ è stata quindi concepita con lo scopo di permettere ai programmatori di comprendere e gestire programmi più estesi e complessi.

La maggior parte delle funzionalità aggiunte da Stroustrup al C consente il supporto della programmazione a oggetti, chiamata anche OOP (per una breve descrizione della programmazione a oggetti, si consulti la prossima sezione di questo capitolo). Stroustrup asserisce che alcune delle funzionalità a oggetti del C++ sono state ispirate da un altro linguaggio di programmazione a oggetti il Simula67. Pertanto, il C++ rappresenta il punto di unione fra due dei metodi di programmazione più potenti.

| << |  <  |  >  | >> |

Pagina 265

11.2 Che cos'è la programmazione a oggetti

Poiché la programmazione a oggetti (OOP) ha dato origine al C++, è necessario comprendere i suoi principi fondamentali. La programmazione a oggetti rappresenta un nuovo e potente metodo di programmazione. Le metodologie di programmazione sono cambiate notevolmente dall'invenzione del computer, soprattutto per consentire di aumentare la complessità dei programmi. Ad esempio, quando furono inventati i computer, la programmazione veniva eseguita impostando istruzioni binarie tramite il pannello frontale del computer. Finché i programmi erano composti da poche centinaia di istruzioni, questo approccio ha funzionato. Con la crescita dei programmi è stato sviluppato il linguaggio Assembler con il quale un programmatore poteva realizzare programmi più estesi e complessi, utilizzando rappresentazioni simboliche delle istruzioni in linguaggio macchina. Ma i programmi continuavano a crescere e furono perciò introdotti linguaggi di alto livello che davano al programmatore più strumenti per gestire questa nuova richiesta di complessità. Il primo linguaggio di questo genere fu naturalmente il FORTRAN. Anche se il FORTRAN è stato un notevole passo in avanti rispetto al passato, si trattava di un linguaggio che non incoraggiava la realizzazione di programmi chiari e facili da comprendere.

Il 1960 ha dato i natali alla programmazione strutturata. Questo è il metodo seguito da linguaggi come il C e il Pascal. L'impiego di linguaggi strutturati ha reso possibile la realizzazione di programmi piuttosto complessi con una discreta facilità. I linguaggi strutturati sono caratterizzati dal supporto di subroutine indipendenti, variabili locali, costrutti di controllo avanzati e dal fatto di non impiegare GOTO. Tuttavia, anche utilizzando metodi di programmazione strutturata, un progetto può diventare incontrollabile una volta che raggiunga determinate dimensioni.

Si consideri questo fatto: ad ogni punto di svolta nel campo della programmazione, sono stati creati strumenti e tecniche che consentivano al programmatore di realizzare programmi più complessi. Ogni passo in questo percorso consisteva nell'utilizzo dei migliori elementi dei metodi precedenti e nel loro sviluppo. Prima dell'invenzione della programmazione a oggetti, molti progetti raggiungevano o superavano il punto in cui l'approccio strutturato non può più essere adottato. La programmazione a oggetti è nata con lo scopo di superare questa barriera.

La programmazione a oggetti ha preso le migliori idee della programmazione strutturata e le ha combinate con nuovi concetti. Il risultato è un'organizzazione completamente nuova dei programmi. In generale un programma può essere realizzato in due modi: ponendo al centro il codice ("ciò che accade") o ponendo al centro i dati ("gli attori interessati"). Utilizzando le tecniche della programmazione strutturata, i programmi vengono tipicamente organizzati attorno al codice. Questo approccio prevede che il codice operi sui dati. Ad esempio, un programma scritto con un linguaggio di programmazione strutturato come il C è definito dalle sue funzioni, le quali operano sui dati usati dal programma. I programmi a oggetti seguono l'altro approccio. Infatti sono organizzati attorno ai dati e si basano sul fatto che sono i dati a controllare l'accesso al codice. In un linguaggio a oggetti si definiscono i dati e le routine che sono autorizzate ad agire su tali dati. Pertanto sono i dati a stabilire quali sono le operazioni che possono essere eseguite. I linguaggi che consentono di attuare i principi della programmazione a oggetti hanno tre fattori in comune: l'incapsulamento, il polimorfismo e l'ereditarietà.

| << |  <  |