Undefined reference problem z konsolidacją plików nagłówkowych

Odpowiedz Nowy wątek
2013-02-28 20:22

Rejestracja: 8 lat temu

Ostatnio: 6 lat temu

0

Oczywiscie spedzilem swoje kilka godzin z panem googlem i milionami innych forow programistycznych, gdzie inni mieli podobne problemy, niestety na zadnym z nich nie znalazlem odpowiedzi na moj problem. Przeczytalem takze kwadrylion tutoriali na necie, moja ksiazke z ktorej korzystam czasem podczas programowania, wyprobowalem kazdy pomysl jaki mi przychodzi do glowy, ale nie wiem gdzie jest blad (przebudowywanie, ponowne dodawanie plikow do projektu, dodawanie odpowiednich flag kompilatora w opcjach, wszystkie możliwe kombinacje dyrektyw include w roznych plikach, dodwanie extern przed definicjami funkcji i bog wie go co tam jeszcze - podczas 4h jakie spedzilem na rozwiazywnaiu tego problemu, rozwiazan bylo wiele).

Uzywam CodeBlocks 12.11 i kompilatora MinGW (g++).

Podczas pisania prostej gierki w allegro 4.2.2 moj kod zaczal sie troszke rozsrastac i postanowilem go elegancko sobie podzielic na rozne pliki. Oczywiscie stworzylem nowy projekt i dodalem odpowiednio "init.h" i "init.cpp" do projektu. Przeniosłem do "init.h" deklaracje funkcji i klas a do "init.cpp" ich definicje.

Niestety wywala mi błąd:

-------------- Build: Debug in CARS 2D (compiler: GNU GCC Compiler)---------------

mingw32-g++.exe -Wall    -ID:\DEVPAKS\include -IE:\Programy\CodeBlocks\MinGW\include  -c "C:\Documents and Settings\Przemek\Moje dokumenty\C++\ALLEGRO\CARS 2D\CARS 2D\main.cpp" -o obj\Debug\main.o
C:\Documents and Settings\Przemek\Moje dokumenty\C++\ALLEGRO\CARS 2D\CARS 2D\main.cpp: In function 'void samochodzik()':
C:\Documents and Settings\Przemek\Moje dokumenty\C++\ALLEGRO\CARS 2D\CARS 2D\main.cpp:5:17: error: 'car1' was not declared in this scope
C:\Documents and Settings\Przemek\Moje dokumenty\C++\ALLEGRO\CARS 2D\CARS 2D\main.cpp:8:14: error: 'track' was not declared in this scope
C:\Documents and Settings\Przemek\Moje dokumenty\C++\ALLEGRO\CARS 2D\CARS 2D\main.cpp:8:21: error: 'buffer' was not declared in this scope
In file included from C:\Documents and Settings\Przemek\Moje dokumenty\C++\ALLEGRO\CARS 2D\CARS 2D\main.cpp:1:0:
C:\Documents and Settings\Przemek\Moje dokumenty\C++\ALLEGRO\CARS 2D\CARS 2D\init.h: At global scope:
C:\Documents and Settings\Przemek\Moje dokumenty\C++\ALLEGRO\CARS 2D\CARS 2D\init.h:12:13: warning: inline function 'void init()' used but never defined [enabled by default]
C:\Documents and Settings\Przemek\Moje dokumenty\C++\ALLEGRO\CARS 2D\CARS 2D\init.h:13:13: warning: inline function 'void deinit()' used but never defined [enabled by default]
Process terminated with status 1 (0 minutes, 0 seconds)
3 errors, 2 warnings (0 minutes, 0 seconds)

Wnioskuje ze kompilator po prostu nie widzi definicji funkcji zawartych w pliku "init.cpp".

Zawartosci plikow:

main.cpp:

#include "init.h"

void samochodzik()
{
    Car player1(car1, 0.5, 120, 370, ARROWS);
    while(true)
    {
        blit(track, buffer, 0,0,0,0, track->w, track->h);
        player1.player_move();
        player1.move();
        player1.draw_on_buffer();
        blit(buffer, screen, 0,0,0,0, buffer->w, buffer->h);
        clear_to_color(buffer, makecol(255,255,255));
        rest(30);
    }
}
int main()
{
    init();

    deinit();
    return 0;
}
END_OF_MAIN()

"init.h"

#ifndef init_h
#define init_h

#include <allegro.h>
#include <cmath>
#define grass_color 1024
#define road_color 50712
#define black_color 0
///deklaracje funkcji i klas:
enum control{WSAD, ARROWS};

inline void init();
inline void deinit();

class Car
{
private:
    double tab_sin[72];
    double tab_cos[72];

