LA NUOVA GERUSALEMME
Qui si costruisce la NUOVA GERUSALEMME grazie al SECONDO TESTIMONE e UNTO, GESU' vi aveva avvisati del mio arrivo ovvero l'arrivo del FIGLIO dell'UOMO, Gesù stesso ha detto che non lo vedete mai più da Giovanni 16,10 "LA GIUSTIZIA" da cui leggiamo ( 10La giustizia sta dalla mia parte, perché torno al Padre e non mi vedrete più.) Lui stesso manda lo Spirito Santo che è il VERO Figlio dell' Uomo . Il vero Figlio dell' Uomo è descritto in Apocalisse 1, 12 ecc.. Io uso la Bibbia Interconfessionale, diversamente cito altri testi. >>> Pace e Bene dal Figlio dell'Uomo <<<
 
Pagina precedente | 1 | Pagina successiva

12) Funzioni e Classe template

Ultimo Aggiornamento: 15/08/2016 13:21
Autore
Vota | Stampa | Notifica email    
OFFLINE
Post: 257
Post: 246
Registrato il: 02/03/2016
Registrato il: 03/03/2016
Sesso: Maschile
15/08/2016 11:38
 
Quota

Funzioni e Classi template overloading dei template parole chiave typename e export


Ora usiamo un nuovo sistema per fare sia l’ overloading o per creare il polimorfismo , ovvero creiamo un modello ( template ) di classe o di funzione in modo che questo template modello possa essere usato da differenti tipi di dati, un esempio potrebbe essere lo scambio di 2 oggetti  A e B  dove  A e B potrebbe essere benissimo un numero intero, o un numero reale, oppure
caratteri, tanto il lavoro da svolgere è sempre lo stesso  spostare a in b e viceversa



In poche parole  con la creazione di un template il compilatore già riconosce che deve creare una funzione o classe che deve funzionare con tutti i tipi di dati come detto sia interi che reali oppure caratteri o parole  vediamo come si crea una funzione template  che potrebbe essere  <class tipo > oppure <typename tipo >  :


 template <class_tipo1, class_tipo2 , ecc> 


il class_tipo è un segnaposto figurativo da usare per  sostituire  un valore che potrebbe essere ( int ) intero oppure un valore (char) oppure un ( float ) ecc.. possono esserci più di un tipo di segnaposti,   mentre la parte secondaria è come una funzione normale  tipo_ritorno usiamo  void , tra la prima parte  e la seconda parte non deve esserci nulla tutto il resto va scritto dentro il corpo della funzione 

 
 tipo_ritorno nome_funzione (parametri)

    {corpo della funzione }



Ecco un piccolo esempio di una funzione template dove posso scrivere 2 tipi diversi un int con una striga oppure 2 stringhe oppure un numero reale con un intero :


#include<iostream> using namespace std;


template<class x1 , class x2> void funzione (x1 l1 , x2 l2)

{   cout << l1 << " template " << l2 << endl;}

int main() { 

    funzione(1 , "provare il C++"); 

    funzione("il 5-8-2016" , "ciao da ByMpt-Zorobabele");

    funzione(0.23 , 14l); 

    cout << "\n\n Per uscire premere un tasto  + invio: "; char zx; cin >> zx; }


Nella parte x1,x2 sostituisce i tipi int o char ecc… l1e l2 dentro la funzione è leggi1 e leggi2 è una variabile di tipo x1 e x2 nella chiamata della funzione possiamo inserire quello che desideriamo , se creiamo una funzione template specifica il compilatore sceglie questa anzi che il modello, una funzione template  specifica  è scritta :



template<> tipo_ritorno nome_funzione <tipo_specifico>(parametri_funzione ) {corpo funzione }



vediamola da vicino  questa funzione se riceve 2 interi viene scelta al posto del template e questo viene considerato un overload delle funzioni la inserisco tutta su una riga :


