domenica 23 novembre 2014

Funzioni "Friend" e istruzione "operator"

Le Funzioni Friend sono delle funzioni che non fanno parte della Casse. Il loro scopo è quello di assolvere compiti che altrimenti non potrebbero essere assolti.

Class Frazione
{
    friend Frazione Somma(Frazione);

  • "friend Frazione" indica il tipo di dato restituito dalla funzione friend
  • "(Frazione)" indica il tipo di parametro che verrà passato alla funzione, è possibile tralasciare     nel prototipo dell funzione il parametro
  • Una funzione friend i posiziona prima di ogni altra funzione
  • Le funzioni friend possono essere utilizzate solo dai membri della classe, non sono                     raggiungibili dal main()
  • Una funzione friend è raggiungibile solo dall'oggetto stesso, non da altri oggetti di stessa           tipologia   
private:
        int num;
        int den;
}

Come va implementata una funzione friend:
Frazione Somma (Frazione a)
   {
      ...
      ...
      ...
   }

Se non fosse un metodo friend invece utilizzeremmo la sintassi:
Frazione::Somma (Frazione a)
   {
      ...
      ...
      ...
   }

Istruzione "operator":
E' possibile sostituire alla parola somma l'operatore di somma "+", per farlo utilizzo l'istruzione "operator" seguito dall'operatore matematico (nel nostro caso +):
Frazione operator + (Frazione a)
   {
      ...
      ...
      ...
   }
che implementato all'interno del main() mi permetterà di utilizzare due oggetti come se fossero due numeri, vediamo l'esempio:

main()
 {
   Frazione a(5,3);
   Frazione b(3,2);
   Frazione c;
   
   c=a+b;
}

*!* l'istruzione "operator" può essere utilizzato anche con gli altri operatori matematici +  -  +=  -=  >   <   /   *   ...

Puntatore "this"

Il Puntatore "this" è un Puntatore ad un oggetto, serve ad identificare l'indirizzo di partenza di un oggetto.
Il Puntatore "this" viene utilizzato quando vengono rilevati dei possibili casi di ambiguità del codice:

Esempio di un possibile caso di "Ambiguità" in codice:
Class Prova                                                      Class Prova
{                                                                       {
   public:                                                               public:
      Prova(int a);                                                       Prova(int a);
      {                                                                         {
         a=0;                                                                     this->a=0;
         a++;                                                                     this->a++;
       }                                                                         }
      private:                                                                private:
         int a;                                                                    int a;
}                                                                       }


Passaggio di Puntatori come Parametri di Funzioni

Anche le variabili di tipo Puntatore possono essere passate come parametro sia "per valore" che "per riferimento":

f (int *p)   come per una variabile di tipo intero f (int r)
qui duplico un puntatore di tipo intero                      qui duplico una variabile di tipo intero

è la dichiarazione di un puntatore passato come parametro per valore, passa quindi il contenuto dell'area a cui punta il puntatore.
*!* lo si utilizza quando è necessario mantenere invariato il contenuto di *p
                   
f (int *&q)   come per una variabile di tipo intero f (int &s)
qui passo l'indirizzo del puntatore                      qui passo l'indirizzo di una variabile di tipo intero

è la dichiarazione di un puntatore passato come parametro per riferimetno, passa quindi l'indirizzo di memoria a cui punta il puntatore.
*!* lo si utilizza quando devo modificare il contenuto di *q




Array di Puntatori

#include <iostream>
using namespace std;

int a[10];
int *b;

main()
{
    b=new int[10];   //alloca spazio in memoria al puntatore 'p' e restituisce in 'p' il valore dell' indirizzo del primo elemento
    cout<<"Lezione del 13/10/2014 -> Utilizzo di un array di puntatori"<<endl;
int i;

//Inserimento 
    for(i=0;i<10;i++)
    {
        a[i]=i;   //assegnazione del valore 'i' all'elemento [i] dell'array di interi
        b[i]=i+1;   //assegnazione del valore 'i+1' all'elemento [i] dell'array di puntatori 'b'
    }
//Visualizzazione
       for(i=0;i<10;i++)
       {
             cout<<endl<<"A: " << a[i];
             cout<<endl<<"B: " << b[i];
             cout<<endl<<"Indirizzo puntato da 'b': " << &b[i];   //aumenta su base esadecimale di 4 + 4 perchè è un array di interi (intero=4 byte)
             cout<<endl<<endl;
       }
return 0;
}



Puntatori a un Oggetto

Un puntatore può puntare a un Area di Memoria di tipo "Oggetto", vediamo un esempio di codice:

Class Punto 
{
      ...
      ...
      ...
}

Punto* q;   //dichiarazione di un puntatore "q" di tipo "Punto"
q=new Punto;   //alloco spazio di memoria adatto a tipo "Punto" e restituisco a "q" l'indirizzo di                                       memoria

