Differences

This shows you the differences between two versions of the page.

Link to this comparison view

appunti3s:sorgenti_multifile [2018/04/25 07:55] (current)
Line 1: Line 1:
 +====== Sorgenti multifile ======
 +Durante la realizzazione di un software costituito da un //main()// e numerose funzioni, può risultare utile dividere "​fisicamente"​ il codice del programma, in più file sorgenti.
 +In questo modo diventa più facile apportare modifiche e leggere il codice, soprattutto nei programmi di grandi dimensioni.
 +Inoltre, siccome in certi casi il compilatore può compilate le singole parti anche individualmente,​ in caso di modifiche ad uno dei file sorgenti non è necessario ricompilare tutto il programma, ma solo il file modificato. Comunque tutti i file sorgente appartenenti allo stesso programma dovranno essere contenuti in una sola cartella.
  
 +
 +Nel seguente esempio riprenderemo un semplicissimo programma, che sarebbe stato inutile dividere in più file, ma che comunque divideremo per esercizio, per poter capire come procedere anche nei casi più complicati.
 +
 +<file c main.cpp>​
 +/** @file main.cpp ​
 +*
 +*/
 +
 +#include <​iostream>​
 +
 +int triplicare(int x) 
 +{
 +  return 3*x;
 +}
 + 
 +int main()
 +{
 +  int mioNumero,​mioTriplo;​
 + 
 +  std::cout << "Per favore scrivi un numero intero: ";
 +  std::cin >> mioNumero;
 +  mioTriplo = triplicare(mioNumero);​ // chiamata della funzione
 +  std::cout << "il triplo di " << mioNumero << " vale "
 +            << mioTriplo << endl;
 +  return 0;
 +}
 +</​file>​
 +
 +La cosa che sembra più semplice da fare è quella di dividerlo in due file sorgenti.
 +
 +ATTENZIONE: c'è grave un errore nel seguente file //​main.cpp//​! Infatti non basta spezzare il codice in due parti... per comprendere l'​errore bisogna aver compreso l'​importanza delle //​[[appunti3s:​programmi_procedurali#​dichiarazioni]]//​.
 +<file c triplicare.cpp>​
 +/** @file triplicare.cpp ​
 +*
 +*/ 
 +int triplicare(int x) 
 +{
 +  return 3*x;
 +}
 +</​file>​
 +
 +<file c main.cpp>​
 +/** @file main.cpp ​
 +*
 +*/ 
 +
 +#include <​iostream>​
 +// ERRORE qui manca una dichiarazione
 +
 +int main()
 +{
 +  int mioNumero,​mioTriplo;​
 + 
 +  std::cout << "Per favore scrivi un numero intero: ";
 +  std::cin >> mioNumero;
 +  mioTriplo = triplicare(mioNumero);​ // chiamata della funzione
 +  std::cout << "il triplo di " << mioNumero << " vale "
 +            << mioTriplo << endl;
 +  return 0;
 +}
 +</​file> ​
 +                                             
 +NOTA: bisogna usare **#include <​iostream>​** SOLO dove serve! Cioè dove si vuole fare Input/​Output.
 +
 +Quando il compilatore legge il contenuto del file //main()// trova la chiamata alla funzione //​triplicare()//​ ma non può verificarne la correttezza del passaggio dei parametri. È necessario far precedere il //main()// con la //​dichiarazione//​ della funzione che si vuole usare.
 +<​code>​int triplicare(int x);</​code>​
 +Dopo questa correzione, i due file sorgente non vanno compilati separatamente,​ bisogna comunicare al compilatore che da questi due file sorgente si deve ottenere un unico file eseguibile.
 +
 +  * Il primo comando serve a generare due file oggetto (compilatore)
 +    * <​code>​g++ -c main.cpp triplicare.cpp</​code>​
 +  * Il secondo comando serve a collegarli in un unico file eseguibile (linker)
 +    * <​code>​g++ main.o triplicare.o -o triplica.exe</​code>​
 +
 +In questo modo il programma viene compilato senza errori, ma il codice può essere ancora migliorato. ​
 +Infatti, se per poter usare //​std::​cout//​ è necessaria la direttiva //​include//,​ allo stesso modo, una simile direttiva potrebbe essere utilizzata anche per usare //​triplicare()//​.
 +
 +Si può creare un nuovo file di intestazione (header file) chiamato //​triplicare.h//​ e contenente le dichiarazioni di tutte le funzioni del file //​triplicare.cpp//,​ includendolo al posto della precedente dichiarazione di //​triplicare()//​. Anche se in questo semplice caso esiste una sola funzione. Ecco come si presenterebbe la soluzione finale:
 +
 +<file c triplicare.h>​
 +/** @file triplicare.h ​
 +*
 +*/ 
 +int triplicare(int x);
 +</​file>​
 +
 +<file c triplicare.cpp>​
 +/** @file triplicare.cpp ​
 +*
 +*/ 
 +int triplicare(int x) 
 +{
 +  return 3*x;
 +}
 +</​file>​
 +
 +<file c main.cpp>​
 +/** @file main.cpp ​
 +*
 +*/ 
 +
 +#include <​iostream>​
 +#include "​triplicare.h"​
 +
 +int main()
 +{
 +  int mioNumero,​mioTriplo;​
 + 
 +  std::cout << "Per favore scrivi un numero intero: ";
 +  std::cin >> mioNumero;
 +  mioTriplo = triplicare(mioNumero);​ // chiamata della funzione
 +  std::cout << "il triplo di " << mioNumero << " vale "
 +            << mioTriplo << endl;
 +  return 0;
 +}
 +</​file> ​
 +La differenza tra le virgolette di "​triplicare.H"​ e <​iostream>​ sta nel differente percorso dei file. Le virgolette si usano quando uso un percorso relativo agli altri file sorgente.
 + 
 +Si può pensare a //​iostream//​ come all'​interfaccia che permette di usare //​std::​out//​ e a //​triplicare.h//​ come all'​interfaccia che permette di usare //​triplicare()//​.
 +
 +Nulla vieta di racchiudere tutti gli header necessari al //​main.cpp//​ in un nuovo header, //main.h//
 +
 +<file c main.h>
 +/** @file main.h ​
 +*
 +*/ 
 +#include <​iostream>​
 +#include "​triplicare.h"​
 +</​file>​
 +
 +{{ :​appunti3s:​header_file.png |}}
  • appunti3s/sorgenti_multifile.txt
  • Last modified: 2018/04/25 07:55
  • (external edit)