template<>void funzione<int> (int a , int b)  {    cout << a << " template 2  " << b << endl; }



vediamo il programma di prima modificato, per capire quale funzione si usa ho scritto dentro la funzione  template e template 2 come potete vedere la terza chiamata è un ( int a ) e ( int b ) chiama template 2  :

#include<iostream> using namespace std;

template<class x1 , class x2>

void funzione (x1 l1 , x2 l2) {   cout << l1 << "  template  " << l2 << endl;   }

template<>void funzione <int> (int a , int b) {   cout << a << " template 2 " << b << endl;}

int main() { 

    funzione(1 , "provare il C++");

    funzione("il 5-8-2016" , "ciao da ByMpt-Zorobabele"); 

    funzione(14 , 20);        funzione(0.23 , 14l);

    cout << "\n\n Per uscire premere un tasto  + invio: ";  char zx;   cin >> zx;}



Abbiamo visto nella funzione template specializzata dopo il nome della funzione c’ è <tipo> il tipo dati e questo tipo di funzione template è personalizzata e con dati unici 



E’ possibile creare anche funzioni template con overload, ovvero basta far cambiare qualche piccolo accorgimento vediamo un esempio dallo stesso modello di su modifichiamo le funzioni in modo di avere le stesse funzioni template per motivi di spazio inserisco tutto su una riga vedete le 2 funzioni template una usa un solo parametro l’ altro usa 2 parametri ugualmente nella chiamata una usa un parametro l’ altra due  :

#include<iostream>using namespace std;

template <class x1> void funzione (x1 l1) {  cout << " Template f(x1 l1)  l vedi nota* \n"; }



template <class x1, class x2> void funzione (x1 l1, x2 l2) 

{   cout
<< " Template1 f(x1 l1, x2 l2)  l vedi nota*\n";}

int main() {    cout <<" nota*: < l = leggi > \n"; 

funzione(30);  funzione(29 , 33); 

cout
<< " \n Per uscire premere un tasto + invio: "; cin.get(); }



In queste funzioni template possiamo utilizzare come parametri sia standard (int ,long, char, ecc..) oppure utilizzare parametri di tipo generici come visto ma possiamo utilizzarli anche insieme nella stessa funzione inserite la nuova funzione nel programma scritto su come possibile vedere inseriamo un intero con numero 3 in l2 e una parola per x  ciao con l1:



template <class x1 >void funzione (x1 l1 , int l2)

{   cout << " Template2 f(x1 l1, int l2)  l vedi nota*\n";  cout << "scrivi i dati: l1 = " << l1 << " l2 = " << l2 << "\n"; }   

Nella chiamata inserire  :  funzione ("ciao" , 3);



L’utilizzo delle funzioni generiche è utilizzato per sistemare in modo alfabetico o numerico i dati ad esempio ordinare l’ array non importa se sia numeri interi o reali oppure caratteri con la funzione generica è tutto possibile ordinare , oltre le funzioni generiche  abbiamo anche le classi template e anche qui la classe può operare su qualsiasi tipo di dato e il compilatore crea i tipi di oggetti in base al tipo dato  la sintassi di una classe generica è:

template< class tipo > class nome_classe{ parametri della classe  };



class tipo è il tipo generico x come per le funzioni è solo un segnaposto è possibile inserire più tipi separati da una virgola come per le funzioni <class x, class x1 ecc..> le funzioni dentro una classe generica sono automaticamente anche esse generiche e non serve dichiararle template, poi per creare gli oggetti è importante inserire il < tipo > di dato da creare per questo oggetto,  ricordiamo l’ oggetti era  creati con (nome_classe   o;)   poi l’ oggetto  si usava ( o. )  ora per la classe template  l’ oggetto va creato con :

nome_classe <tipo> oggetto ; 

