Newsgroup: it.comp.lang.c++
Titolo: problema con gli include

Salve a tutti. Sono un novellino in c++, e sto facendo uno dei classici
esercizi per fare un po' di pratica. Ho realizzato una classe Persona,
ed
ora sto realizzando la classe Studente, che eredita da Persona.
Tuttavia, mi si presenta un problema con gli include.
La classe Persona e' formata dal file persona.h e persona.cpp
La classe Studente e' formata dal file studente.h e studente.cpp
Nel file persona.cpp ho messo #include "persona.h"
Nel file persona.h non vi e' nessun include (eccetto che a funzioni di
libreria tipo iostream, anche se non so se era piu' corretto metterli
qui
o nel file .cpp)
Nel file studente.cpp ho messo #include "studente.h"
Nel file studente.h non vi e' nessun include
Se nel main del programma metto #include "persona.cpp", posso creare
oggetti di tipo Persona senza problemi.
Ma se tolgo  #include "persona.cpp" ed al suo posto vi metto #include
"studente.cpp", il linker dice "unresolved external
Persona::Persona(char*,int) referenced from project1.obj".
Come mai? Dal momento che la classe Studente, per ereditare da Persona,
include anche il file persona.h, il main non dovrebbe vedere ugualmente
la
classe persona come la classe Studente?
Ho risolto il problema mettendo entrambi gli include nel main, e negli
header file
le famose direttive #ifndef PERSONA_H ..... per evitare doppie
definizioni.
Tuttavia questa non mi sebra la soluzione corretta, probabilmente c'e'
un
mio errore di fondo da una qualche parte...
Qualcuno e' cosi gentile da spiegarmi cosa sto sbagliando?
Grazie, Alberto

oggetti di tipo Persona senza problemi.
i file cpp non vanno inclusi, sono gli header che vanno inclusi.
lo schema da seguire e`:
file persona.h
#ifndef PERSONA_H
#define PERSONA_H
/* include di eventuali altri header */
/* dichiarazioni relative alla classe persona  e funzioni
    inline */
#endif   // PERSONA_H
file persona.cpp
#include "persona.h"
/* altri eventuali include */
/* implementazione della classe persona */
file studente.h
#ifndef STUDENTE_H
#define STUDENTE_H
#ifndef PERSONA_H     // evita inutili aperture
  #include "persona.h"    // dell'header, se esso e`
#endif                // gia` stato incluso da qualche alta parte
/* include di eventuali altri header */
/* dichiarazioni relative alla classe studente  e funzioni
    inline */
#endif   // STUDENTE_H
file studente.cpp
#include "studente.h"   // include anche persona.h
/* altri eventuali include */
/* implementazione della classe studente */
Ti consiglio di rivedere l'uso degli header, trovi un spiegazione
dettagliata sul mio tutorial nel sito 
www.programmazione.it
Paolo
-----------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
-----------------------------------------------

 definizioni.
Va bene anche così, ma non è il massimo.
--
Alessandro Monti

 Qualcuno e' cosi gentile da spiegarmi cosa sto sbagliando?
Il metodo normale e':
persona.h
  #include eventuali header esterni
persona.cpp
  #include "persona.h"
studente.h
  #include "persona.h"
studente.cpp
  #incude "studente.h"
main.cpp
  #include "studente.h"
Compilazione:
  persona.cpp  -> persona.o (o .obj)
  studente.cpp  -> studente.o
  main.cpp  -> main.o
Linking:
  main.o persona.o studente.o  -> eseguibile finale
	Mauro

 persona.cpp.
Ok, ora ho le idee piu' chiare, in effetti ottengo solo errori da parte del
linker.
Ma come posso linkare questi file .obj? Il BCB3 non dovrebbe farlo da solo?
Ho guardato nella directory dove tengo il progetto, ma non viene creato
nessun file .o oppure .obj, di obj vi e' solo il "project.obj".
Spero che queste operazioni possano essere eseguite automaticamente,
altrimenti se in un progetto uso, per esempio, 50 classi, devo linkare 50
file .obj, che tra l'altro non vedo neppure la loro esistenza nella
directory....
Grazie di nuovo, Alberto


Cioè, una precisazione. Supponiamo di avere una classe
class Prova
{
    std::list <int> lista;
}
dove inserisci l'header <list>, nel .cpp o nel .h ? Perchè essendo il membro
privato in realtà non sarebbe necessario inserire l'include nell'header, ma
basterebbe metterlo solo nel file .cpp che effettivamente utilizza l'oggetto
lista e nel file .h basterebbe mettergli una dichiarazione forward "class
list" solo che essendo un template ed essendo dentro il namespace std
diventa un casino fare questa dichiarazione. Cosa si fa comunemente in
questi casi? Ciao e grazie, FBF.

 basterebbe metterlo solo nel file .cpp che effettivamente utilizza l'oggetto
Il fatto che il membro sia privato o pubblico non fa differenza,
tutti quelli dichiarati nell'header hanno bisogno dell'#include
(o della forward decl. se solo puntatori).
Per le classi della libreria standard non si puo' usare la
forward decl., ma e' necessario l'#include.  Per gli stream
si puo' usare #include <iosfwd> che e' piu' leggero di <iostream>
e si limita alle dichiarazioni.
	Mauro

#endif   // PERSONA_H
[.....]
Un po' mi ritrovo in quello che hai detto. Cioe' se in OWL ho la
classe TWindow e da essa derivo un'altra classe, il riferimento a
"window.h" va' messo chiaramente nel file di dichiarazione. Ma se nel
file di implementazione della nuova classe ho bisogno dei servizi di
una classe esterna, ad esempio la classe TUIFace, l'include di tale
classe va' messo nel file di dichiarazione o nel file di
implementazione? Io di solito lo metto nel file di implementazione
della classe anche perche' tali servizi vengono usati solo in alcuni
metodi della nuova classe. Che relazione ha questo tipo di
disposizione degli include con la peculiarita' di molti compilatori di
precompilare gli header (precompiled headers)? Cioe' se tale opzione
e' attivata, e' piu' conveniente (per ridurre anche i tempi di
compilazione) mettere l'ultimo tipo di include da me descritto nel
file di dichiarazione o in quello di implementazione?
Bye.

precompilare gli header (precompiled headers)?
Per quanto riguarda gli header precompilati, essi sono efficienti solo
se gli header non subiscono modifiche, altrimenti e` necessario
ricompilarli. Quindi e` conveniente includere all'inizio dei file solo
gli header piu` stabili e usare la direttiva
#pragma hdrstop
per evitare la procompilazione di header poco stabili. In tal modo
si ottiene il massimo dagli header precompilati.
C'era un interessante articolo su questo in un vecchio numero
di computer programming, non ricordo quale ma in sostanza
il punto era quello che ho appena esposto.
