5

I am trying to initialise a static map of
map<string, int>
in my program as follows:

testApp.h

class testApp(){
public:
void setup();
void update();
void renew();
static map<string, int> _someMap;
};

testApp.cpp

testApp::setup(){
   _someMap["something"] = 1;
   _someMap["something2"] = 2;
cout<<_someMap["something"]<<"\n";
}

I don't want to use boost for this short use of map and add source dependency for my code. I am not on C++11 and I don't have the constructor here in the program since the class is some framework's class. I am on Xcode and on doing the above in .cpp, I get the following error:

Undefined symbols for architecture i386:
  "testApp::mapppp", referenced from:
      testApp::setup() in testApp.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)

-- >Additionally, let's say my map is private, for which I tried doing this in my class:

...
private:
static someVariable;
static void someFunction();

.cpp

testApp::setup(){
someFunction();
}

Error:

Undefined symbols for architecture i386:
  "testApp::_someMap", referenced from:
      testApp::someFunction() in testApp.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
user1240679
  • 6,829
  • 17
  • 60
  • 89
  • 5
    Did you ever define the variable? – chris May 30 '13 at 14:36
  • 4
    Have you put this: map testApp::_someMap; in your .cpp file? – marcinj May 30 '13 at 14:37
  • I believe you mistakenly wrote `map` in `setup` while meaning `_someMap`. There is also the fact that the error complains about the symbol `mapppp` which appears nowhere in your program... Please, if you want help, copy paste the real code (trimming it down) and do not write a different version (which produces different issues than the one you have). – Matthieu M. May 30 '13 at 14:38
  • @marcin_j : No. You mean there's no declaration of static variable? – user1240679 May 30 '13 at 14:38
  • @MatthieuM. : Sorry. those were typos. Corrcted. – user1240679 May 30 '13 at 14:39
  • @chris : Yes, the variable is there in `.h` file >> `_someMap`. Does this have to be included in `.cpp` file again for definition? – user1240679 May 30 '13 at 14:40
  • 3
    You have to define it as marcin_j said, outside class functions implementations. Your static have to reside somewhere, it's a global for god sake ! – Liviu May 30 '13 at 14:40
  • better to use the namespace prefix to fully qualify the map type. use `std::map` – Yousf May 30 '13 at 14:41
  • @Liviu : Thanks! That looks like it works. But why is that only a declaration doesn't work? Also, why can't I initialise static member variable in the class constructors? – user1240679 May 30 '13 at 14:42
  • Some more info on class static variables: http://stackoverflow.com/questions/11178434/static-variable-in-the-class-declaration-or-definition – marcinj May 30 '13 at 14:44
  • in test testApp.h you have made the entire std namespace available. Not such a smart idea since the developers have tried to hide it. In the .cpp it's not so much of a problem – hetepeperfan May 30 '13 at 14:45
  • In C++, there's no such thing as `per class` constructor and your static variable must reside (be defined) somewhere outside the class instantiations (objects). Just like a normal global C variable. – Liviu May 30 '13 at 14:51

1 Answers1

5

You've declared the variable in the class definition, but it looks like you haven't defined it. Every static variable needs to be defined in exactly one translation unit. So add a definition to your source file:

map<string, int> testMap::_someMap;

If you like (and if you can't use a C++11 initialiser), you could avoid having to call the setup function by initialising the map from the result of a function instead:

map<string, int> make_map() {
    map<string, int> map;
    map["something"] = 1;
    map["something2"] = 2;
    return map;
}

map<string, int> testMap::_someMap = make_map();
Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • Why is that? Is it because of some rule or logical decision as well? – user1240679 May 30 '13 at 14:48
  • Also, why is it that I can't initialize private static member variables from my constructor? Why do I need to use another static function to initialize my static map in this case? – user1240679 May 30 '13 at 14:49
  • @user1240679: Why is that? It's a rule, known as the One Definition Rule: every static variable, if the program uses it, has to be defined in one translation unit. – Mike Seymour May 30 '13 at 14:50
  • 1
    @user1240679: Why is it that I can't initialize private static member variables from my constructor? Because the constructor initialises each object of the class. There's only one instance of the static member, however many instances of the class you create; and it must exist even if you never create a class object (and therefore never run the constructor). – Mike Seymour May 30 '13 at 14:52
  • @user1240679: One question per question please – Lightness Races in Orbit May 30 '13 at 14:55