Undefined reference to something that's appearently declared.

Hello, I'm getting a whole lot of compile errors:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
obj/Debug/LoadFromXml.o||In function `LoadPinballTable(b2World&)':|
/home/werner/c++workspace/Pinball/LoadFromXml.cpp|51|undefined reference to `StaticWall::StaticWall(b2Vec2*, int, b2World&)'|
/home/werner/c++workspace/Pinball/LoadFromXml.cpp|58|undefined reference to `Ball::Ball(float, float, float, float, b2World&)'|
/home/werner/c++workspace/Pinball/LoadFromXml.cpp|67|undefined reference to `Bumper::Bumper(float, float, float, float, int, b2World&)'|
/home/werner/c++workspace/Pinball/LoadFromXml.cpp|74|undefined reference to `Flipper::Flipper(float, float, float, float, char, b2World&)'|
/home/werner/c++workspace/Pinball/LoadFromXml.cpp|81|undefined reference to `Flipper::Flipper(float, float, float, float, char, b2World&)'|
/home/werner/c++workspace/Pinball/LoadFromXml.cpp|88|undefined reference to `Launcher::Launcher(float, float, b2World&)'|
/home/werner/c++workspace/Pinball/LoadFromXml.cpp|94|undefined reference to `BallDispenser::BallDispenser(float, float, short)'|
obj/Debug/pinball.o||In function `main':|
/home/werner/c++workspace/Pinball/pinball.cpp|50|undefined reference to `EventHandler::EventHandler(ALLEGRO_EVENT_QUEUE*)'|
/home/werner/c++workspace/Pinball/pinball.cpp|78|undefined reference to `MyContactListener::MyContactListener()'|
/home/werner/c++workspace/Pinball/pinball.cpp|115|undefined reference to `EventHandler::HandleEvent(ALLEGRO_EVENT)'|
/home/werner/c++workspace/Pinball/pinball.cpp|131|undefined reference to `EventHandler::~EventHandler()'|
||=== Build finished: 11 errors, 0 warnings ===| 


I don't understand why, because I believe I did define these in the header file.

The code:

LoadFromXml.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include "rapidxml.hpp"
#include "Entities.h"
#include "LoadFromXml.hpp"
#include <fstream>
#include <iostream>

// This function loads a pinball table from an XML file.
bool LoadPinballTable(b2World &physics_world)
{
    // Emit a warning to the user/developer that errors given by the parser are probably due to errors in the xml file.
    std::cout << "Loading pinball table from XML file. If you get any errors beyond this point, it's probably in the XML file." << std::endl;

    using namespace rapidxml;

    std::string input_xml;
    std::string line;
    std::ifstream in("testtable.xml");

    // read file into input_xml
    while(getline(in,line))
    {
        input_xml += line;
    }
    // Run the RapidXML parser inputting the string that has just been loaded.
    std::vector<char> xml_copy(input_xml.begin(), input_xml.end());
    xml_copy.push_back('\0');
    xml_document<> doc;
    doc.parse<parse_full>(&xml_copy[0]);
    xml_node<> *node = doc.first_node(0);

    // Iterate over the DOM tree
    while (node != 0)
    {
        // Determine what entity is specified in the XML file and spawn it.

        // Static wall: A chain of vertices specifying an immobile solid wall.
        if ((strcmp((node->name()), "staticwall") == 0))
        {
            // Make an array that's as long as specified in the xml tag
            int num_vertices = atoi(node->first_attribute("num_verts")->value());
            b2Vec2 verts[num_vertices];
            xml_node<> *node2 = node->first_node("vertex");

            // Make an array of the vertices
            for (int i = 0; i<num_vertices; i++)
            {
                verts[i].Set(atof(node2->first_attribute("x")->value()),
                             atof(node2->first_attribute("y")->value()));
                node2 = &(*node2->next_sibling());
            }
            entity_list.push_back(new StaticWall(verts,num_vertices,physics_world));
        }
        // Ball: The "ball" in "pinBALL". Usually spawned by a ball dispenser rather than through this function.
        if ((strcmp((node->name()), "ball") == 0))
        {
            entity_list.push_back(new Ball(atof(node->first_attribute("x")->value()),
                                           atof(node->first_attribute("y")->value()),
                                           0,0,physics_world));
        }
        if ((strcmp((node->name()), "bumper") == 0))
        {
            entity_list.push_back(new Bumper(atof(node->first_attribute("x")->value()),
                                           atof(node->first_attribute("y")->value()),
                                           atof(node->first_attribute("radius")->value()),
                                           atof(node->first_attribute("strenght")->value()),
                                           555,
                                           physics_world));
        }
        // The left flipper
        else if ((strcmp((node->name()), "lflipper") == 0))
        {
            entity_list.push_back(new Flipper(atof(node->first_attribute("x")->value()),
                                              atof(node->first_attribute("y")->value()),
                                              0,0,'l',physics_world));
        }
        // And the other one
        else if ((strcmp((node->name()), "rflipper") == 0))
        {
            entity_list.push_back(new Flipper(atof(node->first_attribute("x")->value()),
                                              atof(node->first_attribute("y")->value()),
                                              0,0,'r',physics_world));
        }
        // A plunger used to launch the ball
        else if ((strcmp((node->name()), "launcher") == 0))
        {
            entity_list.push_back(new Launcher(atof(node->first_attribute("x")->value()),
                                               atof(node->first_attribute("y")->value()),
                                               physics_world));
        }
        // An invisible object that spawns a ball at the start of the game and whenever a ball falls through the drain.
        else if ((strcmp((node->name()), "balldispenser") == 0))
        {
            entity_list.push_back(new BallDispenser(atof(node->first_attribute("x")->value()),
                                               atof(node->first_attribute("y")->value()), 3));
        }
        node = node->next_sibling(); // Assign a reference of the xml node's next sibling to the node pointer for the next iteration.
        // If the xml node has no next sibling, the returned adress will be 0, in which case the looping condidion will return false and stop looping.

    }
    return true;
}

Entities.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <allegro5/allegro.h>
#include <Box2D/Box2D.h>
#include "Drawables.h"
#include <vector>

// All these functions are declared in Entities.cpp

#ifndef ENTITIES_H
#define ENTITIES_H

enum EntityType {ETYPE_ABSTRACT,ETYPE_STATIC_WALL,ETYPE_BALL,ETYPE_BUMPER,ETYPE_FLIPPER,ETYPE_LAUNCHER,ETYPE_BALL_DISPENSER};

class GameEntity
{
public:
    EntityType entity_type;
    GameEntity();
    void virtual draw_self();
    void virtual HandleEvent(ALLEGRO_EVENT & ev);
    void virtual doStep(float spf);
};

extern std::vector<GameEntity*> entity_list;

void SpawnEntity(GameEntity* entity);

class StaticWall : public GameEntity
{
public:

    std::vector<Drawable_Line*> drawList;

    StaticWall(b2Vec2 vertices[], int vertex_amount, b2World & physics_world);

    ~StaticWall();

    void draw_self();
};

// File goes on... 


Entities.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <iostream>
#include <allegro5/allegro.h>
#include <allegro5/allegro_primitives.h>
#include <Box2D/Box2D.h>
#include <vector>
#include <string>
#include "Drawables.h"
#include "eventhandler.hpp"
#include <math.h>
#include "SoundController.hpp"
#include "Entities.h"

extern SoundController sound_controller;
extern EventHandler* event_handler;

// The abstract GameEntity superclass -----------------------------------------------------

GameEntity::GameEntity(){entity_type = ETYPE_ABSTRACT;}

void GameEntity::draw_self()
{
        std::cout << "WRONG! GameEntity draw() called!" << std::endl;
}
void GameEntity::HandleEvent(ALLEGRO_EVENT & ev)
    {
            std::cout << "WRONG! GameEntity HandleEvent() called!" << std::endl;
    }
void GameEntity:: doStep(float spf) {}

// Spawn Entity function
void SpawnEntity(GameEntity* entity)
{
    entity_list.push_back(entity);
}

// The Static Wall Class ---------------------------------------------------------------------

StaticWall::StaticWall(b2Vec2 vertices[], int vertex_amount, b2World & physics_world)
{
    entity_type = ETYPE_STATIC_WALL;

    b2BodyDef bodyDef;
    bodyDef.type = b2_staticBody;
    bodyDef.position.Set(0,0);
    bodyDef.userData = this;

    b2Body * body = physics_world.CreateBody(&bodyDef);

    b2ChainShape chain;
    chain.CreateChain(vertices, vertex_amount);

    b2FixtureDef fixtureDef;
    fixtureDef.shape = &chain;
    fixtureDef.density = 1.0f;
    fixtureDef.friction = 0.3f;
    body->CreateFixture(&fixtureDef);

    drawList = std::vector<Drawable_Line*>();

    for (int i=0; i<vertex_amount-1; i++)
    {
        drawList.push_back(new Drawable_Line(vertices[i].x*32,-vertices[i].y*32,vertices[i+1].x*32,-vertices[i+1].y*32));
    }
}

    StaticWall::~StaticWall()
    {
        for (unsigned i=0; i < drawList.size(); i++)
        {
            delete drawList[i];
        }
    }

    void StaticWall::draw_self()
    {
        for (unsigned i=0; i < drawList.size(); i++)
        {
            drawList[i]->draw();
        }
    }

//File goes on... 

Are you sure your Entities.cpp is also being compiled and linked in with your LoadFromXML file? That's the only possibility I can think of right now: that it's not being linked properly.

-Albatross
Last edited on
It seems that your module Entities.cpp was not included in your project.
Looks like a bug in the IDE, it simpIy says nothing is to be done when I request a compile of Entities.cpp.
I detached the file from the project and then reattached it, It suddenly works.
Ever so often may want to "clean" your project. Maybe that'll help.

-Albatross
Topic archived. No new replies allowed.