Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static Map as Class Member in C++

Tags:

c++

static

map

I'm having trouble using a static map as a C++ member. My header file is:

class Article
{
public:
//
static map<string,Article*> dictionary;
....
....   
};

In my constructor I call the following method first:

 void Article::InitializeDictionary()
 {
   #ifndef DICT
   #define DICT
   map<string,Article*> Article::dictionary;
   #endif
 }

Based on other posts about this I am supposed to declare the static member but when I try to do this I get the following error:

Error   1   error C2655: 'Article::dictionary' : definition or redeclaration illegal in current scope   c:\.......\article.cpp  88  1

If I change the function to the following:

void Article::InitializeDictionary()
{
    #ifndef DICT
    #define DICT
    Article::dictionary["null"] = 0;
    #endif
}

I get this error:

Error   1   error LNK2001: unresolved external symbol "public: static class std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class Article *,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,class Article *> > > Article::dictionary" (?dictionary@Article@@2V?$map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PAVArticle@@U?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PAVArticle@@@std@@@2@@std@@A)

Any ideas on what I can do?

like image 248
Kyle Avatar asked Oct 12 '13 15:10

Kyle


2 Answers

You have to properly declare and define static member (doing this in method is wrong):

class Article
{
public:
//
static map<string,Article*> dictionary;
....
....   
};

map<string,Article*> Article::dictionary;

int main() {
    //..
}

You've asked in the comment:

I tried doing this after the class declaration and got an error but if I do this in the .cpp file where the function definitions are it works. Why is that?

Since static members are shared between ALL instances of a class, they have to be defined in one and only one compilation unit (place). Really, they're global variables with some access restrictions.

If you try to define them in the header, they will be defined in every module that includes that header, and you'll get errors during linking as it finds all of the duplicate definitions.

like image 159
4pie0 Avatar answered Nov 11 '22 23:11

4pie0


There's nothing wrong with your declaration of the static in your class.

However, you need to tell the compiler to reserve storage for the static member: you need to define it. To do this include the line

map<string,Article*> Article::dictionary;

in exactly one compilation unit and at global scope; i.e. not in a method or a namespace.

The normal thing to do is to put that line in the source file associated with your Article class. If you put the line in a header file then multiple compilation units could define it which will give you link errors. This will happen even with include guards.

It's important to note that the initialisation of the map will occur before the program's main function is run.

like image 6
Bathsheba Avatar answered Nov 12 '22 00:11

Bathsheba