Il 0% ha trovato utile questo documento (0 voti)
4 visualizzazioni

Fdocumenti.com Corso c

Caricato da

Gaetano Scorsone
Copyright
© © All Rights Reserved
Formati disponibili
Scarica in formato PDF, TXT o leggi online su Scribd
Il 0% ha trovato utile questo documento (0 voti)
4 visualizzazioni

Fdocumenti.com Corso c

Caricato da

Gaetano Scorsone
Copyright
© © All Rights Reserved
Formati disponibili
Scarica in formato PDF, TXT o leggi online su Scribd
Sei sulla pagina 1/ 68

C++

Antonio Furone
Febbraio 2000
C++ Linguaggio OO

•Le classi Estende le caratteristiche del C


fornendo i meccanismi per

•Proprietà e metodi l'astrazione dei dati e la


programmazione orientata agli
oggetti.
•Gli oggetti
•L’ereditarietà
•Simula
• Smalltalk •Incapsulamento
• C++ •Overloading
• Visual Basic
• Java •Polimorfismo
•Persistenza
C++ Inoltre...

• E’ un linguaggio “all purpose”;


• Mantiene una compatibilità “quasi completa” con il C;
• Porting agevole delle applicazioni;

Svantaggi:

• Maggiore sforzo nella progettazione delle applicazioni;


• Complessità del linguaggio
C++ Hello World

#include "stdafx.h"
#include < iostream.h >

int main(int argc, char* argv[])


{
cout << "Hello World !!!" << endl;
return 0;
}

•“” : stessa directory, /I (opzione di compilazione) , INCLUDE;


•<>: /I, INCLUDE;
C++ Il Linguaggio

void Func() { ...

// questo è un commento su un’unica riga


Commenti
int a = 5; /* questo e` un commento

diviso su piu` righe */

a = 4 /* commento */ + 5;

... }
Gli identificatori sono simboli definiti dal
programmatore per riferirsi a cinque diverse categorie
Identificatori di oggetti:

•Variabili;
•Costanti simboliche;
•Etichette;
•Tipi definiti dal programmatore;
•Funzioni.
C++ Il Linguaggio

Parole riservate:

Sono inoltre considerate parole chiave tutte quelle che iniziano con un doppio underscore
__; esse sono riservate per le implementazioni del linguaggio e per le librerie standard, e il
loro uso da parte del programmatore dovrebbe essere evitato in quanto non sono portabili.
C++ Il Linguaggio

Tipi primitivi:
Un tipo e` una coppia <V, O>, dove V e` un insieme di valori e O e` un insieme
di operazione per la creazione e la manipolazione di elementi di V. I quattro tipi
fondamentali del C++:

•char :utilizzato per rappresentare piccoli interi e caratteri;


•int :per numeri interi in un intervallo più ampio di char;
•float :numeri a virgola mobile a singola precisione;
•double :numeri a virgola mobile a doppia precisione;
C++ Il Linguaggio: Tipi Primitivi

Ai tipi fondamentali e` possibile applicare i qualificatori


signed, unsigned, short e long per selezionare differenti
intervalli di valori:
signed long int
char
unsigned char
short int
unsigned short int
int
unsigned int
long int
unsigned long int
signed char
float
signed short int •Esercitazione sulla
double
signed int dimensione(in byte) dei
long double vari tipi (sizeof operator).
Il Linguaggio:
C++ Dichiarazione di Variabili

short int s1,s2,s3=5;


int s2=5555;
char a=‘c’;
char c3=c1+1;

All'interno delle espressioni e` possibile inserire direttamente dei valori,


questi valori sono detti costanti letterali: ‘a’ // carattere “abc” // stringa

20 // intero in base 10 .0 // 0 in virgola mobile


024 // 20 in base 8 110E+4 // equivalente a 110 * 10000 (10 elevato a 4)
.14e-2 // 0.0014
0x14 // 20 in base 16 -3.5e+3 // -3500.0
3.5f // forza float
12ul // forza unsigned long
3.4L // forza long double
12l // forza long

12u // forza unsigned


Il Linguaggio:
C++ Caratteri Speciali

