Esercitazioni LPS
Da Bioingegneria Elettronica e Informatica.
Indice
Esercitazione del 2 e 15 maggio 2019
// questo è un commento a linea singola in puro stile C++
// la programmazione ad oggetti supporta //
// l'incapsulamento
// il polimorfismo
// l'ereditarietà
// esempio di incapsulamento: dati e funzioni in un oggetto
// esempio di polimorfismo a compile time: overloading di funzioni
// esempio di ereditarietà: classe persona e classe studente
// esempio di costruttore per inizializzare variabili a valori di default
// un oggetto è una istanza di una classe
// include la necessaria intestazione <iostream>
#include <iostream>
// l'istruzione using informa il compilatore che intende utilizzare il namespace standard
using namespace std;
// i namespace creano delle regioni di dichiarazione
// nel namespace standard viene dichiarata l'intera libreria standard del C++
// Creazione della classe persona
// una classe può contenere attributi (variabili) e metodi (funzioni) privati, protetti e pubblici
// per ora prevediamo soltanto attributi privati e metodi pubblici
class persona {
private: //private è pleonastico (si può omettere)
int IDP;
// IDP in quanto variabile privata non risulta visibile da funzioni che non siano metodi della classe persona
public:
void leggiIDP();
void leggiIDP(int);
void stampaIDP();
// segue la funzione costruttore, omonima della classe, e nella cui dichiarazione non si specifica il valore restituito
persona();
// segue la funzione costruttore overloadata con un parametro
persona(int);
// segue la funzione distruttore, omonima della classe ma preceduta dal TILDE, e nella cui dichiarazione non si specifica il valore restituito
~persona();
};
class studente : public persona {
private:
int IDS;
public:
void leggiIDS();
void stampaIPDS();
studente();
~studente();
};
void persona::leggiIDP()
{
cin >> IDP;
}
void persona::leggiIDP(int A)
{
IDP = A;
}
void persona::stampaIDP()
{
cout << IDP << endl;
// endl per andare a capo
}
persona::persona()
{
cout << "Persona costruita " << endl;
IDP = 0;
}
persona::persona(int A)
{
cout << "Persona costruita con parametro passato per valore " << endl;
IDP = A;
}
persona::~persona()
{
cout << "Persona distrutta " << endl;
}
studente::studente()
{
cout << "Studente costruito " << endl;
IDS = 0;
}
studente::~studente()
{
cout << "Studente distrutto " << endl;
}
void studente::leggiIDS()
{
cin >> IDS;
}
void studente::stampaIPDS()
{
cout << "Identificativo studente pari a " << IDS << endl;
}
// verificare il sorgente modificato ...
int main()
{
persona P, Q(3);
studente S; // verifica della chiamata del costruttore di persona senza parametri
// P.IDP=2; errore cannot access private member
P.stampaIDP();
P.leggiIDP();
P.stampaIDP();
Q.stampaIDP();
Q.leggiIDP(2);
Q.stampaIDP();
S.leggiIDP();
S.stampaIDP();
S.leggiIDS();
S.stampaIPDS();
// Decommentare su visual studio
// system("pause");
return 0;
}
Funzioni virtuali
#include <iostream>
using namespace std;
class Base
{
public:
virtual void stampa() {
cout << "Metodo stampa della classe Base" << endl;
}
};
class DerivataUno : public Base
{
public:
void stampa() {
cout << "Metodo stampa della classe DerivataUno" << endl;
}
};
class DerivataDue : public Base
{
public:
void funzione() {
cout << "Funzione specifica della classe DerivataDue" << endl;
}
};
int main()
{
Base b, *p;
DerivataUno d1;
DerivataDue d2;
p = &b;
// Richiamata la funzione stampa della classe Base
p->stampa();
p = &d1;
// Richiamata la funzione stampa della classe DerivataUno
p->stampa();
p = &d2;
// Richiamata la funzione stampa della classe Base
p->stampa();
// Richiama il metodo specifico della classe DerivataDue ->
// -> cast a punatatore di tipo classe derivata
((DerivataDue*)p)->funzione();
system("pause");
}
Funzioni virtuali pure e Classi Astratte
#include <iostream>
#include <cmath>
using namespace std;
class Figura
{
// Classe Astratta: contiene almeno una funzione virtuale pura
protected:
double perimetro;
double area;
public:
Figura() { perimetro = 0; area = 0; }
virtual void calcolaPerimetro() = 0; // Funzione virtuale pura
virtual void calcolaArea() = 0; // Necessario ridefinire i metodi virtuali puri nelle classi derivati, altrimenti errore in compilazione
};
class Triangolo : public Figura
{
private:
// Dimensione dei tre lati
double l1, l2, l3;
public:
Triangolo(double L1, double L2, double L3) {
l1 = L1; l2 = L2; l3 = L3;
}
void calcolaPerimetro() {
perimetro = l1 + l2 + l3;
cout << "Il perimetro del Triangolo con lati " <<
l1 << " " << l2 << " e " << l3 << " vale: " << perimetro << endl;
}
// Calcolo area con formula di Erone
void calcolaArea() {
double p = (l1 + l2 + l3) / 2;
area = sqrt(p*(p - l1)*(p - l2)*(p - l3));
cout << "L'area del Triangolo con lati " <<
l1 << " " << l2 << " e " << l3 << " vale: " << area << endl;
}
};
class Rettangolo : public Figura
{
private:
// Dimensione di base e altezza
double l1, l2;
public:
Rettangolo(double L1, double L2) {
l1 = L1; l2 = L2;
}
void calcolaPerimetro() {
perimetro = 2*(l1 + l2);
cout << "Il perimetro del Rettangolo con lati " << l1 << " e " << l2 << " vale: " << perimetro << endl;
}
void calcolaArea() {
area = l1 * l2;
cout << "L'area del Rettangolo con lati " << l1 << " e " << l2 << " vale: " << area << endl;
}
};
class Cerchio : public Figura
{
private:
// Dimensione del raggio
double l1;
public:
Cerchio(double L1) {
l1 = L1;
}
void calcolaPerimetro() {
perimetro = 3.14 * 2 * l1;
cout << "La circonferenza del cerchio con raggio " << l1 << " vale: " << perimetro << endl;
}
void calcolaArea() {
area = 3.14 * l1 * l1;
cout << "L'area del cerchio con raggio " << l1 << " vale: " << area << endl;
}
};
int main()
{
Figura f; // Errore: non è consentito istanziare oggetti di tipo classe astratta
Figura *f1;
Triangolo t1(10.3, 9, 18.3);
Rettangolo r1(10, 3.5);
Cerchio c1(10);
f1 = &t1;
f1->calcolaPerimetro();
f1->calcolaArea();
f1 = &r1;
f1->calcolaPerimetro();
f1->calcolaArea();
f1 = &c1;
f1->calcolaPerimetro();
f1->calcolaArea();
system("pause");
return 0;
}
Costruttore di copia di un vettore
#include <iostream>
#include <new>
#include <cstdlib>
using namespace std;
// ATTENZIONE: in ambiente Visual Studio avviare senza eseguire Debug (CTRL+F5)
// N.B. quando si esegue una copia i due oggetti sono identici bit a bit,
// quando però la inizializzazione comporta l'allocazione di memoria non deve
// essere fatta una copia bit a bit
// Questo programma crea una classe per array "sicuri"
class vettore
{
int *p;
int dimensione;
public:
vettore(int dim)
{
cout << "costruzione" << endl;
p = new int[dim];
dimensione = dim;
}
~vettore() { delete[] p; cout << "distruzione" << endl; }
// costruttore di copie
vettore(const vettore &vett);
void imposta(int i, int j)
{
if (i >= 0 && i <dimensione)
p[i] = j;
}
int prendi(int i)
{
return p[i];
}
};
// Costruttore di copie
vettore::vettore(const vettore &vett)
{
int i;
p = new int[vett.dimensione];
cout << "costruttore di copie" << endl;
for (i = 0; i<vett.dimensione; i++)
p[i] = vett.p[i];
}
int main()
{
vettore num(10);
int i;
for (i = 0; i<10; i++) num.imposta(i, i);
for (i = 9; i >= 0; i--) cout << num.prendi(i);
cout << "\n";
// i vettori num e x contengono gli stessi valori ma ciascun vettore
// si trova in aree diverse di memoria
// crea un altro vettore e lo inizializza con num
vettore x(num); // richiama il costruttore di copie;
for (i = 0; i<10; i++) cout << num.prendi(i);
cout << "\nciao\n";
return 0;
}
/*
costruzione
9876543210
costruttore di copie
0123456789
ciao
distruzione
distruzione
Press any key to continue
*/
Costruttore di copia di una matrice
#include <iostream>
#include <new>
#include <cstdlib>
using namespace std;
// ATTENZIONE: in ambiente Visual Studio avviare senza eseguire Debug (CTRL+F5)
// N.B. quando si esegue una copia i due oggetti sono identici bit a bit,
// quando però la inizializzazione comporta l'allocazione di memoria non deve
// essere fatta una copia bit a bit
// Questo programma crea una classe per array bidimensionali "sicuri"
class matrice
{
int **p;
int dimRighe;
int dimColonne;
public:
matrice(int r, int c)
{
cout << "Costruzione matrice e inizializzazione degli elementi a zero" << endl;
dimRighe = r;
dimColonne = c;
p = new int *[r];
for (int i = 0; i < dimRighe; i++) {
p[i] = new int[dimColonne];
}
int i, j;
for (i = 0; i < dimRighe; i++) {
for (j = 0; j < dimColonne; j++) {
p[i][j] = 0;
}
}
cout << endl;
}
~matrice() {
for (int i = 0; i < dimRighe; i++) {
delete[] p[i];
}
delete[] p;
cout << "Distruzione della matrice creata nel main alla fine del main" << endl;
}
// costruttore di copie
matrice(const matrice &mat);
void stampa() {
cout << "Stampa elementi matrice: " << endl;
int i, j;
for (i = 0; i < dimRighe; i++) {
cout << endl;
for (j = 0; j < dimColonne; j++) {
cout << p[i][j];
}
}
cout << endl << endl;
}
void modificaMatrice() {
cout << "Modifica elementi matrice ( +1 ): " << endl;
int i, j;
for (i = 0; i < dimRighe; i++) {
for (j = 0; j < dimColonne; j++) {
p[i][j] = p[i][j] + 1;
}
}
cout << endl;
}
};
// Costruttore di copie
matrice::matrice(const matrice &mat)
{
cout << "Costruttore di copie della matrice" << endl;
dimRighe = mat.dimRighe;
dimColonne = mat.dimColonne;
p = new int *[dimRighe];
for (int i = 0; i < dimRighe; i++) {
p[i] = new int[dimColonne];
}
int i, j;
for (i = 0; i < dimRighe; i++) {
for (j = 0; j < dimColonne; j++) {
p[i][j] = mat.p[i][j];
}
}
cout << endl;
}
int main()
{
matrice m1(2,3);
m1.stampa();
matrice m2(m1);
m2.stampa();
m1.modificaMatrice();
m1.stampa();
return 0;
}
/*
Costruzione matrice e inizializzazione degli elementi a zero
Stampa elementi matrice:
000
000
Costruttore di copie della matrice
Stampa elementi matrice:
000
000
Modifica elementi matrice ( +1 ):
Stampa elementi matrice:
111
111
Distruzione della matrice creata nel main alla fine del main
Distruzione della matrice creata nel main alla fine del main
Premere un tasto per continuare . . .
*/
Lettura e Scrittura di un file binario
#include <iostream>
#include <new>
#include <cstdlib>
#include <fstream>
using namespace std;
// Esempio di lettura/scrittura di un vettore di interi da/su file binario
class vettore
{
private:
int *p;
int dimensione;
public:
vettore(int dim)
{
// costruzione di un vettore di dimensione dim
dimensione = dim;
p = new int[dimensione];
}
vettore(const vettore &vett);
void generaRandom() {
// inizializzazione con elementi random nell'intervallo [1,100]
for (int i = 0; i < dimensione; i++)
p[i] = rand() % 100 + 1;
}
void inserisci() {
// inizializzazione con elementi inseriti manualmente
for (int i = 0; i < dimensione; i++) {
cout << "Inserisci elemento " << i << ":" << endl;
cin >> p[i];
}
}
void imposta(int *arr) {
// inizializzazione con elementi di un array
for (int i = 0; i < dimensione; i++)
p[i] = arr[i];
}
void stampa() {
// stampa elementi del vettore
for (int i = 0; i < dimensione; i++)
cout << p[i] << " ";
cout << endl;
}
void salvaSuFileBin() {
//apre il file binario in scrittura
ofstream fileBinario("binario.dat", ios::binary);
//scrive l'array di elementi
fileBinario.write((char*)p, sizeof(int)*dimensione);
// scrivo la dimensione del vettore
fileBinario.write((char*)&dimensione, sizeof(int));
// chiudo il file
fileBinario.close();
}
~vettore() {
// distruzione vettore di interi allocato
delete[] p;
}
};
vettore::vettore(const vettore &vett)
{
dimensione = vett.dimensione;
int i;
p = new int[vett.dimensione];
cout << "Costruttore di copie" << endl;
for (i = 0; i<vett.dimensione; i++)
p[i] = vett.p[i];
}
vettore leggiDaFileBin();
int main()
{
int numInteri;
cout << "Quanti interi conterra' il file binario?" << endl;
cin >> numInteri;
cout << "Generazione file binario con " << numInteri << " interi." << endl;
vettore v1(numInteri);
v1.generaRandom();
//v1.inserisci();
v1.stampa();
v1.salvaSuFileBin();
vettore v2 = leggiDaFileBin();
v2.stampa();
return 0;
}
vettore leggiDaFileBin() {
int numInteri;
//apre il file binario in lettura
ifstream fileBinario("binario.dat", ios::binary);
// posiziono il puntatore di lettura in modo da leggere l'ultimo intero scritto sul file
fileBinario.seekg(-4, ios::end);
// leggo l'intero
fileBinario.read((char*)&numInteri, sizeof(int));
// creo un array di interi per contenere tutti gli elementi sul file
int *arr = new int[numInteri];
// riposiziono il puntatore di lettura all'inizio del file
fileBinario.seekg(0);
// leggo l'array di interi intero
fileBinario.read((char *)arr, sizeof(int)*numInteri);
// chiudo il file
fileBinario.close();
vettore v(numInteri);
v.imposta(arr);
return v;
}