    const static int max_speed = 30; //maksymalna predkosc
    const static int min_speed = -5; //minimalna predkosc (predkosc cofania)
    control keys;
    int x,y; //pozycja samochodu na ekranie
    int dx, dy; //przesuniecie samochodu wzgledem osi OX i OY
    int angle; //kat pod jakim jest samochod
    double speed; //obecna predkosc samochodu
    double acc; //przyspieszenie samochodu
    double friction; //tarcie powierzchni na jakiej znajduje sie auto
    BITMAP *sprite;// sprite z jakiego jest pobierany wyglad samochodu

    void fill_sin_cos();
    void increase_speed();
    void decrease_speed();
    void turn_right();
    void turn_left();
    void change_friction();
public:
    Car(BITMAP* _sprite, double _acc, int _x, int _y, control _keys); //sprajt auta, przyspieszenie auta, wspolrzedne startowe, sposob sterowania (strzalki/wsad)
    void move(); //odpowiada za ruch autka na planszy
    void player_move();
    void draw_on_buffer(); //rysuje auto na buforze

};

#endif /* init_h */

"init.cpp":

#include "init.h"
//deklaracje zmiennych globalnych:

BITMAP *car1 = NULL;
BITMAP *car2 = NULL;
BITMAP *track = NULL;
BITMAP *buffer = NULL;

const int Y_SIZE = 768;
const int X_SIZE = 1024;
//----------------------------------
inline void init()
{
    allegro_init();
    set_color_depth(16);
    set_gfx_mode(GFX_AUTODETECT_WINDOWED, X_SIZE, Y_SIZE, 0, 0);
    car1 = load_bmp("auto1.bmp", default_palette);
    car2 = load_bmp("auto2.bmp", default_palette);
    track = load_bmp("trasa.bmp", default_palette);
    buffer = create_bitmap(X_SIZE,Y_SIZE);
    install_timer();
    install_keyboard();
    install_mouse();
}
//----------------------------------------
inline void deinit()
{
    clear_keybuf();
    allegro_exit();
}
//----------------------------------------

//definicja klasy Car
Car::Car(BITMAP* _sprite, double _acc, int _x, int _y, control _keys)
{
    sprite = _sprite;
    acc = _acc;
    x = _x;
    y = _y;
    dx = dy = speed = angle = friction = 0;
    keys = _keys;
    fill_sin_cos();

}
//----------------------------------------
void Car::fill_sin_cos()
{
    for(int i = 0; i < 72; i ++)
    {
        tab_sin[i] = sin((M_PI*(i*5))/180);
        tab_cos[i] = cos((M_PI*(i*5))/180);
    }
}
//----------------------------------------
void Car::increase_speed()
{
    if(speed < max_speed) speed += acc;
}
//----------------------------------------
void Car::decrease_speed()
{
    if(speed > min_speed) speed -= acc;
}
//----------------------------------------
void Car::turn_right()
{
    if(angle < 71)
        angle++;
    else
        angle = 0;
}
//----------------------------------------
void Car::turn_left()
{
    if(angle > 0)
        angle--;
    else
        angle = 71;

}
//----------------------------------------
void Car::change_friction()
{

    int ground = getpixel(track, x+30, y+30); //wspolrzedne +30 poniewaz odczytujemy 'ze srodka' autka
    switch(ground)
    {
    case black_color:
    case road_color:
        friction = 0.2;
        break;
    case grass_color:
        friction = 0.45;
        break;
    default:
        friction = 0.2;
    }
}
//----------------------------------------
void Car::player_move()
{
    if(keypressed())
    {
        switch(keys)
        {
        case ARROWS:
            if(key[KEY_UP]) increase_speed();
            if(key[KEY_DOWN]) decrease_speed();
            if(key[KEY_RIGHT]) turn_right();
            if(key[KEY_LEFT]) turn_left();
        case WSAD:
            if(key[KEY_W]) increase_speed();
            if(key[KEY_S]) decrease_speed();
            if(key[KEY_D]) turn_right();
            if(key[KEY_A]) turn_left();
        }
    }
}
//----------------------------------------
void Car::move()
{
    dx += speed*tab_cos[angle];
    dy += speed*tab_sin[angle];
    if( dx >=1 || dx <= -1)
    {
        x += int(dx);
        dx = dx - int(dx);
    }
    if( dy >=1 || dy <= -1)
    {
        y += int(dy);
        dy = dy - int(dy);
    }

    //obsluguje tarcie:
    if(speed < friction && speed > 0) speed = 0;
    if(speed > friction && speed < 0) speed = 0;
    if(speed > 0) speed -= friction;
    if(speed < 0) speed += friction;

    //powoduje zderzenia z brzegami planszy
    if(x <= 0)
    {
        speed = 0;
        x = 1;
    }
    if(y <= 0)
    {
        speed = 0;
        y = 1;
    }
    if(x >= X_SIZE-60)
    {
        speed = 0;
        x = X_SIZE-61;
    }
    if(y >= Y_SIZE-60)
    {
        speed = 0;
        y = Y_SIZE-61;
    }
}
//----------------------------------------
void Car::draw_on_buffer()
{
    masked_blit(sprite, buffer, 60*( angle % 18)  ,60*( (angle)/18 ), x,y, 60, 60);
    textprintf_ex(buffer, font, X_SIZE - 130, Y_SIZE - 50, makecol(0, 0, 0), -1, "Predkosc: %.2f km/h", speed); //wyswietla predkosc
    textprintf_ex(buffer, font, X_SIZE - 130, Y_SIZE - 60, makecol(0, 0, 0), -1, "Kierunek: %d", angle);
    textprintf_ex(buffer, font, X_SIZE - 130, Y_SIZE - 70, makecol(0, 0, 0), -1, "(x,y): %d %d", x, y);
    textprintf_ex(buffer, font, X_SIZE - 130, Y_SIZE - 80, makecol(0, 0, 0), -1, "Tarcie %.2f", friction);
}
[/code]