Nome ASCII Carattere


A capo NL \n
Tab orizzontale HT \t
Tab verticale VT \v
Spazio indietro BS \b
Ritorno carrello CR \r
Form feed FF \f
Campanello BEL \a
Slash \ \\
Apice ‘ \’
C++ Il Linguaggio: Operatori

Gli operatori sono raggruppati per tipologia e ordinati per precedenza di valutazione
C++ Il Linguaggio: Operatori

•Gli operatori unari e quelli di assegnamento sono associativi


a destra, gli altri a sinistra;
•L'operatore ? : e` l'unico operatore ternario:
s1>0?y=x+1:y=x-1; // <Cond> ? <Expr2> :<Expr3>
• = (assegnamento):un programma C++ e` sostanzialmente
una sequenza di assegnamenti di valori a variabili del tipo:
lvalue=rvalue;
Il termine lvalue indica una qualsiasi espressione che riferisca
ad una regione di memoria (in generale un identificatore di
variabile), mentre un rvalue e` una qualsiasi espressione la
cui valutazione produca un valore.
C++ Il Linguaggio:Operatori
Pluto = Pippo = 5;

equivale a
Pluto = (Pippo = 5);

Concatenazione di operatori binari:


Pippo += 5;// equivale a Pippo = Pippo + 5;
Pippo -= 10;// equivale a Pippo = Pippo -
10;
Pippo *= 3;// equivale a Pippo = Pippo * 3;
Operatori di autoincremento e autodecremento:
Pippo++; // Pippo += 1;
++Pippo; // Pippo += 1;
Pippo--; // Pippo -= 1;
--Pippo; // Pippo -= 1;

Pluto = ++Pippo;// equivale a:Pippo++;Pluto = Pippo;


Pluto = Pippo++;// equivale a:Pluto = Pippo;Pippo++;
C++ Il Linguaggio:Input e Output

int main(int argc, char* argv[])


{
double valore;
cout << "Digita un numero:" ;
cin >> valore;
cout << "Hai battuto:" << valore << endl;
return 0;
}

extern ostream cout;


extern istream cin;
C++ Il Linguaggio:Controllo del flusso

if ( <Condizione> ) <Blocco1> ; IF-ELSE


else <Blocco2> ;

while ( <Condizione> ) <Blocco> ; WHILE

do <Blocco> while ( <Condizione> ) ; DO-WHILE

for ( <Inizializzazione> ; <Condizione> ; <Iterazione> )


<Blocco>

FOR
C++ Il Linguaggio:Controllo del flusso

Fattoriale = 1; BREAK & CONTINUE


while (1) { // all'infinito...
if (InteroPositivo > 1) {
Fattoriale *=Interopositivo--;
continue;
}
break; // se eseguita allora InteroPositivo <= 1
// continue provoca un salto in questo punto
}

switch ( <Espressione> )
SWITCH
{
case <Valore1>: <Blocco> ; /* ... */
case <ValoreN> : <Blocco> ;
default : <Blocco> ;
}
C++ Il Linguaggio:Controllo del flusso

<Etichetta> : <Istruzione>
GOTO
...

goto <Etichetta>

COSTANTI

const double pi=3.1415926;


C++ Il Linguaggio: Scope e lifetime
{ ... int X = 5;
{ // X e` visibile anche in questo blocco ...
}

}
{ ...
int X = 5;
{
char X = 'a'; // ora e` visibile char X …
}
// qui e` visibile int X

}
C++ Il Linguaggio: Scope e lifetime

int X = 4; // dichiarazione esterna ad ogni blocco


void main()
{
}

void funz()
{
int x = 5; // x e` creata e distrutta ogni volta
static int c = 3; /* ... */
}
La variabile c è creata la prima volta
che si esegue la funzione e distrutta
alla fine del programma.
C++ Il Linguaggio: Array

< Tipo > < Identificatore >[ < NumeroElementi > ];


