Проблема в том, что вы не отделяете свою ДЕКЛАРАЦИЮ от своего ОПРЕДЕЛЕНИЯ. Рассмотрим:
class Player
{
private:
static int numPlayers;
public:
Player() { numPlayers++; }
};
Приведенный выше код просто объявляет о существовании «numPlayers» в классе «Player». Однако он не резервирует места и не присваивает адрес памяти переменной «Player :: numPlayers». Тем не менее:
int Player::numPlayers = 0;
Приведенный выше код является DEFINITION - он резервирует место для объекта Player :: numPlayers и назначает уникальный адрес для этого объекта. Наличие этой строки более одного раза в программе нарушает правило одного определения. Теперь, скорее всего, происходит то, что вы включаете этот файл ...
Вы НИКОГДА не должны, НИКОГДА включать «.c», «.cpp», «.m», «.mm» или любой другой «исходный» файл (то есть файл, который содержит ОПРЕДЕЛЕНИЯ). Вы должны включать только файлы заголовков (то есть файлы, содержащие чисто декларации). Для многих систем сборки, включая Xcode, каждый исходный файл автоматически компилируется и связывается с проектом. Если вы включаете исходный файл из другого исходного файла, то определения связываются дважды - сначала, когда он компилируется самостоятельно, а затем снова, когда на него ссылается другой исходный файл.
Поскольку вы спрашиваете о XCode ... вы можете устранить эту проблему, сняв флажок с исходного файла в подробном представлении проекта; Галочка рядом с исходным файлом указывает, что он будет скомпилирован и связан для текущей цели. Однако я настоятельно рекомендую оставить ваш файл «.mm» отмеченным, создать файл «.h», в который вы помещаете свои объявления, и включать файл «.h» вместо того, чтобы включать один исходный файл из другого.