





Studia grazie alle numerose risorse presenti su Docsity
Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium
Prepara i tuoi esami
Studia grazie alle numerose risorse presenti su Docsity
Prepara i tuoi esami con i documenti condivisi da studenti come te su Docsity
Trova i documenti specifici per gli esami della tua università
Preparati con lezioni e prove svolte basate sui programmi universitari!
Rispondi a reali domande d’esame e scopri la tua preparazione
Riassumi i tuoi documenti, fagli domande, convertili in quiz e mappe concettuali
Studia con prove svolte, tesine e consigli utili
Togliti ogni dubbio leggendo le risposte alle domande fatte da altri studenti come te
Esplora i documenti più scaricati per gli argomenti di studio più popolari
Ottieni i punti per scaricare
Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium
Una panoramica completa sulla programmazione orientata agli oggetti (oop), partendo dai concetti base come classi e oggetti, fino ad arrivare a principi più avanzati come l'incapsulamento, l'ereditarietà e il polimorfismo. Anche la gestione della memoria dinamica e l'importanza dell'interfaccia nelle classi. Inoltre, viene introdotto uml come strumento di modellazione grafica per l'oop, facilitando la comprensione e la progettazione di sistemi software complessi. Gli appunti sono utili per studenti universitari e sviluppatori che desiderano approfondire le proprie conoscenze sull'oop e migliorare le proprie competenze nella progettazione di software.
Tipologia: Appunti
1 / 9
Questa pagina non è visibile nell’anteprima
Non perderti parti importanti!