int Pippo[10];
long double Qui[3][4]; Il Tipo può essere anche un tipo
definito dall’utente (astratto).
int SuperPippo[12][16][20];
int Pippo[5] = { 10, -5, 6, 110, -96 };
short Pluto[2][4] = { 4, 7, 1, 4, 0, 3, 5, 9 );
float Minni[ ] = { 1.1, 3.5, 10.5 };
long Manetta[ ][3] = { 5, -7, 2, 1, 0, 5 };
char Topolino[ ] = "investigatore" ; // ‘\0’

Topolino[4] = 't'; // assegna 't' al quinto elemento


C++ Il Linguaggio: Strutture

struct < NomeTipo > struct Persona


{ {
< Tipo > < NomeCampo > ; char Nome[20];
... unsigned short Eta;
< Tipo > < NomeCampo > ; char CodiceFiscale[16+1];
}; };

Persona Pippo = { "Pippo", 40, "PPP718F444E18DR0" };


Pippo.Eta = 41;
Persona Pluto=Pippo;
C++ Il Linguaggio: Union
union TipoUnione {
unsigned Intero;
char Lettera;
char
Stringa[500]; };

Mentre in una struttura i vari campi vengono memorizzati in indirizzi diversi e


non si sovrappongono mai, in una unione invece tutti i campi vengono
memorizzati a partire dallo stesso indirizzo. Cio` vuol dire che, mentre la
quantita` di memoria occupata da una struttura e` data dalla somma delle
quantita` di memoria utilizzata dalle singole componenti, la quantita` di
memoria utilizzata da una unione e` data da quella della componente piu`
grande (Stringa in questo caso). Dato che le componenti si sovrappongono,
assegnare un valore ad una di esse vuol dire distruggere i valori memorizzati
accedendo all'unione tramite una qualsiasi altra componente.
C++ Il Linguaggio:Enumerazioni

enum < NomeTipo > enum Elemento


{ {Idrogeno, Elio,
< Identificatore >,
/* ... */ Carbonio, Ossigeno };
< Identificatore >
};
enum Elemento
{ Idrogeno = 2,
Elio, Carbonio = Idrogeno - 10,

Ferro = Elio + 7, Ossigeno = 2 };

Elemento Atomo = Idrogeno;


int Numero = Carbonio; // Ok!
Non esiste l’operatore di conversione da int
Atomo = 3; // Errore!
a Elemento.
C++ Il Linguaggio:Typedef

Permette di dichiarare un alias per un altro tipo (non un


nuovo tipo):

typedef < Tipo > < Alias > ;

typedef unsigned short int PiccoloIntero;


typedef long double ArrayDiReali[20];

typedef struct { long double ParteReale;


long double ParteImmaginaria;} Complesso;
C++ Il Linguaggio:Le funzioni

int Sum(int a, int b); Dichiarazione di una funzione (.h)


int Sum(int x, int y)
Implementazione di una
{ return x+y; }
funzione (.cc,.cxx,.cpp)

Passaggio di parametri int Sum (int a = 0, int b = 0);


int Sum (const int a ,int b);
per riferimento:
void scambia(int & a,int & b);

inline void scambia(int &x,int &y)


{
... funzioni inline
}
Il Linguaggio: Overloading di
C++ Funzioni

int Sum(int a, int b);


float Sum(float a, int b);

float Sum(int a, float b);

Il compilatore si basa univocamente sui tipi di parametri


in input, quindi non si può avere:

void Foo(int a, float f);


int Foo(int a, float f);
C++ Il Linguaggio: I puntatori

I puntatori possono essere pensati come maniglie da applicare alle porte delle
celle di memoria per poter accedere al loro contenuto sia in lettura che in
scrittura, nella pratica una variabile di tipo puntatore contiene l'indirizzo di una
locazione di memoria.
Vediamo alcune esempi di dichiarazione di puntatori:
short * p1; void * PuntatoreGenerico;
Persona * p2;
I puntatori void possono essere
double * * p3; inizializzati come un qualsiasi altro
puntatore tipizzato, e a differenza di
questi ultimi possono puntare a
int UnIntero = 5; qualsiasi oggetto senza riguardo al tipo
o al fatto che siano costanti, variabili o
int * PuntatoreAInt =
funzioni; tuttavia non e` possibile
&UnIntero; eseguire sui puntatori void alcune
operazioni definite sui puntatori
Puntatore = 0;//non punta a
tipizzati.
nulla (NULL)
C++ Il Linguaggio: I puntatori

