Lez. 1. |
Introduzione al corso:
Richiami alle moderne esigenze nella progettazione e produzione del software. L'importanza
dell'astrazione e del modello cliente-servitore. Oggetti come centri di servizio. Il
cambio del punto di vista. Testi consigliati |
Lez. 2. |
Un primo progetto: Proposta
di un cammino concettuale. Impostazione tradizionale alla progettazione e costruzione del
software a partire dalla Macchina. L'origine riferimento non � stata trovata.. Problema
0: il conteggio delle parole in un file. Necessit� di passare dalla costruzione di automi
risolventi alla costruzione del software per componenti riusabili e modificabili |
Lez. 3. |
Le funzioni come componenti
software: Le funzioni come servitori. Trasferimento di argomenti: il meccanismo di
trasferimento per riferimento. Funzioni inline. Insufficienza del concetto di funzione. Il
ruolo dell'astrazione. Il problema della modifica del software al variare dei requisiti.
Problema 1: contare le parole contenute in un file e visualizzare la (prima) parola pi�
lunga |
Lez. 4. |
Astrazione e
rappresentazione: Astrazioni di dato: principi di base. Tipi di dato astratto (ADT) e loro
influenza sul progetto. Astrazione, interfaccia e implementazione: il caso dell'ADT
parola. Necessit� di mantenere il codice dei clienti indipendente dalla rappresentazione
dei dati. Organizzazione modulare del testo del programma attraverso l'uso dei files. ADT
e progetto del software: una soluzione al problema 1 basata sull'ADT parola |
Lez. 5. |
Operazioni, valori,
costanti: Una possibile classificazione delle operazioni di un ADT: il punto di vista del
cliente. Oggetti come istanze di ADT. Oggetti atomici o composti. Oggetti con o senza
stato. Importanza della distinzione tra oggetti come valori e oggetti come contenitori.
Protezione dell'informazione nel caso di oggetti intesi come valori. Variabili,
assegnamento, r-value ed l-value. Denotazione di oggetti-valore mediante costanti.
Costanti in C e C++ |
Lez. 6. |
Costanti, trasformatori,
primitive: Problematiche legate all'uso di costanti in C++. Trasformatori: operazioni che
modificano lo stato degli oggetti. Una possibile classificazione delle operazioni di un
ADT: il punto di vista di chi realizza. Operazioni dipendenti dalla rappresentazione
concreta e operazioni indipendenti dalla rappresentazione (primitive). Problema 2: contare
le parole contenute in un file e visualizzarle in un elenco ordinato per lunghezza: una
soluzione indipendente dalla rappresentazione |
Lez. 7. |
Costruzione di un ADT:
l'elenco: Costruzione dell'ADT elenco. Separazione tra interfaccia e rappresentazione.
Modifica trasparente della rappresentazione: da una soluzione a memoria statica ad una
soluzione basata su memoria dinamica. ADT lista come contenitore di valori |
Lez. 8. |
Costruzione di un ADT: la
lista. Liste come valori non modificabili: primitive sulle liste di tipo Lisp (cons,
first, rest, null). Operazioni sulle liste indipendenti dalla rappresentazione:
visualizzazione e inserzione ordinata. La definizione ricorsiva di operazioni come
caso-limite di riusabilit�. Eliminazione ricorsiva di elementi da una lista priva di
trasformatori e analisi del processo a tempo di esecuzione |
Lez. 9. |
Astrazione,
rappresentazione, moduli: Influenza della rappresentazione sul progetto e sulla struttura
del software: il caso delle liste. ADT e organizzazione a moduli dei programmi.
Modificabilit� dei sistemi organizzati a moduli: il caso dell'elenco di parole. Moduli e
componenti software. Realizzazione a moduli di singole astrazioni di dato: il caso del
contatore. Limiti di questa impostazione |
Lez. 10. |
Classi, istanze, creazione,
distruzione: Il concetto di classe come unificazione dei concetti di ADT e di modulo.
Protezione dell'informazione: i qualificatori private e public. Esempi di definizione e
uso di classi: l'esempio del contatore. Variabili che denotano istanze di classi e loro
uso come normali variabili: importanza e conseguenze. Il problema della costruzione e
distruzione delle istanze. Meccanismi impliciti C++ per la costruzione-distruzione di
istanze di classi. Il concetto di oggetto-destinatario (sel) e la parola chiave this del
C++ |
Lez. 11. |
Costruttori multipli e
costruzione implicita: Operazioni di auto-spiegazione degli oggetti e loro importanza in
fase di messa a punto di programmi ad oggetti. Costruttori definiti dall'utente: l'esempio
del contatore. Trasferimento di oggetti per valore a funzioni e restituzione di oggetti da
parte di funzioni. Trasferimento di oggetti per riferimento |
Lez. 12. |
Variabili di classe,
puntatori a oggetti: Attributi comuni a istanze di oggetti: variabili di classe (static).
Il caso del contatore che tiene traccia del numero delle istanze. Esperimenti e
individuazione di un costruttore nascosto. La costruzione di copia e i momenti della sua
attivazione. Creazione di oggetti dinamici e relativa distruzione. Operatori new e delete |
Lez. 13. |
Oggetti costanti, puntatori,
vettori di oggetti: Oggetti costanti e operazioni dichiarate const. Puntatori a oggetti
costanti. Array di oggetti |
Lez. 14. |
Overloading di operatori,
conversioni di tipo: Estensione del linguaggio con tipi di dato definiti dall'utente:
l'esempio dell'ADT complex. Il problema della uniformit� tra tipi predefiniti e classi
definite dall'utente: il caso degli operatori. Overloading degli operatori in C++.
Espressioni miste. Costruttori come convertitori di tipo. |
Lez. 15. |
ADT complex, operazioni
friend, operatori di accesso: Espressioni miste complessi-float: non tutto funziona.
Superamento del problema mediante operazioni amiche (frient) di una classe. Categorie di
oggetti: oggetti come valori e come contenitori. Ridefinizione dell'operator [] come
selettore per la classe complex. Selettori e accessi indebiti a oggetti intesi come valori
|
Lez. 16. |
Oggetti, valori,
contenitori: le stringhe: Possibili interpretazioni dell'assegnamento ed eliminazione
dell'operator =(X&) dal protocollo di una classe. Oggetti come valori e come enti
dotati di stato: il caso dell'ADT stringa. Definizione della classe myString. Una
interfaccia funzionale, ispirata al Lisp, per l'uso convenzionale (non a messaggi) di
oggetti di tipo myString |
Lez. 17. |
Una versione funzionale
dell'ADT string: Interfacce funzionali per oggetti-valore della classe myString.
Indipendenza del codice dei clienti dalla scelta relativa alla rappresentazione concreta.
Transizione da una rappresentazione a memoria statica ad una a memoria dinamica.
Ridefinizione dei costruttori, distruttori e dell'operatore di concatenazione (operato +).
Influenza della rappresentazione sulla correttezza del software prodotto: il problema dei
riferimenti pendenti (dangling references) |
Lez. 18. |
Oggetti composti, oggetti
con puntatori: Classificazione degli oggetti in termini di struttura interna: oggetti
semplici, oggetti composti, oggetti con puntatore. Il caso degli oggetti composti:
revisione dei meccanismi impliciti di costruzione e distruzione. Esempio: il punto con
contatore. Invocazione esplicita di costruttori nell'intestazione di un costruttore. Il
caso degli oggetti con puntatori: il problema della condivisione delle strutture
(structure sharing) e dei riferimenti pendenti (dangling reference). La necessit� del
costruttore di copia |
Lez. 19. |
Il costruttore di copia:
Costruzione di copia X(X&) di default in C++ e momenti in cui essa interviene.
Definizione esplicita della costruzione di copia in oggetti semplici (esempio del
contatore) e composti (esempio del punto). Costruzione di copia in oggetti con puntatori,
superamento della copia bit a bit e della condivisione di strutture: il caso delle
stringhe basate su memoria dinamica |
Lez. 20. |
L'operatore di assegnamento:
Assegnamento di default in C++: copia membro a membro (shallow copy) con restituzione di
un riferimento all'oggetto destinatario. Frasi ad assegnamento multiplo. Ridefinizione
dell'assegnamento da parte dell'utente: le fasi di distruzione e ricostruzione
(dell'oggetto destinatario. Ridefinizione dell'operator= per la classe myString con copia
profonda (d'EEP copy) e superamento dei malfunzionamenti precedenti |
Lez. 21. |
Oggetti per
l'ingresso/uscita: cin, cout: Il modello ad oggetti: uno strumento per dominare la
complessit�. Sistemi ad oggetti che includono oggetti predefiniti per l'ingresso/uscita:
esempi d'uso. Overloading degli operatori >>e<< per gestire le trasformazioni
da rappresentazione esterna ad interna e viceversa di oggetti di classi definite
dall'utente |
Lez. 22. |
Ridefinizione degli
operatori <<e>>: Ridefinizione degli operatori di uscita ed ingresso per
classi di dati definite dall'utente: il caso del contatore e del punto. Introduzione alla
problematica della progettazione per il cambiamento. Problema 3: costruire un elenco di
parole in cui ciascuna � riportata una sola volta con a fianco il numero di volte in cui
compare nel testo dato. Una (specifica di) soluzione basata sull'astrazione "parola
con contatore" |
Lez. 23. |
Ereditariet�: introduzione:
Definizione di classi di dati "alle differenze": il caso dell'ADT parola
rispetto all'ADT my String. I concetti-base della relazione di ereditariet� tra classi. I
punti di vista del realizzatore e dell'utente e la dicotomia meccanismo-significato.
Struttura e protocollo delle classi derivate. Il problema della visibilit� delle
informazioni all'interno delle classi derivate e il qualificatore pretected. La non
ereditariet� di costruttori, distruttori e assegnamento. |
Lez. 24. |
Ereditariet�: costruzione,
distruzione: I meccanismi di costruzione-distruzione di default di istanze di classi
derivate. Invocazione esplicita di costruttori delle classi-base. L'esempio dell'ADT
parola |
Lez. 25. |
Ereditariet�, costruzione
di copia, assegnamento: I meccanismi impliciti di costruzione di copia nel caso di classi
derivate. Ridefinizione del costruttore di copia in una classe derivata e configurazione
di campi privati. I meccanismi impliciti di assegnamento nel caso di classi derivate.
Ridefinizione dell'assegnamento in una classe derivata, chiamata qualificata e
configurazione di campi privati |
Lez. 26. |
Ereditariet� e sviluppo
incrementale: un esempio: L'ADT parola (con contatore) come classe derivata. Risoluzione
del problema 3 usando gli elenchi come liste convenzionali e oggetti di tipo parola.
Mancanza di distruzione dell'elenco e delle parole ivi contenute al termine del programma |
Lez. 27. |
Ereditariet� e sviluppo
incrementale: un elenco di parole (modificabili): Completamento del problema 3 con
ingresso da input standard e da file (dispositivo di classe ifstream). Il problema della
revisione di operazioni ereditate: il caso della concatenazione di parole. Ereditariet� e
modifica dei requisiti. Problema 4: scrittura in lettere maiuscole delle parole con una
molteplicit� superiore a un valore dato. Definizione di una classe di parole modificabili
(modifWord) |
Lez. 28. |
Ereditariet� e significato:
la relazione IS_A: Completamento del problema 4. Ereditariet� e significato:
ereditariet� public come relazione IS_A. Classi derivate come sottotipi. Introduzione al
concetto di polimorfismo. Limiti alla possibilit� di realizzare operazioni polimorfiche:
il problema del "taglio" degli oggetti trasferiti per copia e i limiti del
binding statico |
Lez. 29. |
Ereditariet� e
polimorfismo: Polimorfismo connesso al trasferimento di oggetti per riferimento e suoi
limiti. Il concetto di binding dinamico. Operazioni virtual. Uso dei metodi virtual per
realizzare operazioni polimorfiche. Necessit� di impostare distruttori virtual |
Lez. 30. |
Ereditariet� e
polimorfismo: la realizzazione C++: La tabella dei metodi virtuali. Late binding come
chiamata indiretta a procedure. Necessit� di uso di riferimenti o puntatori ad oggetti
per ottenere operazioni polimorfiche. Impossibilit� di definire costruttori virtual e
regole connesse all'uso di operazioni virtual. Polimorfismo e assegnamento |
Lez. 31. |
Ereditariet� IS_LIKE e
riuso di codice: Ereditariet� private/protected e visibilit� delle informazioni. Riuso
del codice attraverso l'ereditariet� private/protected: il caso degli interi non limitati
e l'ADT myInt. Il concetto di invariante di classe nel progetto e realizzazione di classi
con riferimento alla metodologia di programmazione contrattuale. Ereditariet�
private/protected e metodi virtuali |
Lez. 32. |
Ereditariet�, progetto e
struttura: Ereditariet�, specializzazione e generalizzazione. Uso dell'ereditariet� per
separare interfaccia e implementazione: il concetto e il ruolo delle classi astratte.
Problema 5: fare l'elenco degli identificatori e delle rappresentazioni dei numeri interi
senza segno contenute in un file dato. Impostazione di un progetto basato su una
tassonomia di tipi. Una classe astratta PAROLA che sfrutta il late binding per realizzare
operazioni indipendenti dalla rappresentazione concreta dei dati |
Lez. 33. |
Ereditariet� multipla:
introduzione: Completamento del problema 5 con definizione e realizzazione di un semplice
analizzatore lessicale. Introduzione alla ereditariet� multipla. Ambiguit� delle
informazioni e sua risoluzione, derivazioni miste e loro significato. Classi comuni a pi�
percorsi |
Lez. 34. |
Ereditariet� multipla:
ereditariet� virtuale: Il problema delle classi comuni a pi� percorsi di derivazione.
Ereditariet� virtual. Schemi realizzativi della ereditariet� multipla virtual e non.
Ereditariet� multipla e puntatori a classi di oggetti. Complessit� strutturale e
semantica connessa all'ereditariet� multipla: un esempio. Non solo ereditariet�:
confronto tra ereditariet� e uso |
Lez. 35. |
Classi amiche: una
applicazione: Non solo ereditariet�: altre possibili relazioni tra classi. Realizzazione
di una lista-contenitore con condivisione di strutture e gestione della memoria. Il ruolo
delle classi amiche (friend). Una nuova soluzione al problema 3. Il concetto di iteratore.
Uso delle classi friend per realizzare iteratori. Un iteratore per l'ADT myInt della
lezione 31. Classi annidate: cenni |
Lez. 36. |
Componenti generici:
function template: Il problema della costruzione di componenti software generici. Problema
6: costruire elenchi omogenei di oggetti di tipo diverso. Limiti dell'approccio basato
sulla ereditariet� (genericit� constrained). Il concetto di modello (template). Funzioni
generiche: function template e template function. Esempi di uso di function template. Il
processo di istanziazione di un modello |
Lez. 37. |
Componenti generici:
function e class template: Regole per la determinazione (a compile-time) del codice da
eseguire in corrispondenza ad una invocazione di funzione. Esempi. Introduzione alle
classi generiche: class template e template class. Progetto di modelli ed ipotesi sui
parametri che rappresentano tipi |
Lez. 38. |
Class template: esempi:
Esempi di definizione ed uso di class template. Problematiche di suddivisione delle
dichiarazioni e definizioni dei modelli in file diversi. Class template ed ereditariet�.
Una lista generica e risoluzione del problema 6 |
Lez. 39. |
Architetture a oggetti.
Messaggi come eventi: Modello ad oggetti, progetto e produzione del software. Architettura
statica e a tempo di esecuzione dei programmi. Un caso di studio: determinazione dei
numeri primi con il metodo del crivello di Eratostene. Soluzione del problema mediante un
sistema a oggetti che si riconfigura dinamicamente. Messaggi: non solo chiamate di
procedura. Messaggi come eventi. Il caso di Windows e la Object Windows Library |
Lez. 40. |
Librerie di classi:
Programmazione ad oggetti ed ambienti di programmazione. Librerie di classi: il caso dei
dispositivi di ingresso-uscita. Il concetto di manipolatore e gestione dei manipolatori.
Derivazione da ofstream di una nuova classe di dispositivi che inserisce in testa ad ogni
linea il valore del contatore dei messaggi emessi. Uso della classe List della libreria
3.1 per la soluzione del problema 6. Cenni a direzioni di sviluppo del C++: le eccezioni
nell'ambito della programmazione contrattuale |