(Ripasso puntatori)
I puntatori hanno “ ***** ” davanti! → il puntatore “p” lo si indica con *p Ricorda: gli array sono dei puntatori (quando si dichiara un array si dichiara un puntatore con qualche caratteristica in più)
Unica differenza in C++ è che array è “limitato”: ● è lecito fare p++ p=a ● NON è lecito fare a++ a=p
RICORDARE: & indica/ricava l’indirizzo della variabile!!
Come poter allocare la memoria in modo dinamico? Vedi funzione new !! (Memo.Dinamica)
OOP : Object Oriented Project , programmazione che si concentra sui dati e le relazioni tra essi ( procedure di manipolazione dei dati) → Modello orientato ai dati
Sistema costituito da entità , oggetti che interagiscono tra loro. Si parla di tipo di dato astratto (ADT = abstract date type) Un dato ha: ● un insieme di valori ● un insieme di operazioni ad esso applicabili
Si parte da un sistema complesso (molteplici dati) e lo si scompone in diverse entità interagenti tra loro (NB. nel sistema strutturale si scompone il problema in sotto-problemi, con sotto-procedure risolutive; qui si lavora direttamente sull’entità)
La OOP facilita la progettazione ed il mantenimento di sistemi software molto complessi
Principali vantaggi : ● supporto naturale della modellizzazione software degli oggetti del mondo reale o del modello astratto da riprodurre ● più facile gestione e manutenzione di progetti di grandi dimensioni ● modularità e possibilità di riutilizzo del codice ● permette di definire oggetti software in grado di interagire tra loro grazie ad uno scambio di messaggi ● Riduce la dipendenza del codice dalla rappresentazione dei dati perché l’accesso ad essi è mediato da un’interfaccia
Elementi fondamentali dell’OOP: ● classe → descrizione astratta del tipo di dato descrive una famiglia di oggetti con caratteristiche e comportamenti simili (analoghe alle struct?) → entità → tipo di dato ● Oggetto → istanza di una classe (istanza di entità) → dato
L’oggetto è definito da: ● attributi : caratteristiche e proprietà fisiche che definiscono uno stato → dati membro → campi (sia variabili, sia costanti); le informazioni inserite ● metodi : comportamenti ammissibili o azioni (proprietà dinamiche) → funzioni membro → interfaccia della classe (attraverso dei messaggi la classe può comunicare all’oggetto, altrimenti l'oggetto non potrebbe interpretare le intenzioni dell’utente)
Lo stato dell’oggetto è l’ insieme dei valori assunti dalle variabili dell’oggetto stesso in un preciso istante. Al variare di un’informazione, muta lo stato dell’entità. esempio : videogame (cavaliere vs orco)
● Incapsulamento ed information hiding :
NB: Gli elementi nell’area privata sono invisibili non solo all’esterno, ma anche tra oggetti diversi in uno stesso programma!
● Interfaccia : insieme dei messaggi riferibili all’oggetto, NON mostra l’implementazione dei metodi, solo la lista di funzioni utilizzabili dall’oggetto ed alle info nella sezione pubblica
volume) → richiamato implicitamente alla creazione di un oggetto , per questo non ha bisogno di alcun tipo(c’è una sorta di default) specifico ma il programmatore ne può creare uno personalizzato utilizzando il nome della classe come metodo; inoltre non prevede la restituzione di alcun valore
ricorda: di default viene tutto impostato come privato
class NomeClasse { //Attributi (default==privati) → dati membro tipo1 attributo1; tipo2 attributo2; (...) //Metodi(default==privati) → funzioni membro public ( → da specificare per modificare il default!) tipo1 metodo1; tipo2 metodo2; (...) };
Per accedere ai membri di una classe dichiarata, si deve utilizzare la “ dot notation ”(il carattere “.” tra l’oggetto di studio ed il metodo/attributo utilizzato) → oggetto1. metodo1(variabile)
La creazione di un oggetto ha due conseguenze principali:
Differenza allocazione statica e dinamica: nel primo caso va conosciuto a priori dal programmatore il numero di byte necessari alla singola variabile, nel secondo caso no!
Nell’heap infatti è possibile sapere la quantità di memoria utilizzata dinamicamente solo durante il runtime , quando viene avviato il programma. Questo no n significa però che la “ durata di vita ” della variabile sia limitata al suo utilizzo: per deallocarla infatti bisogna utilizzare le giuste procedure.
Come allocare e deallocare una variabile dinamica : ● malloc() → allocazione(in memoria dinamica) per intero → alloca una certa quantità di byte, non per forza equamente suddivisa(esempio: tot. 40 byte allocati, elemento da 20, elemento da 5 e elemento da 15) == new (totale spazio) struttura funzione: malloc(dim_tot);
● calloc() → allocazione(in memoria dinamica) “a pezzi” → alloca un vettore con una lunghezza stabilita e suddivisa in ogni elemento(esempio: tot. 10 byte di memo; 5 elementi→ 2 byte a elemento) == new [ ] (array) struttura funzione: calloc(int num_elementi, int dim_elemento);
● realloc() → ri-allocazione utilizzabile solo se ho fatto una delle due allocazioni struttura funzione: voidrealloc(voidptr, int dim_tot)
● free() → la memo utilizzata va sempre liberata dopo aver eseguito il programma → libera la memoria occupata == delete/ delete[ ] struttura funzione: void free(void*ptr); → lascia vuoto lo spazio puntato da ptr, presumibilmente occupato in precedenza da una malloc o da una calloc
Da ricordare:
#ifndef → controlla se una costante non è definita
#define → definisce una costante
ifndef se file.h non è definito define se l'header è già stato definito
Infatti si utilizzano prettamente per il controllo dei file “.h” così da non avere ripetizioni , nel controllo effettuato da queste due funzioni(?) in pratica è come se tutti i fogli/file utilizzati nel programma si “fondessero” in un unico file “.obj” (oggetto) 🙂
● utilizzando questa categoria, si ha un risparmio di memoria
Si utilizzano quando serve utilizzare più volte uno stesso metodo/attributo per non dover specificare ogni volta(ed occupare memoria inutilmente)
Utilizzate per accedere ad attributi(anche privati!) di una classe
La funzione definita come friend riceve l’accesso alle informazioni generalmente non diffuse dal programma
sintassi: friend funzione(..)
si può solo restringere il campo, MAI allargare
Costruttori: il programma deve elaborare prima il costruttore della classe padre e poi va con quello del figlio.
Se quello del padre viene richiamato esplicitamente, viene utilizzato; in caso contrario,(quando non è specificato il costruttore padre) viene richiamato in automatico quello di default(sempre della classe padre ndr).
Se questo non dovesse esistere il programma da errore
funzionamento: viene creato il costruttore padre, poi il costruttore figlio, si esegue il programma fino alla fine, viene creato il distruttore figlio, poi il distruttore padre e si conclude il processo 🙂
Eredità singola: → Struttura: class Nome_Classe_Figlio: accessibilità Nome_Classe_Padre
Eredità multipla: una sottoclasse può essere figlia di più classi padre → Struttura: class Nome_Classe_Figlio: accessibilità Nome_Classe_Padre1, accessibilità Nome_Classe_Padre
● overloading: sovraccarico → stesso metodo con numero e/o tipo di parametri ( firma ) passati al programma diverso ● overriding: sovrapposizione/sovrascrittura → nome del metodo e firma( → numero e tipo dei parametri) uguali sia nella classe padre che nella classe figlio (→ stessi parametri) ma cambia il processo interno
con overriding→ eventuale problema con l’ ereditarietà multipla , per evitare errori di programma, si aggiunge lo scope definition della classe del quale uso il metodo/parametro : esempio del quadrato con metodo disegna sia in classe parallelogramma sia poligono; scrivo nel programma: quadrato disegna.poligono quadrato disegna.parallelogramma
esempio:
A) void registra (int, string, int) → padre void registra (int,string, int, int, string) → figlio: aggiunta di paramenti → overloading
B) void calcola_area (int b, int h) → padre void calcola_area (int b, int h) → figlio( a seconda che venga richiesto quadrato, triangolo, rettangolo; il programma fa il calcolo necessario) → overriding
Puntatore che fa riferimento alla classe, non serve dichiararlo perché già incluso in essa permette di accedere ai dati (anche privati?) della classe
Si utilizza per puntare e far eseguire esattamente quel pezzo di programma
servono per realizzare polimorfismo: funzioni membro introdotte da “virtual” che, inserite nella classe derivata(*), permettono di fare overriding → la funzione virtual deve OBBLIGATORIAMENTE essere creata nella classe base!!
anche queste funzioni,come nel polimorfismo “semplice”, permettono a diversi oggetti di rispondere in modo differente ad uno stesso metodo (cavaliere, fante, arciere → attacca)
(vedi programma “funzioni virtual” negli appunti del prof)
(*)si crea nella classe base e la si ridefinisce nella classe derivata (come esempio dell’area!!)
Questo tipo di polimorfismo è noto come polimorfismo runtime → attuato durante l’utilizzo