int y=5; * = operatore che deferenzia


int *x=0; //NULL
x=&y; un puntatore (non è applicato
solo in fase di dichiarazione).

Persona Pippo;
Persona * Puntatore = &Pippo;
Puntatore -> Eta = 40;
-> = deferenzia e
automaticamente seleziona il
campo Eta.

Atri operatori: +,-,>,<,>=,<=,==,!=


Il Linguaggio: Puntatori vs
C++ Array

Un array (inteso come l’identificatore utilizzato per


“referenziarlo”) non è altro che il puntatore al primo
elemento dell’array.

int a[3]={1,2,3};
int *p=0;
p=&a[0];

if (p==a)
cout << "Vera" << endl;
C++ Il Linguaggio: Reference

I reference (riferimenti) sono un costrutto a meta` tra puntatori e


variabili: come i puntatori essi sono contenitori di indirizzi, ma non e`
necessario dereferenziarli per accedere all'oggetto puntato (si usano
come se fossero variabili).
int Var = 5;
float f = 0.5;
int * IntPtr = &Var;
int & IntRef = Var; // nei reference non e` necessario
float & FloatRef = f; // usare & a destra di =

int * IntPtr = new int(5);


int & IntRef = *IntPtr;
C++ Il Linguaggio: Reference

int *p; double & Esempio(float p1,


p=new int[2]; float p2);
*p=1;
*(p+1)=2; double * Esempio(float p1,
float p2);
int &r=*p;
for (int i=0;i<2;i++)
cout << r+i << endl;

//delete p;
delete &r;
Una funzione può restituire sia un
puntatore che un reference.
int &r=*new int[2];
C++ Il Linguaggio: Puntatori vs
Reference
int x=5; int &somma(int *x,int y)
int *px=&x; { int *z=new int;
int &z=somma(px,x); *z=*x+y;
return *z;
}
C++ Il Linguaggio: Linkage

In C++ l'unita` di compilazione e` il file. Un programma puo` consistere


di piu` file che vengono compilati separatamente e poi linkati (collegati)
insieme per ottenere un file eseguibile. Quest'ultima operazione e` svolta
dal linker e possiamo pensare al concetto di linkage sostanzialmente
come a una sorta di scope dal punto di vista del linker.
// File b.cpp
// File a.cpp
int a = 5; extern int a; int GetVar()

{ return a; }

// File a.cpp
// File b.cpp
int a = 5;
extern int f(int);
int f(int c)
int GetVar()
{ return a+c; }
{ return f(5); }
C++ Il Linguaggio: Linkage

// Contenuto file C++


extern "C" int CFunc(char *);

extern "C" char * CFunc2(int);

In questo modo attraverso la extern è possibile linkare un


modulo C ad un modulo C++.
C++ Il Linguaggio: Header

// Esempio.h
enum Color { Red, Green, Blue };
struct Point {
float X;
float Y; L'uso dei file header e` molto utile
}; quando si vuole partizionare un
programma in piu` moduli.
const int Max = 1000; Tuttavia la potenza dei file header
si esprime meglio quando si vuole
realizzare (o utilizzare) una
inline int Sum(int x, int y) { libreria di funzioni.
return x + y;
}
// Modulo1.cpp

#include "Esempio.h"
C++ OOP

La programmazione orientata agli oggetti (OOP) impone una nuova visione di


concetti quali "Tipo di dato" e "Istanze di tipo". Sostanzialmente mentre gli altri
paradigmi di programmazione vedono le istanze di un tipo di dato come una
entita` passiva (solo dati), nella programmazione a oggetti invece tali istanze
diventano a tutti gli effetti entita` (oggetti) attive.
L'idea e` che non bisogna piu` manipolare direttamente i valori di una struttura
(intesa come generico contenitore di valori), meglio lasciare che sia la struttura
stessa a manipolarsi e a compiere le operazioni.

Un’entità attiva viene dichiarata tramite una dichiarazione di classe.


C++ Le Classi

class <ClassName> Dichiarazione di una classe


{
public: <membri pubblici>
protected: <membri protetti>

private: <membri privati> };

•Se la dichiarazione di una proprietà non è inserita in


alcuna sezione è private per default;

•I metodi possono essere implementati sia nella


dichiarazione della classe che in un secondo momento;
C++ Le Classi

#include <iostream.h>
Esempio:
class MyClass
{
private:
void MioMetodoPrivate(const int i)
{
cout << "MioMetodoPrivate" << endl;
h }
public:
void MioMetodoPublic(const int i);
protected:
};
this
#include "stdafx.h"
#include "MyClass.h"

void MyClass::MioMetodoPublic(const int x)


{
cpp
cout << "MioMetodoPublic" << endl;
}
C++ Le Classi

Costruttori: Metodo richiamato alla creazione dell’istanza


di una classe. E’ utilizzato per rendere consistente lo stato
dell’istanza.

public:
...
MyClass();
MyClass(const int i);
MyClass(MyClass& x) : M1(x.M1), M2(x.M2) {...} //copia
MyClass(int a, int b) : M1(a), M2(b) {...} // lista
// inizializzaz.ne
...

MyClass c; // !!! La classe e instanziata


MyClass c(3);
MyClass c(x); MyClass &r=*new MyClass(x);
MyClass *p=new MyClass(x);
C++ Le Classi

Distruttore:Poiche` ogni oggetto ha una propria durata


(lifetime) e` necessario disporre anche di un metodo che
permetta una corretta distruzione dell'oggetto stesso, un
distruttore.
~MyClass();
...
MyClass::~MyClass()
{
...
}

E’ un metodo che non ricerve parametri e non ritorna alcun


tipo (neanche void).
C++ Le Classi

Membri Static : Membri propri della classe (non dell’istanza). Non è possibile
inizializzarli tramite lista .

static int num; int MyClass::num = 0;


static void MetodoStatic(); // prima di essere utilizzata

cout << MyClass::num << endl;
MyClass::MetodoStatic();

Membri Const : Esso viene allocato per ogni istanza come un normale attributo,
tuttavia il valore che esso assume per ogni istanza viene stabilito una volta per
tutte all'atto della creazione dell'istanza stessa e non potra` mai cambiare durante
la vita dell'oggetto. E’ obbligatoria l’inizializzazione tramite lista .

int GetConstMember() const { return ConstMember; }

La funzione si impegna a non accedere in scrittura ai membri della classe.


C++ Le Classi

Vere costanti nelle classi: class Ok { public: /* ... */


private: enum { Size = 20 };

char String[Size]; };

Membri Volatile:
Il C++ e` un linguaggio adatto a qualsiasi tipo di applicazione, in particolare a
quelle che per loro natura si devono interfacciare direttamente all'hardware.
Una prova in tal proposito e` fornita dalla keyword volatile che posta davanti
ad un identificatore di variabile comunica al compilatore che quella variabile
puo` cambiare valore in modo asincrono rispetto al sistema:

volatile int Var;

In questo caso il compilatore non ottimizza l’accesso alla risorsa.


C++ Le Classi

Funzioni Friend: permette che una funzione non membro


possa accedere direttamente ai membri (attributi e/o metodi)
privati di una classe.
friend ostream& operator<<(ostream& o, MyClass& Obj);
friend void FriendMethod(MyClass &x);
...
ostream& operator<<(ostream& o, MyClass& Obj)
{ o << Obj.F1 << ' ' << Obj.F2 << ' ' << Obj.C; return o;}

class MyClass { Il modificatore friend può


/* ... */ essere applicato anche ad una
friend class AnotherClass; }; classe intera.
Le Classi:
C++ Ereditarietà

Ereditarietà: Il meccanismo dell'ereditarieta` e` per molti aspetti


simile a quello della composizione quando si vuole modellare una
relazione di tipo Is-a. L'idea e` quella di dire al compilatore che una
nuova classe (detta classe derivata) e` ottenuta da una preesistente
(detta classe base) "copiando" il codice di quest'ultima nella classe
derivata e modificandolo (eventualmente) con nuove definizioni.

class Person { class Student : Person


{
public: Person(); ~Person();
public:
void PrintData(); /* ... */
Student(); ~Student(); /* ... */
private: char * Name;
private: unsigned int IdCode; /* ... */
unsigned int Age; /* ... */ };
};
Le Classi:
C++ Ereditarietà

•La classe derivata puo` accedere ai membri protetti e pubblici della


