Reputation: 159
I'm working with Cocos2D and I created a Singleton C++ class that will store Game Settings information. This is what my class looks like:
#include <cstddef>
#ifndef __pyramidofdoom__GameSettings__
#define __pyramidofdoom__GameSettings__
#endif /* defined(__pyramidofdoom__GameSettings__) */
class GameSettings {
private:
static GameSettings* mGameSettings;
GameSettings(){ mGameSettings = this; }
int rowSelected = 0;
public:
GameSettings *getInstance() {
if (mGameSettings == NULL)
mGameSettings = new GameSettings();
return mGameSettings;
};
int getSelectedRow() { return rowSelected; }
void setSelectedRow(int row) { rowSelected = row;}
};
This is how I use it in cocos2D mm file:
GameSettings *gameSettings = gameSettings->getInstance();
if(multi)
gameSettings->setSelectedRow(3);
else
gameSettings->setSelectedRow(1);
Seems basic enough to have everything working fine.
This is the error I'm getting when I try to build now:
Undefined symbols for architecture i386:
"GameSettings::mGameSettings", referenced from:
GameSettings::getInstance() in GameLayer-E06C3150ABD8625A.o
GameSettings::GameSettings() in GameLayer-E06C3150ABD8625A.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I made sure that the cpp/h file is included for Compile Sources under Build Phases. I also added libc++ Library to see if that would fix it.
Upvotes: 0
Views: 426
Reputation: 64478
Any header or implementation where you #import
and use a cpp class must also use the .mm
extension.
So if you import the GameSettings.h and use the GameSettings cpp class in GameLayer.m you have to rename it GameLayer.mm.
You may want to prefer using an Objective-C class instead. Ideally scrap the whole singleton altogether. For example a reference in app delegate to a settings class instantiated on app launch works just as well.
Upvotes: 1
Reputation: 254421
You've declared mGameSettings
, but not defined it. You'll need a definition in a source file:
GameSettings* mGameSettings = NULL;
Alternatively, you could make it a local static variable:
GameSettings *getInstance() {
static GameSettings instance;
return instance;
}
which has the advantage of not leaking memory and being thread-safe (in a conforming C++11 compiler), if that's important to you.
Alternatively, get rid of the singleton. They're almost never a good idea (What is so bad about singletons?), especially in C++ where you get a host of lifetime issues in addition to the excessive coupling and restricted testability inherent in the pattern.
Also, don't use reserved names for your include guards: What are the rules about using an underscore in a C++ identifier? More importantly, it should guard the entire header - yours does nothing.
Upvotes: 1