Elementi di
programmazione
ad oggetti
a. a. 2009/2010
Corso di Laurea Magistrale in Ingegneria Elettronica
Docente: Mauro Mazzieri, Dipartimento di Ingegneria Informatica,
Gestionale e dell’Automazione
Lezione 2
Regole di visibilità e ciclo di vita
Visibilità di una variabile
Il campo d’azione o spazio di visibilità
di una variabile (scope) indica la parte
di programma che può accedere alla
variabile per leggerla o modificarla
 La visibilità è limitata al blocco
(racchiuso tra parentesi graffe) in cui
la variabile è dichiarata

Visibilità in C++

Il C++ supporta tre tipi di visibilità:

Locale
 La
parte di programma che costituisce la
definizione di una funzione definisce un
campo di visibilità separato

Di namespace
 La
parte di programma non contenuta nella
dichiarazione o definizione di una funzione o
di una classe


Lo scope del namespace più esterno è detto
scope globale
Di classe
 Interno
alla definizione di una classe
Esempio
// scope
int a1 =
int a2 =
int b1 =
int b2 =
globale
3;
4;
9;
11;
double distanza(int x1, int y1, int x2, int y2) {
// scope locale
double dx = x2 - x1;
double dy = y2 - y1;
return sqrt(dx*dx + dy*dy);
}
int main()
{
std::cout << distanza(a1, a2, b1, b2) <<std::endl;
system("pause");
return 0;
}
Esempio: errori e precisazioni
double distanza(int x1,
double dx = a2 – a1;
double dy = b1 - y1;
return sqrt(dx*dx +
}
int y1, int x2, int b1) {
// errore: non è accessibile
// parametro, non b1 del main
dy*dy);
int main()
{
int a1 = 3;
int a2 = 4;
int b1 = 9;
int b2 = 11;
std::cout << distanza(a1, a2, b1, b2) <<std::endl;
system("pause");
return 0;
}
Ciclo di vita

Il ciclo di vita di una variabile è il
periodo compreso tra la sua creazione
e la sua eliminazione
Nasce quando la variabile viene
associata ad una locazione di memoria
 Muore quando la locazione di memoria
ritorna libera e riutilizzabile


La vita di una variabile inizia quando
viene dichiarata e finisce con la
parentesi graffa di chiusura del suo
blocco di visibilità
Esempio
int main() {
int a = 5; // a nasce
if (a > 3) {
int b = 7; // b nasce;
a = b * b;
a++;
} // b muore
cout << a;
cout << b; // errore: b non è pù
visibile
} // a muore
Ciclo di vita e scope
Se una variabile è viva, non vuol dire
che sia visibile dalla porzione di
codice in esecuzione ad un dato
istante
 Una variabile locale può esistere in
più istanze contemporaneamente


Tutte le istanze sono vive, ma solo una è
visibile
Esempio
int fattoriale(int n) {
int f1 = 1;
if (n > 1)
f1 = fattoriale(n - 1);
return f1 * n;
}
int main()
{
int a = 3;
cout << fattoriale(4);
}


Dentro fattoriale, a è viva ma non visibile
Vengono successivamente create 3 istanze di f1
(corrispondenti alle chiamate ricorsive di fattoriale)
Oggetti e funzioni globali

Una funzione dichiarata nel campo
d’azione globale è una funzione
globale

Una variabile dichiarata nel campo
d’azione globale è un oggetto globale


Il ciclo di vita di un oggetto globale inizia
all’avvio del programma e termina alla
fine del programma
One Definition Rule (ODR): funzioni e
oggetti globali possono essere definiti
una sola volta
Definizioni

La definizione di una funzione le fornisce un corpo,
racchiuso tra parentesi graffe
int calcola(int a, int b); // solo
dichiarazione
int maggiore(int x, int y) { // definizione
if (x > y)
return x;
return y;
}

La definizione di un oggetto ha due possibili forme


<tipo> <nome>; // senza inizializzazione
<tipo> <nome> = <inizializzazione>;
Oggetti locali


La dichiarazione di una variabile nel campo
d’azione locale introduce un oggetto locale
Ci sono 3 generi di oggetti locali:

Automatici


register


Vivono dalla chiamata della funzione in cui sono
definiti fino al ritorno dalla funzione
Oggetti automatici per i quali viene richiesta al
compilatore una memorizzazione veloce
Statici

Risiedono in uno spazio di memoria che rimane
riservato per l’intera vita del programma
Oggetti automatici
Occupano uno spazio di memoria che
viene allocato al momento della
chiamata della funzione in cui sono
dichiarati
 Se non vengono inizializzati, hanno
un contenuto che dipende da cosa
era memorizzato in precedenza in
quella locazione di memoria
 Lo spazio di memoria a loro dedicato
viene liberato in automatico al
termine della funzione

Oggetti register

Dichiarati con la parola chiave
register
La dichiarazione suggerisce al
compilatore di ottimizzarne l’accesso per
uso frequente
 Nella maggior parte dei compilatori
moderni, è inutile e ridondante

Oggetti locali statici



Dichiarate con la parola chiave static
Durano l’intera esecuzione del programma
Sono inizializzate la prima volta che
l’esecuzione del programma passa
attraverso la loro dichiarazione


Se non inizializzate esplicitamente, vengono
inizializzate a 0
Vengono usate quando il valore di una
variabile non deve andar perso alla fine
dell’esecuzione di una funzione ma deve
poter essere riutilizzabile
Esempio
int uso_frequente(int a) {
static int count;
count++;
if (count == 1000)
std::cout <<
"Complimenti, lei è il
millesimo cliente!" <<
std::endl;
return a * 3;
}
Ciclo di vita e visibilità delle
variabili statiche

Una variabile statica definita
all’interno di una funzione

Ha lo stesso ciclo di vita di una variabile
globale
 Viene
distrutta solo quando il programma
termina

Ha la stessa visibilità di una variabile
locale
Definizioni di namespace
I namespace (compreso il namespace
globale) possono contenere altri
namespace annidati
 Le entità definite in un namespace
sono membre del namespace


I nomi dei membri del namespace sono
composti da
<nome_namespace>::<nome_membro>


:: è l’operatore di scope
Ci si può riferire ai membri del namespace globale
con ::<nome_membro>
Esempi
int a1 = 3;
int f() {
int a = 3;
return ::a1 * a; // uso di una variabile del namespace globale
}
namespace n1 {
int a;
int g() {
// definzione dentro il namespace
return 2;
}
int h();
}
int n1::h() {
// definizione fuori dal namespace
return 3;
}
Uso dei namespace

Generalemente, in un programma si pongono


Le dichiarazioni dei membri di un namespace in un file
header
Le definizioni dei membri in un file di implementazione
Si possono utilizzare i mebri di un namespace
includendo l’header e utilizzando l’operatore di
scope
#include <iostream>
std::cout << “test1”;
 Si può rendere visibile un membro di un
namespace con la direttiva using
#include <iostream>
using std::cout;
cout << “test2”;

Uso dei namespcae (cont.)
Si possono rendere visibili tutti i membri di
un namespace con a direttiva using
namespace:
#include <iostream>
using namespace std;
cout << “test3”;
 Si può utilizzare un namespace tramite un
alias
#include <iostream>
namespace predefinito = std;
predefinito::cout << “test3”;

Scarica

Elementi di programmazione ad oggetti a. a. 2009/2001