Corsi on-line
Chiudi
Newsletter:
  • Seguici su Facebook
  • Seguici su Twitter
  • Seguici su Google+
  • Seguici via RSS
  • Seguici col tuo Smartphone

La classe numero complesso

In questo capitolo amplieremo le nostre conoscenze riguardo all'uso delle classi e parleremo dell'overloading.
L'overloading consiste nel sovraccaricare un operatore o una funzione per far si che essa funzioni con variabili aventi tipi diversi. Ad esempio nel seguito del capitolo vedremo come sovraccaricare l'operatore + per far si che esso sommi due numeri complessi.

Il modo in cui abbiamo scritto il codice precedente non permette un facile ri-uso... scriviamo quindi la nostra classe complessa in modo tale che essa sia riusabile in qualsiasi momento. Per fare ciò basta dividere il codice nelle seguenti parti:

  1. Un file di tipo header dove scrivere la dichiarazione di classe (complex.h)
  2. Un file di tipo cpp dove deve essere inserito il precedente file header e in cui vanno definite le funzioni il cui prototipo si trova nella definizione di classe.
  3. Un terzo file, che includa il file header di classe, dove scriveremo il nostro main.
Iniziamo col creare un nuovo progetto come spiegato nel capitolo 2 di questa guida e diamogli il nome Numero Complesso con Operazioni. A questo punto creiamo all'interno del nostro progetto tre nuovi file sorgente premendo CTRL+N o cliccando su e rispondendo di "sì" alla richiesta di se vogliamo aggiungere tale file al progetto corrente.

A questo punto salviamo con nome i tre file che compaiono cliccando su e diamo a tali file i nomi:

mi raccomado di utilizzare le estensioni giuste!!

Dovreste aver ottenuto la seguente schermata:

Iniziamo con lo scrivere il file complex.h:

#include <iostream>

using namespace std;

class complex{

//overloading di estrazione dello streaming
  friend ostream &operator<<( ostream & , const complex  &);
//overloading di immissione dello streaming
  friend istream &operator>>( istream &, complex & );

public:
         //costruttore
         complex(double = 0.0 , double = 0.0 );
         //overloading vari
         complex operator+(const complex & )const;
         complex operator-(const complex & )const;
         complex &operator=(const complex & );
         complex operator*(const complex &)const;
         bool operator==(const complex &)const;
         bool operator!=(const complex &)const;
         
private:
         //come nell'esempio precedente
         double parteReale;
         double parteImmaginaria;

};
In questo codice vediamo la presenza di una nuova keyword (friend) la quale sta a significare che a quei dati possono accedere solo le funzioni della classe; in particolare noi accederemo agli operatori << e >> rispettivamente delle classi ostream (che sta per output stream) e istream (che sta per input stream).

I parametri specificati tra parentesi rappresentano un oggetto ostream/istream passato per riferimento (&) e un oggetto complex sempre passato per riferimento, con la clausola const nel caso dell'ostream in quanto quell'oggetto non deve essere modificato.

