|
[+] C++ - kompilacja kilku plików
zygi151 - 03-01-2009 21:39
Mam kilka plików do kompilacji mianowicie:W k1.cpp znajdują się definicje 2 funkcji. Podczas kompilowania (z pliku main.cpp wyłączam funkcje które są definiowane w k1.cpp):
g++ main.cpp -Wall -o main.o
Proces kompilacji przebiega bez problemu. Jednak gdy do main.cpp dopisuje funkcję (pokaz) z pliku k1.cpp, to podczas kompilacji wypisuje mi taki błąd:
/tmp/ccOpUTWf.o: In function `main': main.cpp:(.text+0xe1): undefined reference to `zespolona::pokaz()' collect2: ld returned 1 exit status
I nie bardzo rozumiem o co chodzi.
Deklaracja funkcji jest w pliku k1.h, a definicja wygląda bardzo prosto (plik k1.cpp):
void zespolona::pokaz() { cout << rzeczyw << endl << urojon << endl; }
Próbowałem też kompilować w ten sposób:
g++ k1.cpp main.cpp -Wall -o main.o
ale dostawałem takie błędy:
k1.cpp: In constructor ‘zespolona::zespolona(numer)’: k1.cpp:4: error: ‘ob’ has incomplete type k1.cpp:1: error: forward declaration of ‘struct numer’
Jeśli wszystko zapakuję do pliku main.cpp to proces kompilacji przechodzi pomyślnie. Ktoś by mógł powiedzieć, że skoro są to dwie proste klasy i taki prymitywny program, to dlaczego nie wpisać tego do jednego pliku (main.cpp). Dobrze można. Ale co z tego jak w dalszym ciągu nie będę umiał poradzić sobie z wyżej wymienionym problemem?
Aha, przepisałem to w Dev-C++ tam program robi Makefile, ale ten także zwraca błędy podobne do wyżej wymienionych.
Z góry dziękuję za jakiekolwiek rady, propozycje, sugestie.
pietrzuch - 03-01-2009 22:29
/tmp/ccOpUTWf.o: In function `main': main.cpp:(.text+0xe1): undefined reference to `zespolona::pokaz()' collect2: ld returned 1 exit status
Komunikat oznacza że nie widzi takiej funkcji. Najprawdopodobniej jest to spowodowane złym includowaniem plików, dlatego ja stosuje zamiast *.cpp *.hpp. (mam tylko jedno main.cpp) Dopisz w main.cpp: extern zespolona::pokaz();
I powinno pomóc. ;-)
Theq - 03-01-2009 22:38
O sesja sie zbliza :) Pokaz caly kod to wskazemy bledy. Tak przy okazji, to opcja "-o" g++ wiaze sie z nazwa pliku wynikowego (nie ma nic wspolnego z plikami ".o").
[ Dodano: 2009-01-03, 22:55 ] W ramach odswiezenia, prosty przyklad jak to zrobic:
Plik k1.h #ifndef K1_H #define K1_H
class Zespolona { private: int _r; int _u;
public: int pokazR(); int pokazU(); Zespolona(int r = 0, int u = 0) { _r = r; _u = u; } };
#endif
Plik k1.cpp #include "k1.h"
int Zespolona::pokazR() { return _r; }
int Zespolona::pokazU() { return _u; }
Plik main.cpp #include <iostream> #include "k1.h"
int main() { Zespolona a, b(5, 1);
std::cout << a.pokazR() << " " << a.pokazU() << std::endl; std::cout << b.pokazR() << " " << b.pokazU() << std::endl; }
Kompilacja: g++ main.cpp k1.cpp -o zespolone
zygi151 - 04-01-2009 00:25
O sesja sie zbliza :)
Nie zupełnie - nie studiuje - c++ to dla zaspokojenia ambicji ;p hi hi lubię coś robić, więc wspaniały język daje dużo satysfakcji, co prawda jestem początkujący ale jak wszystko ogarnę to coś ciekawego napisze (mam nadzieję) - dobrze bo już chyba off topic.
Tak więc to się staram skompilować. Robiony na podstawie przykładu z Symfonia c++ str.775 (trochę bardziej uproszczony) faktycznie powinienem kompilować *.cpp, a nie tylko main,cpp. Tak więc ostatecznie błędy są trochę inne (przepraszam za podanie wcześniejszych, tym samym robienie 'zamieszania'). O to moje pliki.
K1.h
#ifndef K1_h #define K1_h class numer;
#include <iostream> using namespace std; #include <string>
class zespolona { double rzeczyw; double urojon; public: zespolona(double r=0, double i=0 ) : rzeczyw(r), urojon(i) {} zespolona( numer ); friend zespolona dodaj(zespolona, zespolona); void pokaz(); };
#endif
k1.cpp
class numer; #include "k1.h"
zespolona::zespolona(numer ob) { rzeczyw = ob.n ; urojon = 0 ; }
void zespolona::pokaz() { cout << rzeczyw << endl << urojon << endl; }
k2.h
#ifndef K2_h #define K2_h
class zespolona;
#include <iostream> using namespace std; #include <string>
class numer { double n; string opis; friend zespolona::zespolona(numer); public: numer(double k, string t="opis") : n(k), opis(t) {} };
#endif
main.cpp
#include <iostream> #include "k1.h" #include "k2.h" using namespace std;
zespolona dodaj(zespolona a, zespolona b);
int main() { zespolona a,c; a.pokaz(); numer b(3.3, "napis"); return 0; }
zespolona dodaj(zespolona a, zespolona b) { zespolona wynik; wynik.rzeczyw = a.rzeczyw + b.rzeczyw; wynik.urojon = a.urojon + b.urojon; return wynik; };
kompilacja:
zygi@debian-dawid:~/c/operator_kon$ g++ main.cpp k1.cpp -Wall -o zespol k1.cpp: In constructor ‘zespolona::zespolona(numer)’: k1.cpp:4: error: ‘ob’ has incomplete type k1.cpp:1: error: forward declaration of ‘struct numer’
Jeśli wszystko jest wpisane w main.cpp w kolejności k1.h k2.h k1.cpp main.cpp - to wszystko jest w porządku.
grzesiek - 04-01-2009 08:14
Problem z logicznym łączeniem plików. Przetestowałem - dział. k1.h #ifndef K1_h #define K1_h class numer;
#include <iostream> using namespace std; #include <string>
class zespolona { double rzeczyw; double urojon; public: zespolona(double r=0, double i=0 ) : rzeczyw(r), urojon(i) {} zespolona( numer ); friend zespolona dodaj(zespolona, zespolona); void pokaz(); };
#endif
k1.cpp #include "k1.h" #include "k2.h"
class numer;
zespolona::zespolona(numer ob) { rzeczyw = ob.n ; urojon = 0 ; }
void zespolona::pokaz() { cout << rzeczyw << endl << urojon << endl; }
k2.h #ifndef K2_h #define K2_h
class zespolona;
#include <iostream> using namespace std; #include <string>
class numer { double n; string opis; friend zespolona::zespolona(numer); public: numer(double k, string t="opis") : n(k), opis(t) {} };
#endif
main.cpp #include <iostream> #include "k1.cpp" #include "k2.h" using namespace std;
zespolona dodaj(zespolona a, zespolona b);
int main() { zespolona a,c; a.pokaz(); numer b(3.3, "napis"); return 0; }
zespolona dodaj(zespolona a, zespolona b) { zespolona wynik; wynik.rzeczyw = a.rzeczyw + b.rzeczyw; wynik.urojon = a.urojon + b.urojon; return wynik; };
Theq - 04-01-2009 10:47
Nie zupełnie - nie studiuje - c++ to dla zaspokojenia ambicji ;p hi hi lubię coś robić, więc wspaniały język daje dużo satysfakcji, co prawda jestem początkujący ale jak wszystko ogarnę to coś ciekawego napisze (mam nadzieję)
W takim razie poczytaj o zaleznosciach cyklicznych (circular dependencies) i dlaczego unikac ich stosowania. Twoj kod to wlasnie przyklad takiej zaleznosci. No i powodzenia w dalszej nauce :)
k1.h #ifndef K1_h #define K1_h
#include <iostream> using namespace std; #include <string>
class numer;
class zespolona { double rzeczyw; double urojon; public: zespolona(double r=0, double i=0 ) : rzeczyw(r), urojon(i) {} zespolona( numer ); friend zespolona dodaj(zespolona, zespolona); void pokaz(); };
#endif
k1.cpp #include "k1.h" #include "k2.h"
zespolona::zespolona(numer ob) { rzeczyw = ob.n ; urojon = 0 ; }
void zespolona::pokaz() { cout << rzeczyw << endl << urojon << endl; }
k2.h #ifndef K2_h #define K2_h
#include <iostream> using namespace std; #include <string>
class zespolona;
class numer { double n; string opis; friend zespolona::zespolona(numer); public: numer(double k, string t="opis") : n(k), opis(t) {} };
#endif
main.cpp #include <iostream> #include "k1.h" #include "k2.h"
using namespace std;
zespolona dodaj(zespolona a, zespolona b);
int main() { zespolona a,c; a.pokaz(); numer b(3.3, "napis"); return 0; }
zespolona dodaj(zespolona a, zespolona b) { zespolona wynik; wynik.rzeczyw = a.rzeczyw + b.rzeczyw; wynik.urojon = a.urojon + b.urojon; return wynik; }
zygi151 - 04-01-2009 12:23
Dziękuję wszystkim za odpowiedzi. Odnośnie zależności cyklicznych znalazłem to:
http://en.wikipedia.org/wiki/Circular_dependency
Może komuś się przyda - "przyszłemu pokoleniu".
zanotowane.pldoc.pisz.plpdf.pisz.plminister.pev.pl
|