Newsgroup: it.comp.lang.c++
Titolo: Questione di stile

Salve a tutti,
ecco la mia domanda: se io ho più file header, conviene che io
metta in ognuno gli appropriati includes (sbattendomene delle
ripetizioni, peraltro gestite dal preprocessore), oppure, se
in un mio header è presente <vector>, e lo includo in un cpp
in cui serve std::vector, non includo <vector>?
So di essere stato un po' contorto, ma sono di fretta, scusate :)
Grazie in anticipo
--
Lupin85©
FILSer #2 - Founder di #fils
"It is not important what you believe, only that you believe"

 in cui serve std::vector, non includo <vector>?
IMHO la prima che hai detto.
Ogni file deve essere indipendente dagli altri.
Poi le inclusioni multiple verranno gestite dal preprocessore
col meccanismo degli #ifndef - #define - #endif
--
Gerolamo

Gerolamo, hai turbato la mia meditazione scrivendo questo:

Anche io sto facendo così, ma ero incerto sul fatto che fosse la
soluzione più elegante, anche se è quella che forse è più corretta
a livello logico.


 in cui serve std::vector, non includo <vector>?
Includi *sempre* gli header che servono per compilare correttamente il tuo
file, anche se pensi che siano già inclusi indirettamente da altri file.
Questo perché se il tuo progetto diventa abbastanza grande, potresti
incorrere in noiosi errori ogni volta che modifichi un header togliendo
qualche #include. E poi lo stile di includere sempre tutti gli header
necessari ti consente di avere un colpo d'occhio notevole sulle dipendenze
di ogni unità di compilazione.
Piuttosto, per snellire la compilazione ed evitare dipendenze inutili,
quando è possibile usa dichiarazioni forward per le classi invece di
includere l'intero header file che le definisce.
Ciao,
Marco

 includere l'intero header file che le definisce.
cosa intendi per dichiarazioni forward?
dichiarazione nell'header e definizione in un cpp?


 dichiarazione nell'header e definizione in un cpp?
No. Supponi di avere il seguente header file:
#include <pippo.h>    // in questo header è definita la classe Pippo
class Dummy {
public:
    Dummy();
    Pippo *getPippo() const;
private:
    Pippo *mypippo_;
};
//////////////////
Come vedi, in questo header file viene definita la classe Dummy; questa
utilizza evidentemente la classe Pippo (per qualsivoglia motivo) e quindi
c'è una dipendenza verso tale classe. Se noti bene però, in questo file
compaiono solamente dei *puntatori* a oggetti di tipo Pippo (potrebbero
anche essere reference, non cambia niente), e i puntatori sono tipi sempre
noti al compilatore anche se si riferiscono a classi non ancora definite.
Risultato: l'interfaccia della classe Dummy può essere compilata
correttamente senza aver bisogno di conoscere esattamente come è fatta la
classe Pippo (non vengono usati né suoi membri, né suoi metodi, né sue
istanze, ma solo puntatori a quest'ultime), quindi posso eliminare senza
problemi la direttiva #include <pippo.h>.
Ovviamente il compilatore deve però sapere che il simbolo Pippo esiste ed è
una classe, quindi al posto della direttiva di cui sopra basta scrivere la
seguente dichiarazione forward:
// #include <pippo.h> (eliminato)
class Pippo;    // questa è una dichiarazione forward, dice al compilatore
che Pippo è una classe
class Dummy {
...
};
Questo sistema è molto utile in quanto permette di eliminare la dipendenza
da <pippo.h>, con risultati notevoli sul tempo di compilazione in caso di
progetti di grandi dimensioni. Inoltre, questo potrebbe rivelarsi l'unico
modo per compilare unità che si richiedono a vicenda (inclusione ricorsiva).
Ovviamente nel file dell'implementazione di Dummy dovrai per forza includere
l'header <pippo.h> perché quando operi in qualche modo su istanze della
classe Pippo il compilatore deve sapere come questa classe è fatta.
Ciao,
Marco

 noti al compilatore anche se si riferiscono a classi non ancora definite.
In teoria avrebbe potuto anche essere definita cosě:
#include <pippo.h>    // in questo header č definita la classe Pippo
class Dummy {
public:
    Dummy();
    Pippo getPippo() const;
private:
    Pippo mypippo_;
};
e il discorso funzionerebbe ugualmente. Da quel che ho capito il
forward reference funziona fintanto che non viene richiamato una
funzione membro dell'oggetto in questione (come in questo caso).

 #include <pippo.h>    // in questo header č definita la classe Pippo
Lo scopo era proprio di togliere la dipendenza da <pippo.h> e quindi questa
direttiva #include.
    Marco

 funzione membro dell'oggetto in questione (come in questo caso).
No, in questo caso non basterebbe la dichiarazione forward perché
nell'esempio che hai scritto tu il compilatore ha bisogno di sapere la
dimensione della classe Pippo (per esigenze di allocazione), e la forward
declaration non dà nessun tipo di informazione a riguardo.
Nel caso del puntatore o reference a Pippo invece, non ci sono problemi
perché la dimensione di un puntatore o di un riferimento, di qualsiasi tipo,
è sempre nota.
Marco

 è sempre nota.
*sigh* ... crocifiggetemi in sala mensa! non so cosa avessi in testa
quando ho scritto quelle cose.