Vediamo un semplice utilizzo di una classe con 2 parametri , creo una classe con 2 parametri di tipo Template  T1 e T2 e creo la classe con class classe{ , poi T1 e T2 li trasformo in tipo ta e tb  con T1 ta;  con il costruttore classe si rende pubblici i 2 tipi ta e tb ora questi 2 tipi possono avere qualsiasi tipo di dato  realizziamo una funzione che legge i dati leggi()  :

#include<iostream> using namespace std;

template<class T1 , class T2> class classe{ 
 
T1  ta; T2 tb;
public:
classe(T1 x , T2 z) { ta = x; tb = z; }

void leggi(){ cout << ta << " : " << tb << endl; }     };    int main () { 


  classe < char* , int> o1("ByMpt-Zorobabele" , 1);
 
  classe <char* , double> o2("prova" , 1.1);

  o1.leggi(); o2.leggi();

  cout << "\n\n Per uscire premere un tasto + invio: ";   cin.get();}


Con   classe < char* , int> o1("ByMpt-Zorobabele" , 1);  e 
 
          classe <char* , double>o2("prova"
, 1.1);

ho creato i 2 oggetti o1 e o2  specificando prima con < tipo*, tipo>  ora i tipi 

ta e tb della classe prende i tipi che ho specificato <char e int> oppure <char* e double > nella creazione degli oggetti come già detto va sempre specificato il tipo che desideriamo far prendere all’ oggetto stesso 



Un’ altro modo di creare una classe è creare array generici che poi saranno scambiati come oggetti  come ci serve,  la prima cosa che ci serve è inserire una costante per la creazione dell’ array NUM = 5 , poi creiamo la classe generica  la prima cosa dentro la classe creiamo un array collegato al Template T array[NUM]; dichiariamo un indice ( i ) usiamo la parola register per inserire questa variabile nei registri in questi registri dopo l’ uso la variabile è cancellata ,  ora dobbiamo creare il vero array grazie alla parola chiave operator che lavora come overload per i tipi vedete la guida del compilatore di VS (scrivete e selezionate operator come funzione poi premere il tasto F1 ed ecco la guida del compilatore e la spiegazione di operator )  questa funzione controlla che l’ array sia nei parametri giusti if (i<0 || i> NUM - 1)  se sono errati si esce dal programma con exit(1) oppure crea il vero array return  array;

#include<iostream> using namespace std;     const int NUM = 5;

template <class T > class classe{   array [NUM];   public:

  classe(){  register int i;   for (i = 0; i < NUM; i++)array = i;  }   T &operator [](int i);   };

template<class T> T & classe<T>::operator[](int i)

{   if (i<0 || i> NUM - 1)  {    cout << "\n Indice dell' Array " << i << " e' fuori dai parametri concessi da " << NUM;     exit(1);  }
  return  array; }        int  main ()    {   classe <int>  oint;  
classe <double> odouble;    int i; 

  cout << "\n Array intero :\n ";    for (i = 0; i < NUM; i++)oint ;    for (i = 0; i < NUM; i++)     cout << oint << "  :  "; 
  cout<< endl;  

  cout << "\n Array double :\n ";  for (i = 0; i < NUM; i++)odouble =(double)i/5;    for (i = 0; i < NUM; i++)      cout << odouble << "  : "; 

  cout << "\n\n Per uscire premere
un tasto + invio : "; cin.get();} 


Dopo int main () troviamo la creazione degli oggetti della classe  classe <int>  oint;   classe <double> odouble;  come vedete sono specificati dentro le parentesi quadre < tipo> il tipo che deve essere sempre presente per dire al compilatore che tipo di dato deve elaborare qui abbiamo usato la costante const int NUM = 5;  ora faremo lo stesso programma senza l’ uso dei tipi specifici possiamo fare in modo che un array sia diverso dall’ altro uno conta un array da 5 e l’ altro da 3 vediamo il programma sviluppato tutto quello che cambia dal vecchio al nuovo  lo inserisco in giallo viene inserito un nuovo parametro nella formulazione  delle classi , int NUM , poi nella creazione degli oggetti viene inserito la grandezza dell’ array  classe <int  , 5 >  oint;   classe <double  , 3> odouble;  nei cicli viene inserito il numero del valore dell’ array 5 per oint e 3 per odouble   tutto il resto rimane invariato :



#include<iostream> using namespace std;

template <class T, int NUM > class classe{   array [NUM]; public:  

  classe(){     register int i;     for (i = 0; i < NUM; i++)array = i;   }    T &operator [](int i);  };



template<class T,int NUM> T & classe<T,NUM >::operator[](int i)

{   if (i<0 || i> NUM - 1)   {   cout << "\n Indice dell' Array " << i << " e' fuori dai parametri

concessi da "
<< NUM;     exit(1); 
  
}   return 
array; }         int  main () {

  classe <int, 5 >  oint;   classe <double, 3> odouble;    int i;

  cout << "\n Array intero :\n ";   for (i = 0; i < 5; i++)oint ;   for (i = 0; i < 5; i++)     cout << oint << "  : ";   cout<< endl;



  cout << "\n Array double :\n ";   for (i = 0; i < 3; i++)odouble =(double)i/5;   for (i = 0; i < 3; i++)     cout << odouble << "  :  ";  

    cout << "\n\n Per uscire premere un
tasto + invio : "; cin.get(); }



Anche le classi come le funzioni possono essere specializzate e per fare ciò basta sostituire la parola del template dal semplice (  template  < class T >  class  nome_classe { }; ) si scrive :
 
  template<>  class nome_classe < tipo >{};

dove logicamente tipo è il tipo di dato che desideriamo  questa è la sagoma generale per creare una classe indirizzata al tipo



Con le classi e le funzioni template  possiamo sostituire la parola riservata template < class T > con  template < typename T > usare class o  typename non ha differenza e nello stesso tempo avvisa al compilatore che  sotto mano usa un nuovo tipo anziché un nome di un oggetto  vediamo un esempio la funzione con tipo t  va e legge dentro l’ indirizzo di z e di x:

template <typename t> void funzione (t &z, t &x){};


Altra parola riservata è export   che anticipa la parola template quando si dichiara le funzioni , cosi concede ad altri file di usare il template export esporre solo la dichiarazione senza copiare l’ intera definizione  


Ciao grazie da ByMpt-Zorobabele


Testo PDF aggiornato con questo ultimo capitolo  inserito lo trovate :

http://www.freeforumzone.com/d/11266858/Elenco-figure-dei-comandi-della-programmazione-C-TESTO-PDF/discussione.aspx


Anche qui di queste discussioni che inserisco faccio un testo PDF da poter scaricare tutto il mio
materiale è da utilizzare come desiderate  per il testo PDF vedi cartella dedicata , ogni volta cambia ubicazione del testo  allora cambio il file e il testo lo inserisco dentro la cartella < file aggiornato ad oggi >

http://www.freeforumzone.com/d/11266858/Elenco-figure-dei-comandi-della-programmazione-C-TESTO-PDF/discussione.aspx




[Modificato da JehovaZorobabele 15/08/2016 13:21]
Vota: 15MediaObject1,91421
Amministra Discussione: | Chiudi | Sposta | Cancella | Modifica | Notifica email Pagina precedente | 1 | Pagina successiva
Nuova Discussione
 | 
Rispondi

Feed | Forum | Bacheca | Album | Utenti | Cerca | Login | Registrati | Amministra
Crea forum gratis, gestisci la tua comunità! Iscriviti a FreeForumZone
FreeForumZone [v.6.1] - Leggendo la pagina si accettano regolamento e privacy
Tutti gli orari sono GMT+01:00. Adesso sono le 14:13. Versione: Stampabile | Mobile
Copyright © 2000-2024 FFZ srl - www.freeforumzone.com