3

I have the following code:

namespace GameStatus{

    static std::vector<SavePoint>savePoints;
}

A SavePoint is :

class SavePoint{

public:
    int distance;
    int score;

    SavePoint(int d,int s){
        distance = d;
        score = s;
    };
};

The problem is, that even though GameStatus::savePoints is static, the vector appears to either contain elements or not, depending on who the calling class is.

For example, if I have a class which adds a save point:

class Game{

    void addSavePoint(){
        SavePoint savepoint(12,10);
        GameStatus::savePoints.push_back(savepoint);
    }

    void testView(){
       if(!GameStatus::savePoints.empty()){
          Log("There is a save point"); // Can see that savePoints is not empty in the debugger. Everything looks ok here.
       }
    }

}

But if I have some other class:

class Foo{
    void something(){
         if(GameStatus::savePoints.empty()){  // In this class it appears that the vector is empty.
              //..do something.
         }
    }
}

I have a game loop which alternately executes code in Game and Foo, and it appears that in Game GameStatus::savePoints has a savePoint(is not empty), while in Foo it doesn't (appears empty). It makes no sense to me, because savePoints is static. So both classes should be accessing the same object.

Why does GameStatus::savePoints appear to have different values if different classes ?

Rahul Iyer
  • 19,924
  • 21
  • 96
  • 190

3 Answers3

4

A static variable outside of a class is only defined in the current compilation unit (compilation unit is the current source that is being compiled - i.e the current source file and all its included files). When you put a static variable in a header, each source file that includes that header gets its own copy.

There are two ways to fix this:

1 - Don't make it static - change the static keyword to 'extern', you will reference a global variable. You will then need to define the global variable in one source file. For example:

Header:

 extern std::vector<SavePoint>savePoints;

Game.cpp:

 std::vector<SavePoint> GameStatus::savePoints;

2 - Put it inside a class - static variables inside a class are only created once. Note that if you put it inside a class, you will need to declare it in the header and also define in a single compilation unit, otherwise you will get linker errors. For example:

Header:

 class Game {
 public:
     std::vector<SavePoint>savePoints;
 }

Game.cpp:

 std::vector<SavePoint> Game::savePoints;
The Dark
  • 8,453
  • 1
  • 16
  • 19
  • But if I remove the static keyword, then compilation fails with a Apple Mach-O Linker error. What do you mean by define in a single compilation unit ? The error is "duplicate symbol" for savePoints and appears many times in many files even though I don't use it anywhere – Rahul Iyer Jun 11 '15 at 08:29
  • But now it says non-static data member defined out of line. I'm confused. Which header should the extern variable be ? – Rahul Iyer Jun 11 '15 at 08:36
  • Also what change should I make to GameStatus ? – Rahul Iyer Jun 11 '15 at 08:38
  • If that is all that is in GameStatus, I would change it to a class. That would use my second example. You would then just need a `std::vector GameStatus::savePoints;` in some .cpp file. – The Dark Jun 11 '15 at 08:39
  • I'm confused by your answer. There is nothing else in GameStatus. I made it a class, and not I get Linker errors again. – Rahul Iyer Jun 11 '15 at 08:43
  • What is the error? Did you add the vector definition to one .cpp file? – The Dark Jun 11 '15 at 08:44
  • Sorry - I missed a namespace - that might have caused your problem – The Dark Jun 11 '15 at 09:36
1

static keyword has two meaning in C++.

Solution: You should put the declaration to the header with extern storage specifier instead of static, because you want it to be global. After that you should put the definition to one .cpp file, which is one compilation unit/object. This way you will have one instance of the vector, which is accessible from all other compilation units which includes the header.

header file:

namespace GameStatus{
    extern std::vector<SavePoint> savePoints;
}

cpp file:

    std::vector<SavePoint> GameStatus::savePoints;
szkj
  • 733
  • 4
  • 14
0

Believe you put your static vector in a header file and including in Game and Foo classes.

So, you need to clearly understand wt is mean by static first.

static variables exist for the "lifetime" of the translation unit that it's defined in.

For more refer this.

As you done in hear, when you include header, two separate instance will be initiated on vector. So those two instance act distinctly. That's why GameStatus::savePoints appear to have different values if different classes.

You can do, two things.

  1. define your vector as a a global variable.
  2. You a singleton class to wrap your vector.

For singleton refer this.

Community
  • 1
  • 1
ANjaNA
  • 1,404
  • 2
  • 16
  • 29