(L'articolo continua più sotto...)

Segue la distinzione in parte pubblica e privata come visto in precedenza.

complex(double = 0.0 , double = 0.0 )
sta a significare che il costruttore per default inizializza a zero i due parametri anche se non lo specifichiamo.

Dopo c'è l'overloading dei vari operatori che intendiamo usare.

Nota: qualsiasi classe avete intenzione di sviluppare sappiate che il prototipo dei vari operatori deve essere sempre questo, quindi tenete tali prototipi a modello e cambiate solo ciò che è necessario (ovvero dove compare complex dovrete scrivere il nome della vostra classe).

La parte privata è la stessa dell'esempio precedente.

Vediamo ora il codice da scrivere in complex.cpp:

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

using namespace std;

//costruttore
complex::complex( double r, double i)
{
parteReale = r;
parteImmaginaria = i;
}

//overloading vari
ostream &operator<<(ostream &output , const complex &p)
{
 if (p.parteImmaginaria >= 0)
    output << '(' << p.parteReale << "+j" 
	       << p.parteImmaginaria << ')' << endl;
 else
    output << '(' << p.parteReale << "-j" 
	       << p.parteImmaginaria*-1 << ')' << endl;
    
 return output;   
} 

istream &operator>>( istream &input, complex &a )
{
      input >> a.parteReale >> a.parteImmaginaria;


   return input;  
}

//overloading somma
complex complex::operator+(const complex &addendo2)const
{
  return complex ( parteReale + addendo2.parteReale ,
                  parteImmaginaria + addendo2.parteImmaginaria);
}

//overloading differenza
complex complex::operator-(const complex &addendo2)const
{
  return complex ( parteReale - addendo2.parteReale ,
                   parteImmaginaria - addendo2.parteImmaginaria);
}

//operatore di assegnamento
complex& complex::operator=(const complex &rValue )
{

  parteReale = rValue.parteReale;
  parteImmaginaria = rValue.parteImmaginaria;
   return *this;
}
//operatore di moltiplicazione
complex complex::operator*(const complex &fattore2)const
{

   return complex(parteReale * fattore2.parteReale -
                parteImmaginaria * fattore2.parteImmaginaria,
           parteImmaginaria * fattore2.parteReale +
		        parteReale * fattore2.parteImmaginaria);

}

//operatore di uguaglianza
bool complex::operator==(const complex &pippo)const
{
   if (parteReale==pippo.parteReale &&
             parteImmaginaria==pippo.parteImmaginaria)
      return true;
   else
      return false;
}

//operatore diverso da
bool complex::operator!=(const complex &pluto)const
{

   if (parteReale!=pluto.parteReale && 
           parteImmaginaria!=pluto.parteImmaginaria)
     return true;
   else
     return false;
}
In tale codice è contenuta la dichiarazione delle funzioni membro e la ridefinizione degli operatori.

Esamineremo solo alcuni di questi operatori in quanto la comprensione di tale codice dovrebbe ormai essere semplice:

Notiamo che vi è l'inclusione del file dove è definita la dichiarazione della classe complex ovvero l'istruzione #include "complex.h".

ostream &operator<<(ostream &output , const complex &p)
significa che stiamo per ridefinire l'operatore << il quale restituisce un oggetto di tipo ostream e prende in ingresso una variabile di tipo ostream chiamata output e un const complex, constante poichè non deve essere modificato. All'interno delle parentesi graffe vi è scritta la stessa funzione che avevamo chiamato nell'esempio precedente stampaComplesso, il vantaggio è che ora possiamo permetterci di incanalare nello streaming d'uscita un numero complesso utilizzando l'operatore <<.

complex complex::operator+(const complex &addendo2)const
tale ridefinizione agisce sull'operatore di somma il quale deve restituire un ogetto di tipo complex prendendo in ingresso il secondo addendo che deve essere sempre un complex, a questo punto la funzione non fa altro che restituire la somma della parte reale con la parte reale che gli passiamo in input e lo stesso per la parte immaginaria. Tali somme vengono date come input al costruttore della classe complex.

complex& complex::operator=(const complex &rValue )
indica che stiamo ridefinendo l'operatore di assegnazione il quale restituirà un complex, prendendo in input un altro complex dichiarato const e chiamato rValue (valore di destra). Il corpo della funzione non fa altro che copiare i valori di rValue in quelli dell'oggetto associato in quel momento all'operatore. Inoltre vi è la riga return *this; la quale sta a significare che si restituisce il valore dell'oggetto puntato. Facciamo un esempio:

    complex x(10,-3); //corrisponde a 10-j3
    complex y; //crea un nuovo oggetto complex
    y=x; //ad y viene associato il valore 10-j3
Il resto delle ridefinizioni è simile; ripeto ancora che i prototipi degli operatori sono sempre gli stessi bisogna quindi ricordarli o andare a consultarli ogni volta che si vuole effettuare tale operazione.

In ultimo vi è il codice da inserire nel main.cpp:

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

using namespace std;

int main()
{
 //costruisce a con valori di default
 complex a;
 cout << "Valore di deafult del numero complesso a: "<<a;
  
 cout<< "\nImmetti i nuovi valori di a" << endl;
 //modifica a
 cin >> a;
 cout << a;

 //cotruisce b con i valori di a
 complex b(a);
 cout << "Istanziamo b mediante il costruttore con i valori di a"
       << endl;
 cout << "b vale: " << b;
    
 //inizializza  c con i valori 3 e -5
 complex c(3,-5);  
 cout << "\nViene istanziato c con i seg. valori" << c;

 cout << "\nLa somma di c e b e': " << c+b;
    
 cout << "\nVerifica dell'operatore di assegnamento con c=b" ;
 c=b;
 cout << "\nOra c dovrebbe vale quanto b "<< c;
    
 cout << "\na: " << a;
 cout << "\nc: "<<c;
 cout << "\nc*a: "<< c*a;
    
 if (a==b)
   cout << "a e' uguale a b" << endl;
 else
   cout << "a e' diverso da b" << endl;

 //instanzia un oggetto con valori 89 e 87
 complex d(89,87) ;    
 if (c!=d)
 cout << "c e d sono diversi" << endl;

 system ("PAUSE");
 return 0;
}
Unica nota importante da fare al main è l'inclusione del file #include "complex.h" grazie al quale possiamo utilizzare la classe complex con tutte le sue funzioni. Il resto sono semplici operazioni di input/output eseguite grazie all'overloading degli operatori di streaming.

Arrivati a questo punto siamo in grado di gestire una classe.

Corsi
Corso Paint Shop ProCorso Paint Shop Pro
Grafica Web e fotoritocco col noto Corel PSP. A partire da 39 €.
Corso Visual Basic 6Corso Visual Basic 6
Realizzare applicazioni Desktop con VB6. A partire da 39 €.
Corso XMLCorso XML
Creazione di strutture XML, XSL ed altri linguaggi eXtensible. A partire da 39 €.
Sommario
Annunci

Mr.Webmaster

Pubblicità
Chi Siamo
Contattaci
Collabora
Note Legali
© 2003 - 2012 Mr.Webmaster - Il portale dei Webmaster Italiani - Tutti i diritti riservati | Powered by IKIweb Internet Media S.r.l. - PIVA 02848390122