1
ELEMENTI DI SINTASSI
Per dichiarare una classe, si scrive la parola chiave class
seguita dal nome dell’oggetto e dai suoi membri; ad esempio
una classe Data che gestisce le date
class Data {
public:
Data(…);
void stampa() const;
bool controldata(…);
double dataNum(…);
private:
int mese, giorno, anno;
};
2
Un elemento generico di una classe è detto membro della
classe; i membri hanno nomi diversi all’interno di una classe
(anche se due classi distinte possono avere due membri con lo
stesso nome).
Tra i membri di una classe ci sono gli elementi di cui essa è
costituita, le proprietà, come i tre interi della classe Data, e le
function che rappresentano i metodi.
class Data {
public:
Data(…);
void stampa() const;
bool controldata(…);
double dataNum(…);
private:
int mese, giorno, anno;
};
3
Si tenga presente che tra i membri di una classe può apparire
anche un’altra classe, così come una struct poteva contenere
tra i suoi elementi un’altra struct.
membri
class Data {
public:
Data(…);
void stampa() const;
bool controldata(…);
double dataNum(…);
private:
int mese, giorno, anno;
};
metodi
proprietà
4
Ricordiamo che il campo d’azione (o scope) di una variabile o di
una costante è dato dalla più piccola istruzione composta
(gruppo di istruzioni racchiuso tra due parentesi graffe) che
include la sua dichiarazione.
Con la dichiarazione di una classe introduciamo un nuovo
campo d’azione (o scope) all’interno di un programma e, quindi,
ai due livelli già noti di scope globale e scope locale si aggiunge
un terzo livello: lo scope di classe.
La conseguenza di ciò è che tutti i membri di una classe sono
definiti all’interno del campo d’azione della classe e sono, quindi,
elementi globali dentro la classe.
I membri pubblici della classe diventano anche elementi globali
del programma, mentre i membri privati rimangono visibili
soltanto nel loro ambito.
5
I membri privati sono, comunque, visibili dalle funzioni membro
e dalle funzioni cosiddette “amiche”, le funzioni friend.
Le funzioni friend sono funzioni non membro che possono
accedere ai membri privati di una classe; esse vanno usate con
discrezione perché, superando la protezione della classe,
possono risultare potenzialmente pericolose.
6
ELEMENTI DI SINTASSI
class DECLARATIONS
Una dichiarazione di class equivale a una dichiarazione di un type.
Una variabile il cui type è una class è detta object.
Una class può ereditare proprietà da un’altra classe (di questo però
non ci occuperemo in questo corso).
Sintassi:
class class-name
{
private:
…………. // dichiarazione dei data members
pubblic:
…………. // dichiarazione delle function members
};
// fine di class-name
7
Ad esempio la dichiarazione per la class Studente è la seguente:
class Studente
{
private:
// data members
Definizione di variabile
string studente_nome;
float prima_prova, seconda_prova,
esame_finale, media;
pubblic:
};
Prototipi
// members functions
Studente();
// constructor
 Studente();