classe base;
•E’ possobile ridefinire un metodo ereditato dalla classe base:
void Student::PrintData()
{ Person::PrintData();
cout << "Matricola: " << IdCode;
}
•Costruttori per classi derivate:

Student::Student() Student::Student() : Person(/* ... */) {


{ Person(/* ... */); /* ... */
}
/* ... */ }

Quando parte il costruttore l’stanza è già stata creata.


Le Classi:
C++ Ereditarietà

Per default l'ereditarieta` e` privata, tutti i membri ereditati diventano


cioe` membri privati della classe derivata e non sono quindi parte della
sua interfaccia.

In alternativa:
•Con l'ereditarieta` pubblica i membri ereditati mantengono lo stesso grado di
protezione che avevano nella classe da cui si eredita (classe base immediata): i
membri public rimangono public e quelli protected continuano ad essere
protected;
•Con l'ereditarieta` protetta i membri public della classe base divengono
membri protected della classe derivata; quelli protected rimangono tali.

class < DerivedClassName > : [< Qualifier >] < BaseClassName >
{ /* ... */ };
Le Classi:
C++ Ereditarietà

Il C++ supporta, a differenza di molti altri linguaggi,


l’eredità multipla:
class iostream : public istream, public ostream

{ /* ... */ };

L’eredità multipla talvolta può generare ambiguità che


possono essere risolti con i risolutori di scope:
BaseClass1::Member = 10;
Le Classi:
C++ Ereditarietà

Classe 4 In questo caso la Classe 2 e la Classe 3


dovranno ereditare in maniera virtuale
Classe 2 (virtual) da Classe 1. In questo modo il
Classe 1 compilatore non si limita solo a copiare
la classe base, ma crea un puntatore ad
un istanza di tale classe. Nel caso in cui
una classe eredita più volte da un classe
Classe 3
base virtuale, i puntatori creati
Classe 1 punteranno alla stessa istanza della
classe base.

class Student : virtual private Person


Classi Virtuali
{}
C++ Le Classi: Funzioni Virtuali

T * Ptr = 0;
Ptr = new Td; // Td derivata da T ed entrambi hanno un metodo Paint()
Ptr -> Paint();// Richiama il metodo di T !!!

Le funzioni virtuali fanno in modo che il corretto tipo dell'oggetto


puntato sia automaticamente determinato al momento della chiamata
della funzione e rinviano il linking di tale funzione a run-time .
in T in Td
virtual void Paint(); virtual void Paint();
void Paint();
void T::Paint()
Per avere una chiamata risolvibile staticamente:
{ // non occorre virtual

/* ... */ } pT->T::Paint();
C++ Classi Astratte

I meccanismi dell'ereditarieta` e delle funzioni virtuali possono essere


combinati per realizzare delle classi il cui unico scopo e` quello di
stabilire una interfaccia comune a tutta una gerarchia di classi:
class TShape {
public:
virtual void Paint() = 0; // Funzioni virtuali pure
virtual void Erase() = 0;// Non sono implementate
/* ... */
};

Una classe che possiede funzioni virtuali pure e detta classe astratta
(o interfaccia) e non e` possibile istanziarla; essa puo` essere
utilizzata unicamente per derivare nuove classi forzandole a fornire
determinati metodi (quelli corrispondenti alle funzioni virtuali pure).
C++ Operatori

•Non e` possibile definire nuovi operatori, si puo` solamente


eseguire l'overloading di uno per cui esiste gia` un simbolo nel
linguaggio;
•Non e` possibile modificare la precedenza di un operatore e non
e` possibile modificarne l'arieta` o l'associativita`;
•Non e` concessa la possibilita` di eseguire l'overloading
dell'operatore ternario ? :;
•E` possibile ridefinire un operatore sia come funzione globale
che come funzione membro, i seguenti operatori devono tuttavia
essere sempre funzioni membro non statiche: operatore di
assegnamento ( = ), operatore di sottoscrizione ( [ ] ) e operatore
->.
C++ Operatori

