Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Forward Declaration Problem, among other things...

This thread is locked; no one can reply to it. rss feed Print
Forward Declaration Problem, among other things...
Kibiz0r
Member #6,203
September 2005
avatar

I got a million of these:

C:\...main.cpp:37: error: invalid use of undefined type `struct Unit'
C:\...main.cpp:12: error: forward declaration of `struct Unit'

For different classes though.

1#include "color constants.h"
2#include <allegro.h>
3#include <vector>
4 
5using namespace std;
6 
7class Game;
8class Map;
9class Cell;
10class Player;
11class Unit;
12class Effect;
13class Projectile;
14class GUI;
15class ChatBox;
16 
17class Game
18{
19 private:
20 Map *map;
21 vector<Player*> playerList;
22 vector<Unit*> unitList;
23 vector<Effect*> effectList;
24 vector<Projectile*> projectileList;
25 GUI *myGUI;
26 ChatBox *myChatBox;
27 BITMAP *tileSet[12][5]; // 12 tiles to a set, 5 variations of each tile
28 long lastClock;
29 
30 void step()
31 {
32 long dt = clock() - lastClock;
33 lastClock += dt;
34 for (int i = 0; i < unitList.size();)
35 {
36 if (unitList.at(i)->removeMe)
37 {
38 unitList.erase(unitList.begin() + i);
39 }
40 else
41 {
42 unitList.at(i)->act(dt);
43 i++;
44 }
45 }
46 }
47 
48 void draw()
49 {
50 for (int i = 0; i < playerList.size(); i++)
51 {
52 map->draw(playerList.at(i));
53 for (int j = 0; j < unitList.size(); j++)
54 {
55 unitList.at(j)->draw(playerList.at(i));
56 }
57 for (int j = 0; j < effectList.size(); j++)
58 {
59 effectList.at(j)->draw(playerList.at(i));
60 }
61 for (int j = 0; j < projectileList.size(); j++)
62 {
63 projectileList.at(j)->draw(playerList.at(i));
64 }
65 myGUI->draw(playerList.at(i));
66 myChatBox->draw(playerList.at(i));
67 }
68 }
69 
70 public:
71 Game()
72 {
73 map = new Map();
74 myGUI = new GUI();
75 myChatBox = new ChatBox();
76 }
77};
78 
79class Map
80{
81 private:
82 int rows;
83 int columns;
84 Cell *cellArray;
85 
86 public:
87 Map()
88 {
89 rows = 8;
90 columns = 16;
91 cellArray = (Cell*)malloc(rows * sizeof(Cell*));
92 for (int i = 0; i < rows; i++)
93 {
94 cellArray<i> = (Cell*)malloc(columns * sizeof(Cell*));
95 }
96 }
97 
98 void draw(Player *player)
99 {
100 for (int i = player->camera->y1() / 32; i <= player->camera->y2() / 32; i++)
101 {
102 for (int j = player->camera->x1() / 32; j <= player->camera->x2() / 32; j++)
103 {
104 cellArray<i>[j]->draw(player);
105 }
106 }
107 }
108};
109 
110class Cell
111{
112 private:
113 int x;
114 int y;
115 BITMAP *texture; // 32 x 32
116 
117 public:
118 Cell(BITMAP *tile)
119 {
120 texture = tile;
121 }
122 
123 void draw(Player *player)
124 {
125 blit(texture, buffer, 0, 0, x - player->camera->x1(), y - player->camera->y1(), texture->w, texture->h);
126 }
127};
128 
129class Player
130{
131 
132};
133 
134class Unit
135{
136 private:
137 double x;
138 double y;
139 
140 public:
141 bool removeMe;
142};
143 
144class Effect
145{
146 
147};
148 
149class Projectile
150{
151 
152};
153 
154class GUI
155{
156 
157};
158 
159class ChatBox
160{
161 
162};
163 
164void init();
165void deinit();
166 
167int main()
168{
169 init();
170 
171 deinit();
172 return 0;
173}
174END_OF_MAIN()
175 
176void init()
177{
178 int depth, res;
179 allegro_init();
180 depth = desktop_color_depth();
181 if (depth == 0)
182 depth = 32;
183 set_color_depth(depth);
184 res = set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0);
185 if (res != 0)
186 {
187 allegro_message(allegro_error);
188 exit(-1);
189 }
190 install_timer();
191 install_keyboard();
192 install_mouse();
193 buffer = create_bitmap(800, 600);
194}
195 
196void deinit()
197{
198 clear_keybuf();
199}

Also, there's a problem with my dynamic allocation of the Cell pointer array. I've never done that sort of thing before, so I have no idea what I'm doing really.

Thanks.

Indeterminatus
Member #737
November 2000
avatar

using namespace std;

This is evil. If you want to save typing std:: for every std::vector, use using std::vector; instead.
The whole concept of namespaces is to separate, which is totally circumvented by using, throwing it all in one pot again.

For your errors:

A forward declaration is no full-type declaration, and you may only perform operations that do not need a full-type (like declaring a pointer or a reference to that type). As soon as you start needing more information (like, dereferencing it, accessing a specific field etc.) about it, the compiler must already know the full type, which means that a forward declaration won't do any more.

Solutions to your problem:

a) Move all method definitions to a .cpp file, and include the full declarations of the types needed (like, if you have class Map; as forward declaration, #include <map.hpp>, assuming class Map is defined in map.hpp.

b) Move all method definitions to a place where the classes are already fully defined.

_______________________________
Indeterminatus. [Atomic Butcher]
si tacuisses, philosophus mansisses

Carrus85
Member #2,633
August 2002
avatar

using namespace std;

This is not evil, it is perfectly valid and recommended, as long as you control the scope of the statement. The basic rule of thumb is that the using namespace foo; DECLARATION IS NOT SOMETHING YOU WANT TO DO IN A HEADER FILE (if you need to do it in a header file, do it on a function by function basis. Never just leave a using namespace statement in the global scope if you can help it.) If you are using a lot of namespaced stuff in a header file, usually you enclose the using directive inside of the function scope to prevent unwanted namespace pollution. This same argument goes for even the using std::vector statement, even though the using std::vector statement is considerably less problematic.

edit: using namespace std; in a cpp file is just fine as long as you don't care that it opens up hundereds of names into your current scope; you just don't want to force the entire std namespace on the user of a header file.

AngelChild
Member #3,401
April 2003
avatar

Alternatively, you can use a temporary namespace like this to hide it in a header file:

#include <vector>

namespace temporary {
    using namespace std;

    class Thing
    {
        vector<int> lookImAVector;
    };
}

using temporary::Thing;

-----
The loyal minion of Bob Keane.

Go to: