LNK1169 error

Hello,
I've been reading the book "Game Programming All In One. Third Edition" and have been loving the book. But I know C++ better then I know C, so I thought I would convert the books first example of Tank War to C++ classes. Everything worked great till I tried separating the tank/bullet classes I had created out of the main file and into a separate .h/.cpp file.
But now I get the error:
1>tank.obj : error LNK2005: "public: static int tagTank::numTanks" (?numTanks@tagTank@@2HA) already defined in Main.obj
1>tank.obj : error LNK2005: "class tagTank * tanks" (?tanks@@3PAVtagTank@@A) already defined in Main.obj
1>C:\Documents and Settings\Jesse\My Documents\Visual Studio 2010\Projects\Tank Battle\Debug\Tank Battle.exe : fatal error LNK1169: one or more multiply defined symbols found

I have narrowed this down my self to the fact that in my tank.h I end with the code "} tanks[2];" But I can't think of how to change it so I don't get the LNK error. Could anyone give some help as to how to alleviate this problem since I don't know every in and out of C++ classes?

Here is the code I feel is relevant to the problem.
tank.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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#ifndef _TANK_H
#define _TANK_H

#include "allegro.h"

//constants
const int MAXSPEED = 4;
const int BULLETSPEED = 10;

//define bullet class
class tagBullet
{
public:
    int x,y;
    int alive;
    int xspd,yspd;
    int player;

    int updateBullet();
    int explode(int x, int y);
};

//define tank class
class tagTank
{
public:
    static int numTanks;
    int x,y;
    int dir,speed;
    int color;
    int score;
    int player;
    tagBullet bullet;

    void setupTank();
    void drawTank();
    void eraseTank();
    void moveTank();
    void forward();
    void backward();
    void turnLeft();
    void turnRight();
    void clearPath();
    void fireWeapon();
    
    tagTank()
    { 
        x = 0;
        y = 0;
        dir = 0;
        speed = 0;
        color = 0;
        score = 0;
        player = 0;  // Not a legal player
    };

} tanks[2];

// Initialize instance variable
int tagTank::numTanks = 0;

// Function prototypes
int checkPath(int x1,int y1,int x2,int y2,int x3,int y3);
#endif 


main.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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/////////////////////////////////////////////////////////////////////////
// Game Programming All In One, Third Edition
// Chapter 4 - Tank War Game
/////////////////////////////////////////////////////////////////////////

#include "tankbattle.h"
#include "tank.h"




/////////////////////////////////////////////////////////////////////////
// main function
// start point of the program
/////////////////////////////////////////////////////////////////////////
int main(void)
{
    //initialize everything
    allegro_init();  
    install_keyboard(); 
    install_timer();
    srand(time(NULL));
    setupScreen();
    setupDebris();
    tanks[0].setupTank();
    tanks[1].setupTank();

    //game loop
    while(!gameover)
    {
        //erase the tanks
        tanks[0].eraseTank();
        tanks[1].eraseTank();
        
        //check for collisions
        tanks[0].clearPath();
        tanks[1].clearPath();
        
        //move the tanks
        tanks[0].moveTank();
        tanks[1].moveTank();
        
        //draw the tanks
        tanks[0].drawTank();
        tanks[1].drawTank();

        //update the bullets and set score 
        score(tanks[0].bullet.updateBullet());
        score(tanks[1].bullet.updateBullet());
        
        //check for keypresses
        if (keypressed())
            getInput();

        //slow the game down (adjust as necessary)
        rest(30);
    }

    //end program
    allegro_exit();
    return 0;
}
END_OF_MAIN()

/////////////////////////////////////////////////////////////////////////
// getinput function
// check for player input keys (2 player support)
/////////////////////////////////////////////////////////////////////////
void getInput()
{
    //hit ESC to quit
    if (key[KEY_ESC])
        gameover = 1;
    
    //WASD / SPACE keys control tank 1
    if (key[KEY_W])
        tanks[0].forward();
    if (key[KEY_D])
        tanks[0].turnRight();
    if (key[KEY_A])
        tanks[0].turnLeft();
    if (key[KEY_S])
        tanks[0].backward();
    if (key[KEY_SPACE])
        tanks[0].fireWeapon();
            
    //arrow / ENTER keys control tank 2
    if (key[KEY_UP]) 
        tanks[1].forward();
    if (key[KEY_RIGHT])
        tanks[1].turnRight();
    if (key[KEY_DOWN])
        tanks[1].backward();
    if (key[KEY_LEFT])
        tanks[1].turnLeft();
    if (key[KEY_ENTER])
        tanks[1].fireWeapon();

    //short delay after keypress        
    rest(10);
}

/////////////////////////////////////////////////////////////////////////
// score function
// add a point to the specified player's score
/////////////////////////////////////////////////////////////////////////
void score(int player)
{
    if (player != -1)    // Only update score if the player got a hit. 
    {
    //update score
    int points = ++tanks[player].score;

    //display score
    textprintf_ex(screen, font, SCREEN_W-70*(player+1), 1, BURST, 0,
        "P%d: %d", player+1, points);
    }
}


/////////////////////////////////////////////////////////////////////////
// setupdebris function
// set up the debris on the battlefield
/////////////////////////////////////////////////////////////////////////
void setupDebris()
{
    int n,x,y,size,color;

    //fill the battlefield with random debris
    for (n = 0; n < BLOCKS; n++)
    {
        x = BLOCKSIZE + rand() % (SCREEN_W-BLOCKSIZE*2);
        y = BLOCKSIZE + rand() % (SCREEN_H-BLOCKSIZE*2);
        size = (10 + rand() % BLOCKSIZE)/2;
        color = makecol(rand()%255, rand()%255, rand()%255);
        rectfill(screen, x-size, y-size, x+size, y+size, color);
    }

}

/////////////////////////////////////////////////////////////////////////
// setupscreen function
// set up the graphics mode and game screen
/////////////////////////////////////////////////////////////////////////
void setupScreen()
{
    //set video mode    
    int ret = set_gfx_mode(MODE, WIDTH, HEIGHT, 0, 0);
    if (ret != 0) {
        allegro_message(allegro_error);
        return;
    }

    //print title
    textprintf_ex(screen, font, 1, 1, BURST, 0,
        "Tank War - %dx%d", SCREEN_W, SCREEN_H);

    //draw screen border        
    rect(screen, 0, 12, SCREEN_W-1, SCREEN_H-1, TAN);
    rect(screen, 1, 13, SCREEN_W-2, SCREEN_H-2, TAN);
   
}


Also note that everything is public right now until I have everything running right.
Last edited on
heh, I just responded to a post with similar troubles.

The problem is you're putting globals in header files. Don't do that.

In fact... try not to use globals at all.

Here's my response to a post with a similar problem:

http://www.cplusplus.com/forum/beginner/28712/#msg155044
Topic archived. No new replies allowed.