Newsgroup: it.comp.lang.c++
Titolo: [OT?] [Lunghissimo] problemino linkando due files

Ciao a tutti!
Prima di tutto mi scuso se il problema
dovesse risultare OT.
Veniamo al dunque:
ho scritto una piccolo sorgente per
la gestione di variabili per un futuro ipotetico
metacompilatore.
Poi ho fatto un altro programmino che permetta
di sfruttare il primo (tanto per controllarne gli errori)
simulando la creazione di variabili, tipi e altra
roba del genere.
Mi sono piccato di creare il gestore di variabili
tramite oggetti e sfruttando l'ereditarieta',
ad esempio esiste una classe
El_var
che contiene membri comuni
alle classi derivate Variabile e Costante.
(in fondo al messaggio c'e' un riassunto del codice
del gestore di variabili)
Compilando risulta tutto ok
(a parte ovviamente la mancanza della
funzione main() )
Quando poi compilo l'altro programma (quello
che dovrebbe sfruttare il gestore di variabili)
non viene rilevato alcun errore fino al momento del linking.
Gli errori del linker sono tutti di tipo:
Unresolved External [namespace del gestore]::[classe]::[membro]
referenced from [nome file].OBJ.
al variare di tutti i membri di ciascuna classe
e di tutte le classi del gestore di variabili (sono una caterva di errori).
Non riesco a capire cosa sbaglio
Premetto che e' uno dei primi programmi in C++ che scrivo,
ed il primissimo che cerco di scrivere sfruttando l'ereditarieta'
di oggetti, gli errori potrebbero essere grossolani e stupidi.
//file tables.cpp
#include <list>
#include <string>
#include <vector>
#include <ostream>
namespace tvl {
 // classi per le eccezioni
 // ...
 // classi per gli oggetti
 class Elemento;
 class Variabile;
 class El_var;
 class El_tipo;
 typedef std::list<El_var> tavola_var;
 typedef std::list<El_tipo> tavola_tipi;
 typedef std::list<Elemento> tavola;
 typedef std::list<Variabile*> rev_pun;
 typedef std::vector<bool> bits;
 class Bytes {
// ...
 };
 class Var_bytes: public Bytes {
// ...
 };
 class Elemento {
  protected:
  std::string nome;
  public:
  virtual ~Elemento() {};     // distruttore virtuale, se si distrugge un
"Elemento" chiama il
            // giusto distruttore della classe derivata
  virtual int is_sep()=0;
  virtual std::string id() {return nome
  bool operator!=(const std::string& s) const {return (nome!=s);};    //
serve per find!
  bool operator==(const std::string& s) const {return (nome==s);};
 };
 class El_tipo: public Elemento {
  public:
  virtual ~El_tipo() {};
  virtual int is_sep() {return 0;}
  virtual void def_var(std::string a);   // definizione di variabile
  virtual void def_cos(std::string a, Bytes b); // definizione di costante
  virtual void def_sep();       // definizione di separatore di ambienti
  virtual void rem_var(std::string a);   // rimozione di El_var
  virtual tavola_var& tav_var();     // riferimento alla tavola di El_var
(*pt)
  virtual El_var& var(std::string a);    // riferimento alla El_var a
  virtual unsigned long int res_mem();   // memoria riservata per un
elemento
 };
 class El_var: public Elemento {
  public:
  virtual ~El_var() {};
  virtual int is_sep() {return 2;}  // nel dubbio lo considero separatore
(come bool) tuttavia non e' 1 ma 2
  virtual int is_cos() {return 2;}  // lo considero costante nel dubbio, ma
come sopra
  virtual Var_bytes& val() const;   // riferimanto alla Var_bytes di El_var
  virtual Bytes cos_val() const;   // valutazioni non modificabili (crea un
nuovo Bytes)
  virtual void rif(Var_bytes& v);   // riferisce la El_var a v
  virtual std::string binario();   // esprime il valore della variabile in
codice binario
 };
 class Tipo: public El_tipo {
// ...
 };
 class Variabile: public El_var {
//...
 };
 class Flvar: public Variabile {
// ...
 };
 class Mlvar: public Variabile {
// ...
 };
 class Separatore: public El_var {
// ...
 };
 class Costante: public El_var {
// ...
 };
}
// file "interfaccia.cpp"
#include "tables.cpp"
#include <string>
#include <iostream>
#include <conio.h>
using namespace tvl;
using namespace std;
tavola_tipi table;   // QUESTA LINEA AD ESEMPIO GENERA
     // GLI ERRORI DEL TIPO:
     // Unresolved external tvl::El:type::[membro di El_type] in
"interfaccia.cpp"
// ...
// funzioncine varie di input ed output
// ...
int main() {
 // ...
};
ciao.
    Sprite
Ps: non so se sia un info utile, comunque utilizzo Borland 5.5
(versione gratuita) per compilare

 #include "tables.cpp"
E' in genere meglio spezzare le definizioni di classe in due file, ad
esempio:
- tables.h che contiene le dichiarazioni
- tables.cpp che contiene le definizioni
Dopodichè includi tables.h (e non tables.cpp) nel file che utilizza le
classi in questione, compili tables.cpp (il chè ti crea un .obj), e infine
compili interfaccia.cpp e fai il link.
Non che sia totalmente sbagliato includere un file .cpp in un altro, ma è
una cosa che è sempre meglio evitare per una serie di motivi, che non sto
qui a spiegarti.