"init.h"

[code src="C++"]
#ifndef init_h
#define init_h

#include <allegro.h>
#include <cmath>
#define grass_color 1024
#define road_color 50712
#define black_color 0
///deklaracje funkcji i klas:
enum control{WSAD, ARROWS};

inline void init();
inline void deinit();

class Car
{
private:
    double tab_sin[72];
    double tab_cos[72];

    const static int max_speed = 30; //maksymalna predkosc
    const static int min_speed = -5; //minimalna predkosc (predkosc cofania)
    control keys;
    int x,y; //pozycja samochodu na ekranie
    int dx, dy; //przesuniecie samochodu wzgledem osi OX i OY
    int angle; //kat pod jakim jest samochod
    double speed; //obecna predkosc samochodu
    double acc; //przyspieszenie samochodu
    double friction; //tarcie powierzchni na jakiej znajduje sie auto
    BITMAP *sprite;// sprite z jakiego jest pobierany wyglad samochodu

    void fill_sin_cos();
    void increase_speed();
    void decrease_speed();
    void turn_right();
    void turn_left();
    void change_friction();
public:
    Car(BITMAP* _sprite, double _acc, int _x, int _y, control _keys); //sprajt auta, przyspieszenie auta, wspolrzedne startowe, sposob sterowania (strzalki/wsad)
    void move(); //odpowiada za ruch autka na planszy
    void player_move();
    void draw_on_buffer(); //rysuje auto na buforze

};

#endif /* init_h */
edytowany 1x, ostatnio: goovie, 2013-02-28 20:24

Pozostało 580 znaków

2013-02-28 20:29

Rejestracja: 16 lat temu

Ostatnio: 1 rok temu

Lokalizacja: Katowice

0

Powsadzaj to w <code><code class="cpp"> ... </code></code> bo nie da się tego czytać.

Pierwszy z brzegu błąd: car1 używasz w main.cpp a definicja jest init.cpp. Skąd kompilator ma wiedzieć co to za zmienna? W nagłówku init.h powinieneś mieć deklaracje czyli extern BITMAP *car1;. Podejrzewam, że z całą resztą jest podobnie.


"(...) otherwise, the behavior is undefined".
edytowany 2x, ostatnio: Endrju, 2013-02-28 20:29

Pozostało 580 znaków

2013-02-28 20:30

Rejestracja: 14 lat temu

Ostatnio: 10 godzin temu

0

A dodałeś init.cpp do projektu?


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.

Pozostało 580 znaków

2013-02-28 20:35

Rejestracja: 8 lat temu

Ostatnio: 6 lat temu

0

Dodalem init.cpp do projektu (o czym pisze) i oczywiscie probowalem wszystko poprawiac externem.

Dziekuje za szybka odpowiedz.

Pozostało 580 znaków

2013-02-28 21:14

Rejestracja: 8 lat temu

Ostatnio: 2 tygodnie temu

0

Na pewno musisz dać w init.h defklaracje zmiennych jako extern. Tym niemniej kompletnym bezsesensem jest używanie, jako argumentów obiektów, które trzymasz w plikach wraz z definicjami wywoływanych metod.

Pozostało 580 znaków

2013-02-28 22:08

Rejestracja: 8 lat temu

Ostatnio: 6 lat temu

0

Wybacz ale nie rozumiem zdania "Tym niemniej kompletnym bezsesensem jest używanie, jako argumentów obiektów, które trzymasz w plikach wraz z definicjami wywoływanych metod"

Pozostało 580 znaków

2013-02-28 22:12

Rejestracja: 16 lat temu

Ostatnio: 10 godzin temu

0
inline void init();
inline void deinit();

Wyrzuć te inline'y, prosisz się o kłopoty.

Pozostało 580 znaków

Odpowiedz

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