vector compile error?

Started by
6 comments, last by L. Spiro 11 years, 6 months ago
I'm trying to build my 2nd text based RPG but this time I wanna make it more flexible and have the code split up and everything. I will post my source code below and my compile error:

Source Code:

init.cpp

#include <iostream>
#include "game.h"
#include "rooms.h"
void main() {
intro();
}


game.cpp

#include <iostream>
#include <string>
#include <vector>
#include "rooms.h"
using namespace std;
void intro() {
pRooms[9] = 10;
checkRoom();
system("pause");
}


game.h

#include <string>
#include <vector>
using namespace std;
// Prototypes //
void intro();


rooms.cpp

#include <iostream>
#include <vector>
#include "rooms.h"
using namespace std;
int checkRoom() {
int cRoom = 0;
int counter = 0;
int x = 0;
if (counter <= nRooms) {
if (pRooms[x] = 1) {
x = cRoom;
cout << "cRoom = " << cRoom;
}
else {
++counter;
++x;
cout << "Adding 1\nAdding 1 to x";
}
}
return cRoom;
}


rooms.h

#include <iostream>
#include <vector>
using namespace std;
// Prototypes //
int checkRoom();
// Vectors //
vector<int> pRooms(10,0);
// Integers //
int nRooms = pRooms.size();


Build Log


1>------ Build started: Project: textRPG, Configuration: Debug Win32 ------
1> game.cpp
1> Generating Code...
1> Skipping... (no relevant changes detected)
1> rooms.cpp
1> init.cpp
1>init.obj : error LNK2005: "class std::vector<int,class std::allocator<int> > pRooms" (?pRooms@@3V?$vector@HV?$allocator@H@std@@@std@@A) already defined in game.obj
1>init.obj : error LNK2005: "int nRooms" (?nRooms@@3HA) already defined in game.obj
1>rooms.obj : error LNK2005: "class std::vector<int,class std::allocator<int> > pRooms" (?pRooms@@3V?$vector@HV?$allocator@H@std@@@std@@A) already defined in game.obj
1>rooms.obj : error LNK2005: "int nRooms" (?nRooms@@3HA) already defined in game.obj
1>H:\C++ extRPG\Debug extRPG.exe : fatal error LNK1169: one or more multiply defined symbols found
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Advertisement
If you want to use a global variable in multiple source file. Declare them as extern in a header, and then define them in one source file. I.e.: put extern int i; in a header and in one source file put int i = /* blah blah blah */;
extern vector<int> pRooms(10,0);

is that possible? tongue.png

I tried that ^^ and it still has a compile error.


1>------ Build started: Project: textRPG, Configuration: Debug Win32 ------
1> game.cpp
1> Generating Code...
1> Compiling...
1> rooms.cpp
1> init.cpp
1> Generating Code...
1>init.obj : error LNK2005: "class std::vector<int,class std::allocator<int> > pRooms" (?pRooms@@3V?$vector@HV?$allocator@H@std@@@std@@A) already defined in game.obj
1>init.obj : error LNK2005: "int nRooms" (?nRooms@@3HA) already defined in game.obj
1>rooms.obj : error LNK2005: "class std::vector<int,class std::allocator<int> > pRooms" (?pRooms@@3V?$vector@HV?$allocator@H@std@@@std@@A) already defined in game.obj
1>rooms.obj : error LNK2005: "int nRooms" (?nRooms@@3HA) already defined in game.obj
1>H:\C++ extRPG\Debug extRPG.exe : fatal error LNK1169: one or more multiply defined symbols found
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
No, don't put the initializer as part of the extern declaration in the header. Put the initializers on the definitions in the source file.
#pragma once

Put that at the top of every header file, this prevents things being included more that once during compilation.

#pragma once

Put that at the top of every header file, this prevents things being included more that once during compilation.

Neither that, nor include guards, prevent multiple definition errors.
Time to point out the important difference between declaration and definition. You can have as many declarations in your source files as you like, but only ONE definition.

void function();
Is a declaration. It just says "this thingy exists... somewhere".

void function() {...}
Is a definition, because it defines what the function actually is and does.

For variables it's slightly different.

int x;
int x = 10;
Both are definitions, though the first variable isn't initialized (and if I find code like that at work without a really good reason, the author will be verbally slapped).

extern int x;
Is a pure declaration, saying that somewhere this variable exists.

extern int x = 10;
Doesn't make sense, because you now try to declare it AND already define it.


For classes it's a bit more interesting. You generally implement (define) the member functions in a single source file, so everything is fine. Why does it work if you implement them right there in the header (inside the class)? Because it's automatically considered inline. Inline will "fix" your multiple definitions (for functions), but unless you actually want it to be inlined, that kind of thing also deserves a good slapping (especially on very huge and bloated functions, which you shouldn't be coding anyway).

There is also the most important declaration of all. The forward declaration.

class SomeClass;
Again, this simply declares "this class exists somewhere". Get in the habit of using this in your header files instead of including whole header files for other classes. As long as your header is only containing pointers or references to that class, nobody cares what it looks like and by using forward declarations, you reduce messy include avalanches and often reduce compile time. Basically: only use #include in files that actually use the class itself.
f@dzhttp://festini.device-zero.de
Frankly this is one of the reasons why I never have global variables in this form.
It isn’t even simple to explain to him how to fix this how it is.

I use one class per file and as a result this form of a global never exists in my projects.
Instead, they become class static members (read carefully; they are still globals, just in a different form/syntax).

There are several reasons I do this, but the main point here is that it eliminates this headache.

File.h:
class CMyClass {
public :
static vector<int> pRooms;
};


File.cpp:
vector<int> CMyClass::pRooms = vector<int>( 10, 0 ); // Will this constructor actually work?

The headache of multiple-definitions and proper use extern is gone.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

This topic is closed to new replies.

Advertisement