Programmazione C · 15 min read · Oct 10, 2025
Imparare C/C++ Passo Dopo Passo - Pagina 13
13. Passo dopo passo C/C++ — Programmazione C++ - OOPs
OOP (Programmazione Orientata agli Oggetti) in C++
| | 1. Paradigma Orientato agli Oggetti
- Caratteristiche del Linguaggio Orientato agli Oggetti
- Oggetti
- Classi
- Astrazione dei dati
- Incapsulamento dei dati
- Ereditarietà
- Polimorfismo
- Binding dinamico
- Passaggio di messaggi
- Storia del C++
- Classi e Oggetti
- Funzioni membro definite al di fuori della classe
- Array di Oggetti
- Oggetti come Argomenti
- Restituire Oggetti dalle funzioni
- Costruttore
- Distruttori
- Overloading del Costruttore
- Dati di Classe Statici
- Funzioni Membro Statiche
- Funzioni Amiche |
1. Paradigma Orientato agli Oggetti
L’idea di base dietro il Paradigma Orientato agli Oggetti è quella di combinare in un’unica unità sia i dati che le funzioni che operano su quei dati. Tale unità è chiamata oggetto.
Attraverso questo metodo non possiamo accedere ai dati direttamente. I dati sono nascosti, quindi, sono al sicuro da modifiche accidentali. I dati e le loro funzioni sono detti essere incapsulati in un’unica entità. L’incapsulamento dei dati e la loro occultazione sono termini chiave nella descrizione del linguaggio orientato agli oggetti.
Un programma C++ tipicamente consiste in un numero di oggetti, che comunicano tra loro chiamando le funzioni membro l’uno dell’altro. L’organizzazione di un programma C++ è mostrata in questa figura.
| |
|
2. Caratteristiche del Linguaggio Orientato agli Oggetti
Ecco alcuni elementi principali dei linguaggi orientati agli oggetti.
| | - Oggetti
- Classi
- Astrazione dei dati
- Incapsulamento dei dati
- Ereditarietà
- Polimorfismo
- Binding dinamico
- Passaggio di messaggi |
| |
Oggetti
L’oggetto è un’istanza di una classe. Combina sia i dati che le funzioni membro. Gli oggetti sono le entità di runtime di base in un sistema orientato agli oggetti. | | |
Classi
Un modello o schema che definisce le caratteristiche di un oggetto e descrive come l’oggetto dovrebbe apparire e comportarsi. | | |
Astrazione dei Dati
Identificare le caratteristiche distintive di una classe o oggetto senza dover elaborare tutte le informazioni sulla classe o oggetto. Quando crei una classe — per esempio, un insieme di pulsanti di navigazione della tabella — puoi usarla come un’unica entità invece di tenere traccia dei singoli componenti e di come interagiscono. | | |
Incapsulamento dei Dati
Un termine di programmazione orientata agli oggetti per la capacità di contenere e nascondere informazioni su un oggetto, come strutture dati interne e codice. L’incapsulamento isola la complessità interna dell’operazione di un oggetto dal resto dell’applicazione. Ad esempio, quando imposti la proprietà Caption su un pulsante di comando, non è necessario sapere come viene memorizzata la stringa. | | |
Ereditarietà
Un termine di programmazione orientata agli oggetti. La capacità di una sottoclasse di assumere le caratteristiche della classe su cui si basa. Se le caratteristiche della classe genitore cambiano, la sottoclasse su cui si basa eredita quelle caratteristiche.
Per ereditare le qualità della classe base alla classe derivata. | | |
Polimorfismo
Un termine di programmazione orientata agli oggetti. La capacità di avere metodi con lo stesso nome, ma contenuto diverso, per classi correlate. La procedura da utilizzare è determinata a runtime dalla classe dell’oggetto. Ad esempio, oggetti correlati potrebbero avere entrambi metodi Draw. Una procedura, passata un tale oggetto come parametro, può chiamare il metodo Draw senza bisogno di sapere che tipo di oggetto è il parametro. | | |
Binding Dinamico
Dinamico si riferisce al collegamento di una chiamata di procedura al codice da eseguire in risposta alla chiamata. Il binding dinamico significa che il codice associato a una data chiamata di procedura non è noto fino al momento della chiamata a runtime. È associato al polimorfismo e all’ereditarietà. Una chiamata di funzione associata a un riferimento polimorfico dipende dal tipo dinamico di quel riferimento. | | |
Passaggio di Messaggi
Un programma orientato agli oggetti consiste in un insieme di oggetti che comunicano tra loro. Il processo di programmazione in un linguaggio orientato agli oggetti comporta quindi i seguenti passaggi di base:
- Creare classi che definiscono oggetti e il loro comportamento.
- Creare oggetti dalle definizioni delle classi.
- Stabilire comunicazione tra gli oggetti. |
3. Storia del C++
| Anno | Linguaggio | Sviluppato da | Osservazioni |
| 1960 | ALGOL | Comitato Internazionale | Troppo generale, Troppo astratto |
| 1963 | CPL | Università di Cambridge | Difficile da imparare, Difficile da implementare |
| 1967 | BCPL | Martin Richards | Poteva affrontare solo problemi specifici |
| 1970 | B | Ken Thompson AT & T Bell Labs | Poteva affrontare solo problemi specifici | | 1972 | C | Dennis Ritchie AT & T Bell Labs | Ha perso la generalità di BCPL e B ripristinata | | Inizio anni ‘80 | C++ | Bjarne Stroustrup AT & T | Introduce OOPs. |
C++ è un linguaggio di programmazione orientato agli oggetti. Inizialmente chiamato ‘C con Classi’, C++ è stato sviluppato da Bjarne Stroustrup presso i laboratori Bell di AT & T a Murry Hill, New Jersey, USA, nei primi anni ottanta.
Stroustrup, un ammiratore di Simula67 (un linguaggio OOP) e un forte sostenitore di C, voleva combinare il meglio di entrambi i linguaggi e creare una maggiore potenza ed eleganza di C. Il risultato è stato C++.
C++ è un vero Linguaggio Orientato agli Oggetti, quindi. Deve essere una collezione di classi e oggetti.
4. Classi e Oggetti
Una classe è un modo per legare i dati e le sue funzioni associate insieme. Permette ai dati di essere nascosti, se necessario, dall’uso esterno. Quando definiamo una classe, stiamo creando un nuovo tipo di dato astratto che può essere trattato come qualsiasi altro tipo di dato incorporato. Generalmente, una specifica di classe ha due parti:
| | 1. Dichiarazione della classe
- Definizione della funzione della classe |
La dichiarazione specifica il tipo e l’ambito sia dei dati che delle funzioni membro della classe. Mentre la definizione specifica il codice eseguibile della funzione.
La forma generale di una dichiarazione di classe è:
| | class class_name
{
private:
variabili dichiarazioni;
fuzione dichiarazioni;
public:
variabili dichiarazioni;
fuzione dichiarazioni;
}; |
La dichiarazione della classe è simile alla dichiarazione di struct. La parola chiave class specifica che i dati e le funzioni siano privati per impostazione predefinita. Mentre una parola chiave struct specifica che i dati e le funzioni siano pubblici per impostazione predefinita. Le parole chiave private e public sono conosciute come etichette di visibilità.
| |
|
Ecco un esempio di classe per implementare una classe dipendente.
| |
|
Il seguente è il programma completo della classe emp.
| | // Programma per accettare e visualizzare informazioni sui dipendenti
#include
using namespace std;
class emp // definizione della classe
{
private : // dati privati, funzioni
int eno;
char name[10];
float sal;
public : // dati pubblici, funzioni
void getdata()
{ cin >> eno >> name >> sal; }
void putdata()
{ cout << eno << name << sal; }
};
int main()
{
emp e;
e.getdata();
e.putdata();
return 0;
} |
5. Funzioni membro definite al di fuori della classe
C’è la possibilità di definire funzioni membro al di fuori della classe utilizzando l’operatore di risoluzione dell’ambito (::).
| | // Programma per accettare e visualizzare informazioni sui dipendenti
#include
using namespace std;
class emp // definizione della classe
{
private : // dati privati, funzioni
int eno;
char name[10];
float sal;
public : // dati pubblici, funzioni
void getdata();
void putdata();
};
void emp::getdata()
{ cin >> eno >> name >> sal; }
void emp::putdata()
{ cout << eno << name << sal; }
int main()
{
emp e;
e.getdata();
e.putdata();
return 0;
} |
6. Array di Oggetti
Il compilatore C++ supporta anche array di oggetti.
L’esempio seguente illustra il vantaggio degli Oggetti utilizzando array.
| | // Programma per accettare e visualizzare informazioni sui dipendenti
#include
using namespace std;
class emp // definizione della classe
{
private : // dati privati, funzioni
int eno;
char name[10];
float sal;
public : // dati pubblici, funzioni
void getdata()
{ cin << eno << name << sal; }
void putdata()
{ cout >> eno >> name >> sal; }
};
int main()
{
emp e[10]; // dichiarazione dell’array di oggetti
for(i = 0; i <10; i++) // accesso alle proprietà e ai metodi degli oggetti
e[i].getdata();
for(i = 0; i< 10; i++)
e[i].putdata();
return 0;
} |
7. Oggetti come Argomenti
Passare Oggetti a funzioni è simile a passare strutture, array a funzioni. Il seguente programma dimostra come gli oggetti vengono passati a funzioni.
| | // Programma per accettare e visualizzare informazioni sui dipendenti
#include
using namespace std;
class emp // definizione della classe
{
private : // dati privati, funzioni
int eno;
char name[10];
float sal;
public : // dati pubblici, funzioni
void getdata()
{ cin >> eno >> name >> sal; }
void putdata()
{ cout << eno << name << sal; }
};
void operate(emp t);
int main()
{
emp e;
operate(e);
}
void operate(emp t)
{
t.getdata();
t.putdata();
return 0;
} |
8. Restituire Oggetti dalle funzioni
Abbiamo visto oggetti passati come argomenti a funzioni, ora discuteremo su come restituire oggetti dalle funzioni.
| | // Programma per accettare e visualizzare informazioni sui dipendenti
#include
using namespace std;
class emp // definizione della classe
{
private : // dati privati, funzioni
int eno;
char name[10];
float sal;
public : // dati pubblici, funzioni
void getdata()
{ cin >> eno >> name >> sal; }
void putdata()
{ cout << eno << name << sal; }
};
emp get();
void put(emp t);
int main()
{
emp e;
e = get();
put(e);
return 0;
}
emp get()
{
emp t;
t.getdata();
return t;
}
void put(emp t)
{
t.putdata();
} |
9. Costruttore
Il seguente esempio mostra due modi per dare valori agli elementi dati in un oggetto. A volte, tuttavia, è conveniente se un oggetto può inizializzarsi quando viene creato per la prima volta, senza la necessità di effettuare una chiamata separata a una funzione membro.
L’inizializzazione automatica viene eseguita utilizzando una funzione membro speciale chiamata costruttore. Un costruttore è una funzione membro che viene eseguita automaticamente ogni volta che viene creato un oggetto.
| | // Programma per accettare e visualizzare informazioni sui dipendenti utilizzando costruttori
#include
#include
using namespace std;
class emp // definizione della classe
{
private : // dati privati, funzioni
int eno;
char name[10];
float sal;
public : // dati pubblici, funzioni
emp() { ; } // costruttore senza argomenti
emp(int teno, char tname[10], float tsal) // costruttore con argomenti
{
eno = teno;
strcpy(name, tname);
sal = tsal;
}
void getdata()
{ cin >> eno >> name >> sal; }
void putdata()
{ cout << eno << name << sal << endl; }
};
int main()
{
emp e1(1001, “Magic”, 6700.45);
emp e2;
e2.getdata();
e1.putdata();
e2.putdata();
return 0;
} |
L’esempio di programma sopra accetta valori in due modi utilizzando costruttori e utilizzando funzioni membro. Un oggetto, ogni volta che viene dichiarato, viene automaticamente inizializzato con i valori dati utilizzando costruttori. Mentre l’oggetto e2 è accessibile solo tramite la sua funzione membro.
Un altro esempio per distinguere l’uso del costruttore.
| | // Gli oggetti rappresentano una variabile contatore
#include
using namespace std;
class counter
{
private :
int count; // variabile count
pubilc :
counter() { count = 0; } // costruttore
void inc_count() { count++; } // incrementa count
int get_count() { return count; } // restituisce count
};
int main()
{
counter c1, c2; // definire e inizializzare
cout << “ C1 = “ << c1.get_count(); // visualizza
cout << “ C2 = “ << c2.get_count();
c1.inc_count(); // incrementa c1
c2.inc_count(); // incrementa c2
c2.inc_count(); // incrementa c2
cout << “ C1 = “ << c1.get_count(); // visualizza di nuovo
cout << “ C2 = “ << c2.get_count();
return 0;
} |
| | Un costruttore ha le seguenti caratteristiche.
- Inizializzazione automatica
- Valori di ritorno non accettati
- Stesso nome della classe
- Confusione con il formato |
10. Distruttori
Un distruttore ha lo stesso nome del costruttore (che è lo stesso del nome della classe) ma preceduto da una tilde:
| | // Dimostrazione di un distruttore
#include
using namespace std;
class temp
{
private :
int data;
public :
temp() { data = 0; } // Costruttore (stesso nome della classe)
~temp() { } // distruttore (stesso nome con tilde)
}
int main()
{
temp t;
return 0;
} |
11. Overloading del Costruttore
La capacità di avere funzioni con lo stesso nome, ma contenuto diverso, per classi correlate. La procedura da utilizzare è determinata a runtime dalla classe dell’oggetto.
| | // Dimostrazione di un overloading del costruttore
#include
using namespace std;
class ttime
{
private :
int hh, mm, ss;
public :
ttime() {hh = 0; mm = 0; ss = 0; } // Costruttore con inizializzazione
ttime(int h, int m, int s) // Costruttore con 3 argomenti
{
hh = h; mm = m ; ss = s;
}
ttime(int h, int m) // Costruttore con 2 argomenti
{
hh = h; mm = m; ss = 0;
}
ttime(int h) // Costruttore con 1 argomento
{
hh = h; mm = 0; ss = 0;
}
~ttime() { }
void get_time()
{
cin >> hh >> mm >> ss;
}
void put_time()
{
cout << endl << hh << “ “ << mm <<” “ << ss;
}
};
int main()
{
ttime t1, t2(12, 12, 12), t3(4, 5), t4(11); // Chiamata ai costruttori
t1.get_time();
t1.put_time();
t2.put_time();
t3.put_time();
t4.put_time();
return 0;
} |
12. Dati di Classe Statici
Se un elemento dati in una classe è definito come statico, allora viene creato solo un tale elemento per l’intera classe, indipendentemente da quanti oggetti ci siano. Un elemento dati statico è utile quando tutti gli oggetti della stessa classe devono condividere un elemento comune di informazione. Una variabile membro definita come static ha caratteristiche simili a una normale variabile statica: è visibile solo all’interno della classe, ma la sua durata è l’intero programma.
| | // Dimostrazione di un dato statico
#include
using namespace std;
class temp
{
private :
static int count; // Solo un elemento dati per tutti gli oggetti
public :
temp() { count++; } // incrementa count quando l’oggetto è creato
int getcount() { return count; } // restituisce count
};
int main()
{
temp t1, t2, t3; // crea tre oggetti
cout << “ Count è “ << t1.getcount( ); // ogni oggetto
cout << “ Count è “ << t2.getcount( ); // vede lo stesso
cout << “ Count è “ << t3.getcount( ); // valore di count
return 0;
} |
| | L’output del programma sopra è il seguente: (se è ancora statico)
Count è 3
Count è 3
Count è 3
L’output del programma sopra (se è automatico)
Count è 1
Count è 1
Count è 1 |
13. Funzioni Membro Statiche
Come la variabile membro statica, possiamo anche avere funzioni membro statiche. Una funzione membro dichiarata statica ha le seguenti proprietà.
| | - Una funzione statica può avere accesso solo ad altri membri statici (funzioni o variabili) dichiarati nella stessa classe.
- Una funzione membro statica può essere chiamata utilizzando il nome della classe (invece dei suoi oggetti) come segue:
class-name :: function-name;
|
| | // Programma per dimostrare la funzione membro statica
#include
using namespace std;
class test
{
int code ;
static int count; // variabile membro statica
public:
void setcode() { code = ++count; }
void showcode() { cout << “Numero oggetto :” << code << endl; }
static void showcount() // funzione membro statica
{
cout << “Count :” << count << endl;
}
};
int test :: count;
int main()
{
test t1, t2;
t1.setcode();
t2.setcode();
test::showcount(); // accesso alla funzione statica
test t3;
t3.setcode();
test::showcount();
t1.showcode();
t2.showcode();
t3.showcode();
return 0;
} |
14. Funzioni Amiche
| |
|
I membri privati non possono essere accessibili dall’esterno della classe. Cioè, una funzione non membro non può avere accesso ai dati privati di una classe. Tuttavia, potrebbe esserci una situazione in cui vorremmo che due classi condividessero una particolare funzione. Questo è semplicemente realizzato attraverso le funzioni Amiche.
| | Una funzione amica possiede alcune caratteristiche speciali: - Non è nell’ambito della classe a cui è stata dichiarata come amica.
- Poiché non è nell’ambito della classe, non può essere chiamata utilizzando l’oggetto della classe. Può essere invocata come una normale funzione senza l’aiuto di alcun oggetto.
- A differenza delle funzioni membro, non può accedere direttamente ai nomi dei membri e deve utilizzare un nome di oggetto e l’operatore di appartenenza a punto con ogni nome membro.
- Può essere dichiarata sia nella parte pubblica che in quella privata di una classe senza influenzare il suo significato.
- Di solito, ha gli oggetti come argomenti. |
| | // Programma per dimostrare la funzione amica
#include
using namespace std;
class test
{
int a;
int b;
public:
void setvalue() { a = 25; b = 40; }
friends float sum(test s); // AMICO dichiarato
};
float sum(test s)
{
return float (s.a + s.b ) / 2.0; // s.a & s.b sono i membri privati
// della classe test ma erano accessibili
// dalla funzione amica
}
int main()
{
test x;
x.setvalue();
cout << “Valore medio = “ << sum(x) << endl;
return 0;
} |
Un altro esempio per implementare una funzione amica come ponte tra due classi.
Il seguente programma crea due oggetti di due classi e una funzione amica a due classi.
In questo esempio, la funzione amica è in grado di accedere ai membri dati di entrambe le classi e calcola il più grande dei membri dati di entrambe le classi.
| | #include
using namespace std;
class second;
class first
{
int a;
public:
first(int temp) { a = temp; }
friends void max(first, second);
};
class second
{
int b;
public:
second(int temp) { b = temp; }
friends void max(first, second);
};
void max(first f, second s)
{
if ( f.a > s.b ) // entrambi i membri dati di first, second possono essere
cout << “Max “<< f.a; // accessibili tramite la funzione amica max
else
cout << “Max “<< s.b;
}
int main()
{
first f(20);
second s(30);
max(f, s);
return 0;
} |
Rif: Programmazione Orientata agli Oggetti in Turbo C++: Robert Lafore
Ricevi i nuovi post nella tua casella di posta.
Nessuno spam. Disiscriviti in qualsiasi momento.