user5759490
user5759490

Reputation: 113

Multiple definition of std::map error

Also, I am compiling with g++-4.9 and -std= c++11

I have this exact map in my board.h file:

map <string,string> dirFull = {
    {"no", "north"},
    {"so", "south"},
    {"ea", "east"},
    {"we", "west"},
    {"nw", "north-west"},
    {"ne", "north-east"},
    {"sw", "south-west"},
    {"se", "south-east"},
};

And then I feely start using it in another function in my baord.cc file (i.e. dirFull[no])which includes the .h file. I get this error:

Board/board.o: In function `__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<char const, std::string> > >::deallocate(std::_Rb_tree_node<std::pair<char const, std::string> >*, unsigned long)':
/u6/yhavryshchuk/cs246/1161/a5/CC3K/Board/board.cc:11: multiple definition of `dirFull'
main.o:/u6/yhavryshchuk/cs246/1161/a5/CC3K/main.cc:20: first defined here

I have found multiple answers to this question, so I'm not sure what I should do. Some say I should use extern. some say a declaration should go in the .h file, but the definition should go in a .cc file.

Upvotes: 1

Views: 2611

Answers (1)

wally
wally

Reputation: 11032

dirFull is defined (not just declared) in both board.cc and main.cc.

You could use the keyword extern to declare, but not define for a second time, the same variable.

e.g. extern map<string, string> dirFull;


The following won't work if you have the same in another compilation unit:

extern map <string,string> dirFull = {
    {"no", "north"},
    {"so", "south"},
    {"ea", "east"},
    {"we", "west"},
    {"nw", "north-west"},
    {"ne", "north-east"},
    {"sw", "south-west"},
    {"se", "south-east"},
};

It will produce an dirFull initialized and declared in extern error as you mention in the comments.


First option

If you have base.h for example:

#include <string>
#include <map>

std::map <std::string,std::string> dirFull ={
    {"no", "north"},
    {"so", "south"},
    {"ea", "east"},
    {"we", "west"},
    {"nw", "north-west"},
    {"ne", "north-east"},
    {"sw", "south-west"},
    {"se", "south-east"},
};

And then have Main.cpp:

#include "base.h"


extern std::map <std::string,std::string> dirFull;

int main()
{
    dirFull["no"];
}

Then it will work.


Better option

Might be better to have base.h:

#include <string>
#include <map>

extern std::map <std::string,std::string> dirFull;

then have Main.cpp:

#include "base.h"

std::map <std::string,std::string> dirFull ={
    {"no", "north"},
    {"so", "south"},
    {"ea", "east"},
    {"we", "west"},
    {"nw", "north-west"},
    {"ne", "north-east"},
    {"sw", "south-west"},
    {"se", "south-east"},
};

int main()
{
    dirFull["no"];
}

With this last option it is nice to see the declarations in the header and the definitions in the .cpp (or .cc) files.

Upvotes: 4

Related Questions