// destructor
char* get_name();
// access
void set_name(string);
// modify copia in studente_nome una stringa
void read_in();
// modify introduzione dati
void calcola_media();
// modify calcola la media degli esami
void display_average(); // display mostra la media degli esami
// end Studente class
8
I data members sono private e questo implica che essi sono visibili
solo da parte delle member functions della class Studente.
Funzioni che non appartengono alle member functions della class
Studente non possono accedere direttamente a questi dati.
Tra le sette member functions della class Studente vi sono il
constructor Studente e il destructor  Studente.
In pratica abbiamo quattro categorie di member functions:
1.
2.
3.
4.
constructor – destructor
access
modify
display.
Il fatto che le member functions sono pubblic significa che
dovunque sia definito un oggetto Studente tali member functions
9
possono esse applicate ad esso.
Le class declarations sono in genere messe in un header file
separato che quindi bisogna richiamare con un # include.
Vediamo un programma che definisce un oggetto Studente:
#include “studente.h”
…………………………..
int main()
{
Studente stu;
//Local data
//Statements
stu.read_in();
stu.calcola_media();
stu.display_media();
// end main
}
Il file header fornisce informazioni al compilatore per verificare10che
le chiamate alle member functions siano fatte in maniera corretta.
Nel programma precedente abbiamo introdotto la maniera per
definire un oggetto:
Sintassi: definizione di un oggetto
class-name object-name;
Studente stu;
Questa definizione è analoga a quella delle funzioni. Essa
permette l’allocazione di memoria per tutti i data member
previsti.
La vera differenza consiste nel fatto che negli oggetti è
esplicitamente previsto un constructor che invece nelle
function era implicito.
11
Quindi l’istruzione Studente stu alloca lo spazio necessario e
crea l’oggetto di nome stu appartenente alla class Studente.
Il constructor o non fa nulla o inizializza alcuni data members.
Analogamente quando l’oggetto viene rilasciato, il destructor
automaticamente libera lo spazio di memoria allocato per
esso.
Nell’esempio fatto questo avviene quando si esce dal main.
12
Sintassi per le member functions:
object-name.function-name(actual-arg-list);
stu.calcola_media();
Ovviamente function-name deve essere una public member
function della classe Studente a cui l’oggetto stu appartiene.
La parte della definizione denominata function-name(actualarg-list) è anche detta messaggio e object-name è detto
ricevitore del messaggio.
13
member function DEFINITIONS
Le member function definition è preferibile inserirle tutte in un
file xxx.cpp
Sintassi: constructor
class-name::class-name(formal-arg-list)
{
istruzioni
}
Il nome del constructor è il nome della sua stessa classe.
Si noti l’operatore :: detto scope resolution operator.
14
Un constructor senza argomenti è detto di default.
Un tale constructor deve essere dichiarato e definito per una classe
class-name se:
1. La classe class-name ha almeno un constructor che ha uno o più
argomenti, e
2. La classe class-name serve per essere usata in un array i cui
elementi sono di tipo class-name.
Possono coesistere anche più constructor. La forma dell’oggetto
determina quale constructor adoperare. Esempio
class CL
Le definizioni
{
CL obj1;
private:
CL obj2(0.0, -1.0)
…………….
implicheranno che all’obj1 sarà
pubblic.
applicato il constructor senza
CL();
argomenti, mentre all’obj2 quello
CL(float, float);
con due argomenti.
……………...
15
}
Nel caso della class Studente si ha:
// Constructor
Studente::Studente()
{
strcpy(student_name,” ”);
}
Questo constructor inizializza il valore di student_name alla stringa
vuota senza inizializzare gli altri data member della class.
Si noti che non abbiamo inizializzato l’intera class ma solo il
particolare oggetto Studente per il quale il constructor è stato
invocato.
Ad esempio quando definiamo
Studente stu;
Solo nell’oggetto stu lo student_name verrà posto uguale alla stringa
16
vuota.
// destructor
Una classe può avere un solo destructor il quale non ha argomenti.
Sintassi: destructor
class-name:: ~ class-name()
{
istruzioni
}
Esempio:
// destructor
Studente::~Studente()
{
; // in questo caso non ci sono unità dinamiche da deallocare
}
17
Altre member function DEFINITIONS
Sintassi:
return-type class-name::function-name(formal-arg-list)
Qui si definisce una member function che è stata dichiarata per la
classe class-name.
Le regole per determinare il return-type e gli argomenti sono
analoghe a quelle usate per le function.
Gli argomenti possono essere passati per valore o per indirizzo.
La differenza con le function consiste nel fatto che una member
function può far riferimento a tutte le private member function della
classe cui appartiene. Cioè quando una member function è applicata
ad un object essa può accedere a tutti i private data member di
quell’oggetto.
18
Data la lista astratta L1 contenente numeri interi relativi, scrivere un algoritmo che
pone i numeri negativi di L1 nella lista Lneg in ordine decrescente e i numeri
positivi o nulli nella lista Lpos in ordine crescente.
Si hanno a disposizione le seguenti funzioni membro:
class lista {
lista()
int estrai(int n)
// costruttore, inizializza a lista vuota.
// ritorna il valore dell’elemento di posto n, se esiste,
MAX_INT altrimenti
int lung()
// fornisce la lunghezza della lista.
void inserisci(int n, int k) // Inserisce l’intero k nel posto ennesimo se n è
minore o uguale alla lunghezza della lista più uno.
…………..}
19
void eser1_ListaAstratta(lista L1, lista &Lneg, lista &Lpos)
{
int i=1; int flag;
while i<=L1.lung()
{ if (L1.estrai(i)<0)
{ flag=-1;
inserimento(L1.estrai(i), Lneg, flag)
i++; }
else
{ flag=1;
inserimento (L1.estrai(i), Lpos, flag)
i++;
}
void inserimento (int k, lista &L, bool flag)
}
{
int j=1; bool trovato=false;
}
while (j<=L.lung()
{ if (flag*k< flag*L.estrai(j))
{ L.inserisci(k,j);
trovato=true;
}
else
j++;
}
if (!trovato)
L.inserisci(k,L.lung()+1);
20
}
Le Pile o Stack
• Una pila è una successione lineare di elementi,
eventualmente anche vuota
• Se gli elementi che compongono una pila sono tutti dello
stesso tipo la pila è detta omogenea.
• Le operazioni elementari che possono esser effettuate su di
esse sono: aggiungere un elemento, cancellare e/o estrarre
un elemento.
211
pila
Top
Top
22
pila
Le operazioni fondamentali che si fanno sulle pile sono:
riempimento e svuotamento.
Questo implica che durante lo svolgimento del programma il
numero di oggetti nella pila può cambiare.
Per descrivere una pila è sufficiente sapere quali sono gli oggetti
(Items) nella pila e il loro numero (Top).
23
OPERAZIONI SULLE PILE
In una pila l’elemento inserito per ultimo viene estratto per primo
(LIFO - Last In First Out).
In una pila, se si adopera una struttura ad array, occorrerrà solo
conoscere il numero di oggetti (Top).
Aggiungere ed eliminare oggetti.
Items[ ] è un array in cui si collocano gli oggetti, Top il numero
di oggetti, l’operazione di aggiungere oggetti si chiama push e
quella di eliminare oggetti pop.
Quando Top<0 allora la pila è vuota.
24
OPERAZIONI SULLE PILE
AGGIUNGERE
Top  Top + 1
Items[Top]  Item
ELIMINARE
Top  Top - 1
25
le operazioni
pila inizializza la pila vuota
push se la pila non è piena aggiungi oggetti altrimenti segnala errore
pop se la pila non è vuota elimina il primo oggetto altrimenti segnala
errore
cima se la pila non è vuota la funzione assume il valore dell’oggetto
al top della pila, in mancanza assume valore nullo
Vuota vera se non ci sono oggetti nella pila
Piena vera se la pila è piena
26
// COSTRUZIONE E GESTIONE DI UNA PILA CON UN VETTORE
// pileMat.h
#include<iostream>
using namespace std;
const int Max=10;
//
CLASSE
class pila {
public:
pila() { top=-1; }
void push(int e);
void pop(int &e);
void cima();
bool vuota();
bool piena();
friend ostream& operator<< (ostream&, pila);
private:
int top;
int items[Max];
};
27
// -------------------------- DEFINIZIONI
void pila::push(int e) {
if (!piena()) {
top++;
items[top]=e; }
else
cout<<"Pila piena"<<endl;
}
void pila::pop(int& e) {
if(!vuota()) {
e=items[top];
top--; }
else
cout<<"Errore la pila è vuota"<<endl;
}
bool pila::vuota() {
return (top==-1);
}
bool pila::piena() {
return (top==Max-1);
}
ostream& operator<< (ostream& os, pila p) {
os<<"(";
for(int i=p.top; i>=0; i--)
os<<p.items[i]<<" ";
os<<")"<<endl;
return os;
}
void pila::cima() {
if(!vuota())
cout<<"elemento in cima = "<<items[top]<<endl;
else
cout<<"Non ci sono elementi nella pila "<<endl;
}
28
// COSTRUZIONE E GESTIONE DI UNA PILA CON UN VETTORE
#include<iostream>
#include"pileMat.h"
using namespace std;
//
MAIN
int main() {
pila A;
int e, scelta=-1;
do {
cout<<"\n
MENU PILA "<<endl;
cout<<"1) Inserisci elemento nella pila"<<endl;
cout<<"2) Preleva elemento dalla pila"<<endl;
cout<<"3) Verifica pila vuota"<<endl;
cout<<"4) Verifica pila piena"<<endl;
cout<<"5) Visualizza elemento della pila"<<endl;
cout<<"6) Visualizza elenco della pila"<<endl;
cout<<"0) ESCI"<<endl;
cout<<"\n Inserisci scelta : ";
cin>>scelta;
29
switch(scelta)
{
case 1:
cout<<endl<<"Dammi il valore dell'elemento da inserire nella pila: (0 per finire) ";
cin>>e;
while (e!=0){
if (A.piena()) {
cout<<"\n\a La pila e' piena !!\n";
e=0;}
else {
A.push(e);
cout<<endl<<"Dammi il valore dell'elemento da inserire nella
pila:
(0 per finire) ";
cin>>e; }
}
break;
case 2:
if(!A.vuota()) {
A.pop(e);
cout<<"\n L'elemento prelevato dalla testa alla pila e' : "<<e<<endl;
}
else
cout<<"\n\n LA PILA e' VUOTA \a\n\n";
break;
30
case 3:
if(A.vuota()) cout<<"\n\a La pila e' vuota !!\n";
else cout<<"\n La pila non e' vuota !\n";
break;
case 4:
if(A.piena()) cout<<"\n la pila e' piena !!";
else cout<<"\n La pila non e' piena !";
break;
case 5:
A.cima();
break;
case 6:
cout<<A;
break;
case 0:
scelta =0;
break;
default:
cout<<"\n\a Inserisci un numero tra 0 e 6 \n";
}
} while(scelta);
return 0;
}
31
Si può adoperare una struttura a lista nella quale gli elementi si
aggiungono sempre in testa e si eliminano sempre a partire dalla
testa.
Es.
Pnodo Pila;
Pnodo push(Pnodo &TPila, int item);
// inserisci il nodo con chiave item in testa alla lista Pila;
Pnodo pop(Pnodo &TPila);
// elimina il nodo in testa alla lista Pila;
32
ESERCIZIO
Scrivere i prototipi e le definizioni degli operatori utilizzando le liste:
Pila,
Push ,
Pop,
Top,
pilaVuota ,
pilaPiena
33
Scarica

ppt