Per accedere alle proprietà o ai metodi della Classe Punto tramite puntatore posso utilizzare due strumenti:
q -> ascissa=5;   //operatore freccia
(*q).ordinata=7;   //* è l'area di memoria puntata

Quando è necessario dichiarare un Array di puntatori invece utilizziamo la seguente sintassi:
q=new Punto[10];   //alloca 10 strutture, preleva il primo indirizzo dell'area puntata e lo assegna a                                         q[0] - "q" punta ad un area contigua.
for(int i=0;i<10;i++)
{
   q[i].ascissa=5+i;
   q[i].ordinata=7+i;
}

in alternativa:

for(int i=0;i<10;i++)
{
   *(q+i)=i;   //dove "q" è l'indirizzo di partenza e "i" l'elemento 
}

Per deallocare lo spazio assegnata ai puntatori utilizzeremo lo strumento "delete":
per un puntatore: delete q;
per un array di puntatori delete [10]Punto;

*!* Gli indirizzi puntati dagli Array sono salvati in un area di memoria chiamata +HEAP

domenica 9 novembre 2014

domenica 2 novembre 2014

Compito di Gruppo

Compito sviluppato con la collaborazione della Classe per il programma Classe Frazione:
     nel dettaglio sviluppo del metodo "+=" e "-=":

#include <iostream>

using namespace std;

class Frazione{   //classe Frazione
    public:   //metodi pubblici
        Frazione();   //costruttore senza passaggio di parametri
        Frazione(int a,int b);   //costruttore con passaggio di due parametri di tipo intero per valore
        Frazione(int c);   //costruttore con passaggio di un parametro di tipo intero per valore
        void inserimento();   //metodo per l'inserimento dei dati num e den
        void visualizza();   //metodo per la visualizzazione dei dati inseriti
        void aggiorna();   //metodo per aggiornare i dati inseriti
            Frazione operator +(Frazione a);
            Frazione operator -(Frazione a);
            Frazione operator *(Frazione a);
            Frazione operator /(Frazione a);
            void operator += (Frazione a);
    void operator -= (Frazione a);
    bool operator >(Frazione); //prototipo
   bool operator <(Frazione); //prototipo
   bool operator !=(Frazione a);
        int num;   //dichiarazione di una variabile di tipo intera
        int den;   //dichiarazione di una variabile di tipo intera

    };

Frazione::Frazione()   //costruttore senza passaggio di parametri
    {
    num=1;
    den=1;
    };

Frazione::Frazione(int a, int b)   //costruttore con passaggio di parametri dove passo i valori dal main alle variabili a e b per valore
    {
    num=a;   //associo il contenuto puntato da a alla variabile num
    den=b;   //associo il contenuto puntato da b alla variabile den
    };

Frazione::Frazione(int c)   //costruttore con passaggio di parametri dove passo i valori dal main alla variabile c per valore
    {
    num=c;
    den=1;   //trattandosi di un intero dichiaro il denominatore uguale a 1
    };


void Frazione::inserimento()   //metodo per l'inserimento dei dati
    {
        cout<<"Inserisci il numeratore: "<<endl;
        cin>>num;
        do
        {
            cout<<"Inserisci il denominatore: "<<endl;
            cin>>den;
            if(den==0)   //se il denominatore e' uguale a 0 non accetto i dati inseriti e richiedo di ripetere l'inserimento
                cout<<"Il denominatore deve essere diverso da '0'"<<endl;
        }while(den==0);
    };

void Frazione::aggiorna()   //metodo per l'inserimento dei dati
    {
        cout<<"Inserisci il numeratore: "<<endl;
        cin>>num;
        do
        {
            cout<<"Inserisci il denominatore: "<<endl;
            cin>>den;
            if(den==0)   //se il denominatore e' uguale a 0 non accetto i dati inseriti e richiedo di ripetere l'inserimento
                cout<<"Il denominatore deve essere diverso da '0'"<<endl;
        }while(den==0);
    };

void Frazione::visualizza()   //metodo per visualizzare i dati inseriti
    {
        if(den!=1)   //se a denominatre c'è un valore diverso da uno allora è una frzione e visualizzo num/den
            cout<<"La frazione inserita e': "<<num<< "/" <<den<<endl;
        else   //altrimenti è un intero e visualizzo solo num
            cout<<"La frazione inserita e': "<<num<<endl;
    };

Frazione Frazione :: operator +(Frazione a)
      {
 Frazione b;
             b.den= this->den*a.den;
             b.num= (this->den*a.num)+(this->num*a.den);
             //b.Semplifica();
           return b;

 };
  Frazione Frazione :: operator -(Frazione a)
  {
  Frazione b;
             b.den= this->den*a.den;
             b.num= (this->den*a.num)-(this->num*a.den);
             //b.Semplifica();
           return b;
  };
  Frazione Frazione :: operator / (Frazione a)
  {
  Frazione b;

                b.den=this->den*a.num;
                b.num=this->num*a.den;
               // b.Semplifica();
                return b;
  };
      Frazione Frazione :: operator * (Frazione a)
      {
      Frazione b;

                b.den=this->den*a.den;
                b.num=this->num*a.num;
                //b.Semplifica();
                return b;

      };
