views:

389

answers:

2

I have a static class member incremented in the constructor. As per the rules, it is declared in the class and defined outside. This should be totally legal. Any ideas why I'm getting a duplicate symbol error?

class Player
{
   private:
      static int numPlayers;
   public:
      Player() { numPlayers++; }
};

int Player::numPlayers = 0;
A: 

Did you define multiple times ? ie define it in header file and include in multiple cpp files.

aJ
Thanks, aj. I don't know if you saw my "P.S.", but I have no .h for this one. However, I do have other .mm files that may be including it. Will check. ÷D
Old McStopher
oops! its in xcode is it. But concept remains same I believe. Just check if you have included multiple times.
aJ
Just checked. One other header file for an Objective-C class #includes it, but I haven't had had any problem calling the C++ code from Obj-C. Any other thoughts?
Old McStopher
I tested this in Xcode with a new project and it compiles fine, so yeah, I'm guessing it's defined elsewhere.
Nali4Freedom
Thanks guys, but I already did a project-wide search and find the reference nowhere. Quite odd. Seems like a GITM.
Old McStopher
+1  A: 

The problem is that you are not separating your DECLARATION from your DEFINITION. Consider:

class Player
{
   private:
      static int numPlayers;
   public:
      Player() { numPlayers++; }
};

The code above merely declares the existence of "numPlayers" in the class "Player". It does not, however, reserve any space or assign a memory address to the variable "Player::numPlayers". However:

int Player::numPlayers = 0;

The code above is a DEFINITION -- it reserves space for the object Player::numPlayers and designates a unique address for that object. Having that line appear more than once in a program violates the one-definition-rule. Now what is most likely happening is that you are including this file...

You should NEVER, EVER include a ".c", ".cpp", ".m", ".mm" or any other "source" file (i.e. a file that contains DEFINITIONS). You should only include "header" files (i.e. files containing purely DECLARATIONS). For many build systems, including Xcode, each source file is automatically compiled and linked into the project. If you include a source file from another source file, then the definitions get linked in twice -- first when it is compiled on its own and then again when it is referenced by another source file.

Since you are asking about Xcode... you can remedy this issue by unchecking the source file in the project detail view; a check mark next to a source file indicates that it will be compiled and linked-in for the current target. However, I strongly suggest that you leave your ".mm" file checked, create a ".h" file in which you put your declarations, and include the ".h" file instead of including one source file from another.

Michael Aaron Safyan
You're exactly right, Michael. The definition and declaration need to be separate. The program was originally a standalone .cpp. I was then integrating it into a Cocoa app and didn't have any problems with the #include of the .cpp until now. But now I know! Muchimas Gracimus
Old McStopher