Nieudane podzielenie programu na moduły

0

Witam, może tytuł trochę nie bardzo ale nie wiedziałem jak to inaczej nazwać. Ćwiczę dzielenie programu na moduły i napotkałem problem którego nie mogę ominąć. Stworzyłem trzy pliki. Oto one:
test.cpp:

#include <iostream>

using namespace std;

#include "symbol.hpp"

int main()
{

return 0;
} 

symbol.hpp

 #ifndef SYMBOLE_HH
#define SYMBOLE_HH

#include <iostream>
using namespace std;

enum Symbol { e, a, b, c, d };

Symbol tab_dod[5][5] = {{e,a,b,c,d},{a,d,e,b,c},{b,e,c,d,a},{c,b,d,a,e},{d,c,a,e,b}}; 
Symbol tab_mno[5][5] = {{e,e,e,e,e},{e,d,c,a,b},{e,c,d,b,a},{e,a,b,c,d},{e,b,a,c,d}}; 
Symbol tab_ode[5][5] = {{e,b,a,d,c},{a,e,d,c,b},{b,c,e,a,d},{c,d,b,e,a},{d,a,c,b,e}};
Symbol tab_dzi[5][4] = {{e,e,e,e},{c,d,a,b,},{d,c,b,a},{b,a,c,d},{a,b,d,c}};

#endif

symbol.cpp

#include "symbol.hpp"

Symbol operator +(Symbol z1, Symbol z2)
{
return tab_dod[z1][z2];
}

Symbol operator *(Symbol z1, Symbol z2)
{
return tab_mno[z1][z2];
}

Symbol operator -(Symbol z1, Symbol z2)
{
return tab_ode[z1][z2];
}

Symbol operator /(Symbol z1, Symbol z2)
{
if(z2 != e)
return tab_dzi[z1][z2];
else
  {
    cerr << endl << "    Blad! Proba dzielenia przez czynnik neutralny dodawania" << endl<< endl;
    return e;
  }
}

istream &  operator >> (istream &  StrmWej, Symbol &  WczytSym)
{
  Symbol TabSymboli[] = {a,b,c,d,e};
  char   ZnakSymbolu;
  
  StrmWej >> ZnakSymbolu;
  if (ZnakSymbolu < 'a' || 'e' < ZnakSymbolu) {
    cerr << "Blad! Wprowadzony znak nie odpowiada zadnemu symbolowi."
         << endl;
  }
  WczytSym =  TabSymboli[ZnakSymbolu-'a'];
  return StrmWej;
}

ostream & operator << ( ostream & StrmWy, Symbol x )
{
  StrmWy << "eabcd"[x];
  return StrmWy;
} 

Program próbuję kompilować następującymi poleceniami:
g++ -c test.cpp
g++ -c symbol.cpp
g++ -o test test.o symbol.o

I ciągle dostaję w odpowiedzi błędy o następującej treści:

symbol.o:(.data+0x0): multiple definition of tab_dod' test.o:(.data+0x0): first defined here symbol.o:(.data+0x80): multiple definition of tab_mno'
test.o:(.data+0x80): first defined here
symbol.o:(.data+0x100): multiple definition of tab_ode' test.o:(.data+0x100): first defined here symbol.o:(.data+0x180): multiple definition of tab_dzi'
test.o:(.data+0x180): first defined here
collect2: ld returned 1 exit status

Kod programu to zwykłe podstawy niemniej jednak nie mam pojęcia dlaczego kompilator mówi że jest powtórna definicja tablic. Zwracam uwagę na to, że zastosowałem instrukcje warunkowe preprocesora.
Jeżeli komuś uda się to skompilować to prosiłbym o polecenia jakimi to skompilował. Całkiem możliwe, że jest tutaj jakiś banalny błąd którego akurat w tym momencie nie widzę. Z góry dziękuję za pomoc. Pozdrawiam
sznajder
Sędziwy Jeż

Posty: 36
Dołączył(a): 05 cze 2008 14:18
Płeć: Mężczyzna
Wersja Ubuntu: 10.10
Środowisko graficzne: LXDE
Architektura: x86_64
Góra

0

Tworzysz zmienne globalne, w pliku nagłówkowym powinny byc tylko ich deklaracje (zrobiłeś definicje) poza tym słówko extern żeby kompilator wiedział że korzystasz ze zmiennej globalnej.
Ok, wiec test.cpp bez zmian.
symbol.hpp

 #ifndef SYMBOLE_HH
#define SYMBOLE_HH
 
#include <iostream>

using namespace std;
 
enum Symbol { e, a, b, c, d };
 
extern Symbol tab_dod[5][5];
extern Symbol tab_mno[5][5];
extern Symbol tab_ode[5][5];
extern Symbol tab_dzi[5][4];

#endif 

symbol.cpp

#include "symbol.hpp"

Symbol tab_dod[5][5] = {{e,a,b,c,d},{a,d,e,b,c},{b,e,c,d,a},{c,b,d,a,e},{d,c,a,e,b}}; 
Symbol tab_mno[5][5] = {{e,e,e,e,e},{e,d,c,a,b},{e,c,d,b,a},{e,a,b,c,d},{e,b,a,c,d}}; 
Symbol tab_ode[5][5] = {{e,b,a,d,c},{a,e,d,c,b},{b,c,e,a,d},{c,d,b,e,a},{d,a,c,b,e}};
Symbol tab_dzi[5][4] = {{e,e,e,e},{c,d,a,b,},{d,c,b,a},{b,a,c,d},{a,b,d,c}};

Symbol operator +(Symbol z1, Symbol z2)
{
return tab_dod[z1][z2];
}
 
Symbol operator *(Symbol z1, Symbol z2)
{
return tab_mno[z1][z2];
}
 
Symbol operator -(Symbol z1, Symbol z2)
{
return tab_ode[z1][z2];
}
 
Symbol operator /(Symbol z1, Symbol z2)
{
if(z2 != e)
return tab_dzi[z1][z2];
else
  {
    cerr << endl << "    Blad! Proba dzielenia przez czynnik neutralny dodawania" << endl<< endl;
    return e;
  }
}
 
istream &  operator >> (istream &  StrmWej, Symbol &  WczytSym)
{
  Symbol TabSymboli[] = {a,b,c,d,e};
  char   ZnakSymbolu;
 
  StrmWej >> ZnakSymbolu;
  if (ZnakSymbolu < 'a' || 'e' < ZnakSymbolu) {
    cerr << "Blad! Wprowadzony znak nie odpowiada zadnemu symbolowi."
         << endl;
  }
  WczytSym =  TabSymboli[ZnakSymbolu-'a'];
  return StrmWej;
}
 
ostream & operator << ( ostream & StrmWy, Symbol x )
{
  StrmWy << "eabcd"[x];
  return StrmWy;
}  
0

No i tak w ogóle używanie using namespace std; w pliku nagłówkowym w przestrzeni globalnej może prowadzić do błędów kompilacji, przy odpowiednim zbiegu okoliczności. ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1