< ReturnType > operator@( < ArgumentList > )


{ < Body > }

ReturnType e` il tipo restituito (non ci sono restrizioni); @


indica un qualsiasi simbolo di operatore valido;
ArgumentList e` la lista di parametri (tipo e nome) che
l'operatore riceve, i parametri sono due per un operatore
binario (il primo e` quello che compare a sinistra
dell'operatore quando esso viene applicato) mentre e` uno
solo per un operatore unario. Infine Body e` la sequenza di
istruzioni che costituiscono il corpo dell'operatore.
C++ Operatori

struct Complex Operatore come funzione globale


{ float Re;

float Im; };

Complex operator+(const Complex & A, const Complex & B)


{
Complex Result;
Result.Re = A.Re + B.Re;
Result.Im = A.Im + B.Im; return Result;
}
C++ Operatori

class Complex {
Operatore come membro di una classe
public:

Complex(float re, float im);

Complex operator-() const; // - unario

Complex operator+(const Complex & B) const;

const Complex & operator=(const Complex & B);

private:

float Re; float Im;

};

Complex::Complex(float re, float im = 0.0) { Re = re; Im = im; };

Complex Complex::operator-() const { return Complex(-Re, -Im); }

Complex Complex::operator+(const Complex & B) const

{ return Complex(Re+B.Re, Im+B.Im);}

const Complex & Complex::operator=(const Complex & B)

{ Re = B.Re; Im = B.Im; return *this; }


C++ Operatori

Ecco alcuni esempi di applicazione dei precedenti operatori


e la loro rispettiva traduzione in chiamate di funzioni (A, B e
C sono variabili di tipo Complex):

B = -A; // analogo a B.operator=(A.operator-());


C = A+B; // analogo a C.operator=(A.operator+(B));
C = A+(-B); // analogo a C.operator=(A.operator+(B.operator-()))
C++ Operatori

L'operatore di sottoscrizione

class TArray {
public: ... Anche gli operatori new e
int operator[](unsigned int Index); delete sono ridefinibili
private: int * Array;
unsigned int ArraySize;
};
int TArray::operator[](unsigned int Index)
{ if (Index<ArraySize) return Array[Index];

else /* Errore */ }
Conversioni di tipo
C++
Si intende una operazione volta a trasformare un valore di
un certo tipo in un altro valore di altro tipo. Esistono
conversioni implicite (decise dal compilatore e dette anche
coercizioni) ed esplicite decise dal programmatore.

int i = 5;
float f = 0.0;
double d = 1.0;
d = f + i;
d = (double)f + (double)i;
C++ Conversioni di tipo

Non sempre una conversione di tipo preserva il valore: ad esempio nella


conversione da float a int in generale si riscontra una perdita di precisione. Da
questo punto di vista si puo` distinguere tra conversione di tipo con perdita di
informazione e conversione di tipo senza perdita di informazione. In
particolare in quest'ultimo caso si parla di conversioni triviali e promozione di
tipo. Le conversioni triviali sono:
C++ Classi Template

template < class T >


Questa semplice dichiarazione (che non deve essere seguita da ";")
dice al compilatore che la successiva dichiarazione (o definizione)
utilizzera` un generico tipo T che sara` noto solo quando tale codice
verra` effettivamente utilizzato.
template < class T >
class TVector {
public: Utilizzo
TVector(int Size);
~TVector();
TVector< int > IntArray(30);
T & operator[](int Index);
private: TVector< TMyClass > MyArray(100);
T * Data;
int ArraySize; };
C++ Classi Template

template < class T >


TVector< T >::TVector(int Size) { Se in un metodo di una
ArraySize = Size; classe template viene
Data = Size? new T(Size) : 0;
} utilizzato un operatore,
questo implica che la classe
template < class T >
TVector< T >::~TVector() { attraverso il quale il
if (Data) delete Data; template è tipizzato deve
}
aver definito tale operatore.
template < class T >
T & TVector< T >::operator[] (int Index) {
if (!ArraySize || (Index > ArraySize))
/* Segnalazione errore */
else return Data[Index];
}
C++ Funzioni Template

template < class T > T & min(T & A, T & B)


{ return (A < B)? A : B; }

TMyClass D(/* ... */);


Utilizzo TMyClass E(/* ... */);
TMyClass F = min(D, E);
C++ Classi Template

Un template puo` avere un qualsiasi numero di parametri e sebbene nella


definizione il generico parametro sia indicato con la notazione class T (es.
template <class T>) non e` necessario che all'atto dell'istanzazione esso sia
sostituito da un identificatore di classe, puo` essere anche utilizzato un tipo
primitivo o uno ottenuto tramite struct, enum, union o typedef. O ancora:

template < class T, int Size >


class TVector { public:
T & operator[](int Index);
private: T Data[Size]; };
template < class T, int Size > T & TVector< T, Size >::operator[] (int Index)

{ if (Index > Size) /* Segnalazione errore */ else return Data[Index]; }

TVector< char *, 20 > A;

TVector< TMyClass, 30 > B;


C++ Classi Template

Ereditarietà

template< class T >


class Base { /* ... */ };

template< class T >


class Derived : public Base< T >
{ /* ... */ };
C++ Direttive al compilatore

#include <path>

#include “path”

c=QUADRATO(a); #define MSG “CIAO”

#define QUADRATO( arg ) ((arg) * (arg))

#if DLEVEL == 0
#define STACK 0
#elif DLEVEL == 1
#define STACK 100
#else
#define STACK 200
#endif
Allocazione e

C++ deallocazione di una


matrice bidimensionale

#include <iostream.h> // cout, cin, cerr ...


#include <stdlib.h> // ANSI Compatibilità, malloc...
#include <string.h> // strcpy...

void main(int argc, char* argv[])


{
long **mat; // Dichiaro un puntatore ad un puntatore di long;
long altezza=atol(argv[1]);
long larghezza=atol(argv[2]);
long i,j;

if (argc!=3)
{
cout << "Errore nel passaggio dei Parametri" << endl;
return;
}
Allocazione e

C++ deallocazione di una


matrice bidimensionale
// Allocazione matrice
// Alloco puntatori entry alle righe della matrice
mat=new long *[altezza];

// Alloco le righe della matrice


for (i=0;i<altezza;i++)
mat[i]=new long[larghezza];
// Carico la matrice
for (i=0;i<altezza;i++)
for (j=0;j<larghezza;j++)
mat[i][j]=i+j;
// Stampa della matrice per righe
for (i=0;i<altezza;i++)
{
for(j=0;j<larghezza;j++)
cout << mat[i][j] << " " ;
cout << endl;
}
// deallocazione della matrice
for (i=0;i<altezza;i++)
delete [] mat[i];
delete [] mat;
}
Gestione Files
C++
#include <iostream.h> // cout, cin, cerr ...
#include <stdlib.h> // ANSI Compatibilità, malloc...
#include <string.h> // strcpy...
#include <fstream.h> // file

void main(int argc, char* argv[])


{
char riga[1024];
// Creazione e scrittura di un file
ofstream ofile("appo.txt");
ofile << "Ciccio Cappuccio \n";
ofile << "nato a Penna il 10/09/69 \n";
ofile << "Via Matita, 5 \n";
ofile << "72012 Libro(Lb) \n";
ofile.close();

// Lettura di un file
ifstream ifile("appo.txt");
C++ Gestione Files

// Con questa modalità ci si ferma ogni SPACE


ifile >> riga;
cout << riga << endl;

// Lettura per righe


while (ifile.peek()!=-1)
{
ifile.getline(riga,1024);
cout << riga << "-" << ifile.peek() << endl;
}

ifile.close();
}

Potrebbero piacerti anche