4

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;
2
  • P.S. This is all within one .cpp file. No separate header file. Commented Dec 7, 2009 at 8:17
  • I can't help but wonder if there is some build setting, flag, or project setting that is killing this. I just tested it in a blank Cocoa project and it works just fine. Bizarre. Commented Dec 7, 2009 at 9:02

2 Answers 2

10

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.

Sign up to request clarification or add additional context in comments.

1 Comment

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
1

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

5 Comments

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
oops! its in xcode is it. But concept remains same I believe. Just check if you have included multiple times.
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?
I tested this in Xcode with a new project and it compiles fine, so yeah, I'm guessing it's defined elsewhere.
Thanks guys, but I already did a project-wide search and find the reference nowhere. Quite odd. Seems like a GITM.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.