void Frazione :: operator += (Frazione a)   //metodo per la somma tra frazioni con passaggio di oggetto a parametri (passeremo le due frazioni da sommare)
    {
        *this=a+*this;
    };
void Frazione :: operator -= (Frazione a)   //metodo per la somma tra frazioni con passaggio di oggetto a parametri (passeremo le due frazioni da sommare)
    {
        *this=a-*this;
        if(num==0)   //if per la visualizzazione del solo numeratore in caso di risultato uguale a 0
            {
                num=0;
                den=1;
            }
};
bool Frazione::operator >(Frazione a){

  bool ris=false;

  Frazione appoggio; //istanzio l'oggetto appoggio di classe frazione
  int fraz1=this->num*a.den;   // numeratore fraz1 * den fraz2
  int fraz2=this->den*a.num;   //numeratore fraz2 * den fraz1

  if(fraz1>fraz2)
      ris=true;

   return ris;

};
    bool Frazione::operator <(Frazione a){



    bool ris=false;

    Frazione appoggio;
    int fraz1=this->num*a.den;
    int fraz2=this->den*a.num;

     if(fraz1<fraz2)
      ris=true;

          return ris;


    };

bool Frazione::operator !=(Frazione a)
{
    bool x;
    if((a.num==num)&&(a.den==den))
    {
        x=0;
    }
    else
    {
        x=1;
    }
    return x;
}

main()
{
    int *scelta;
    int *modfraz;
    char mod;
    char *input;
    Frazione obj1;   //istanza oggetto obj1
    Frazione obj2;   //istanza oggetto obj2
    Frazione ris;
    cout<<"CALCOLATRICE PER FRAZIONI:"<<endl;
    scelta=new int;


        cout<<"Quale operazione vuoi eseguire? "<<endl;
        cout<<"1)Somma\n2)Sottrazione\n3)Moltiplicazione\n4)Divisione\n5)'+='\n6)'-='\n7)'>' o '<'\n8)'=' o '!='"<<endl;
        cout<<"Scegli 1-2-3-4-5-6-7-8: ";
        cin>>*scelta;
        cout<<endl;
        obj1.inserimento();   //metodo per inserimento in oggetto obj1
        obj2.inserimento();   //metodo per inserimento in oggetto obj2
        cout<<"Dati inseriti: "<<endl;
        obj1.visualizza();   //metodo per visualizzare dati inseriti in obj1
        obj2.visualizza();   //metodo per visualizzare dati inseriti in obj2
        Frazione risultato;   //istanza oggetto risultato

        input=new char;
        do
        {
            cout<<"Vuoi modificare i dati inseriti? (s/n)";
            cin>>*input;
        }while(((*input=='S')&&(*input=='s'))&&((*input!='n')&&(*input!='N')));
        if((*input=='s')||(*input=='S'))
        {
            modfraz=new int;
            do{
                cout<<endl<<"Quale frazione vuoi modificare? (1/2)";
                cin>>*modfraz;
                if(*modfraz==1)
                    obj1.aggiorna();
                else
                    if(*modfraz==2)
                        obj2.aggiorna();
                    else
                        cout<<endl<<"Scelta non valida"<<endl;
            }while((*modfraz!=1)&&(*modfraz!=2));
            delete modfraz;
        }
        else
            if((*input!='n')&&(*input!='N'))
                cout<<"Scelta non valida"<<endl;
        delete input;

        switch (*scelta)
            {
                case 1: ris=obj1+obj2;   //metodo per somma
                        ris.visualizza();
                        break;
                case 2: ris=obj1-obj2;   //metodo per somma
                        ris.visualizza();
                        break;
                case 3: ris=obj1*obj2;   //metodo per somma
                        ris.visualizza();
                        break;
                case 4: ris=obj1/obj2;   //metodo per somma
                        ris.visualizza();
                        break;
                case 5: obj1+=obj2;   //metodo per somma
                        obj1.visualizza();
                        break;
                case 6: obj1-=obj2;   //metodo per somma
                        obj1.visualizza();
                        break;
                case 7: bool ris;
                        if(ris=obj1>obj2)cout<<endl<<"La prima frazione e' maggiore della seconda"<<endl;
                        if(ris=obj1<obj2)cout<<endl<<"La prima frazione e' minore della seconda"<<endl;
                        break;
                case 8: bool x;
                        ris=obj1!=obj2;
                        if(x==0)
                            cout<<"Le due Frazioni sono uguali"<<endl;
                        else
                            cout<<"Le due frazioni sono diverse"<<endl;
                        break;
                }
        delete scelta;
}