I'm following a Cocos2D-X tutorial for iOS on XCode 5 and the instructor started off by creating a bunch of classes and header files. Among those is a header file called "Utils.h" that contains some static functions
class Utils
{
public:
static Game* gameLayer();
static HUD* hudLayer();
static cocos2d::CCLayer* layerWithTag(int tag);
static cocos2d::CCSize s();
static cocos2d::CCAnimate* getAnimationWithFrames(int from, int to);
static void scaleSprite(cocos2d::CCSprite * sprite);
static float getScale();
static void setScale(float s);
static float getArtScaleFactor();
static void setArtScaleFactor(int s);
};
The s() functions is defined in Utils.cpp to just return CCDirector::sharedDirector()->getWinSize();
Now, the problem is: when the s() function is called in my main menu scene (Utils::s().width for instance), I get this error "Linker command failed with exit code 1 (use -v to see invocation)" and "Symbol(s) not found for architecture i386". However, when I deleted the s() function definition from Utils.cpp and just added the function in the class in the header file so that it becomes
//Utils.h
class Utils
{
public:
.......
static cocos2d::CCSize s()
{
return CCDirector::sharedDirector()->getWinSize();
}
......
It compiles without an error...
Why is it that I get this error when the function is in the cpp file instead of the header file? I know my problem is already solved but it's just driving me crazy
Thanks! :)
Edit: I thought this was a given but to be clearer, in the main menu scene I included Utils.h not Utils.cpp
Please note that such errors also appear when you have declared a function in one file (say Cpp) and not in the .h file.
Most common reason that i have seen is because one declares a function in the .h file but forget to give the implementation.
Related
I'm currently learning java at my university and I'm trying to keep up with C++ while we cover new stuff. In java I have static member fields and methods that are independent of objects created. This is what I'm aiming to do in c++.
I have a static function in the Collision.h file.
The program will compile only when I define the static function in the header file.
//.h file
static void debug() //compiles and function is usable
{
std::cout << "DEBUG from the collision class called in main" << std::endl;
}
//.cpp file
// <nothing>
when I define the function in the .cpp file the program will not compile.
//.h file
static void debug(); //does not compile
//.cpp file
void debug() //I've tried with and without static keyword here.
{
std::cout << "DEBUG from the collision class called in main" << std::endl;
}
I'm at a loss as to why this latter situation doesn't work. Are .cpp files only used when an object is created?
Thanks for any help. :)
A free function is already independent from objects. In C++ static has a few different meanings. For free functions, static means that the function has internal linkage, meaning it is only visible in the current translation unit (cpp file + headers).
Since your function is declared in a header you don't want the static keyword, otherwise every file that includes it will need to implement it (they essentially get there own version of the function). You also shouldn't define it in the header - leave it as void debug();. Define it in a cpp file instead.
How to solve this problem?
Just getting following errors:
g++ output:
duplicate symbol _game in:
/var/folders/w6/yqp0s0t92hl5g842hg8tztfr0000gn/T/main-62666f.o
/var/folders/w6/yqp0s0t92hl5g842hg8tztfr0000gn/T/Game-a5a31d.o
duplicate symbol _game in:
/var/folders/w6/yqp0s0t92hl5g842hg8tztfr0000gn/T/main-62666f.o
/var/folders/w6/yqp0s0t92hl5g842hg8tztfr0000gn/T/Write-83f8ee.o
It seems like the problem is not in the header files.
EDIT: Header files look like this:
#ifndef GAME_H
#define GAME_H
#include "Color.h"
#include "Tile.h"
class Game
{
public:
Game();
~Game();
Color getActivePlayer();
void setStarttile(Tile Firststarttile);
Color togglePlayer();
void setRunning(bool run);
char newActiveplayer;
void run();
void runsecondmethod();
private:
Game(const Game &);
Color Activeplayer;
Tile *Starttile;
bool Running;
}game;
#endif
You have instantiated a Game instance in your header file "Game.h", and since this is being included in multiple files you end up with multiple instances of game at link time. Change:
class Game
{
public:
...
}game;
to:
class Game
{
public:
...
};
extern Game game;
and then add:
Game game;
in one of your .cpp files.
In your header file (the one included from Write.cpp and GameBoard.cpp), you're likely to have an instantiation instead of a declaration.
Common cases/pitfalls :
missing extern before global variables
having function implementation (i.e. having void foo(Bar& b) {} instead of void foo(Bar& b);
Without more details, hard to help...
Look for where addnewtile function is defined for example...
EDIT
With more details
class Game
{
(zip)
}game;
This is declaring the class Game and creating a game object each time you include the header file.
Use
class Game
{
(zip)
};
In the header file and Game game; in the cpp
Or use a singleton pattern / static instance.
I'm a novice programmer, still in the midst of trying to learn C++ and OOP design basics. The project that I've been working on to teach myself is a C++ game that has multiple classes, files, states, etc. However, I keep running into snags with file organization that range from simply struggling with where to create objects to compile-breaking linker errors.
Here's an example of some of the errors that I've been getting:
1>SMGA.obj : error LNK2005: "class Engine smgaEngine" (?smgaEngine##3VEngine##A) already defined in Engine.obj
1>SplashScreenState.obj : error LNK2005: "class Engine smgaEngine" (?smgaEngine##3VEngine##A) already defined in Engine.obj
1>StateManager.obj : error LNK2005: "class StateManager gameStateManager" (?gameStateManager##3VStateManager##A) already defined in Engine.obj
1>MSVCRTD.lib(cinitexe.obj) : warning LNK4098: defaultlib 'msvcrt.lib' conflicts with use of other libs; use /NODEFAULTLIB:library
I've looked around online and I've seen a lot of ~similar~ problems that involve bad include guards or the inclusion of .cpp files instead of .h files. But I haven't done that in my code, so I'm at a loss.
Now, I'm guessing that the error is telling me that I'm trying to create the smgaEngine object of the Engine class (and the gameStateManager object of the StateManager class) twice, but I'm not sure why...
The thing that stands out about these two objects (smgaEngine and gameStateManager) is that I declared them in their corresponding class' .h files immediately after the class declaration. Could this be the issue? - They're still within the include guards, and I wasn't too sure about where else to put them in my code... Would this sloppy coding be the cause of linker errors?
Here's one of the suspect classes...
#ifndef ENGINE_H
#define ENGINE_H
#include <SDL.h>
#include "Timer.h"
class Engine
{
private:
static const int screenWidth = 480;
static const int screenHeight = 270;
static const int screenBPP = 24;
bool running;
SDL_Surface *mainScreen;
SDL_Event eventHolder;
Timer fpsTimer;
public:
Engine();
~Engine();
void init();
void handleEvents();
void handleLogic();
void handleRender();
void cleanUp();
SDL_Event *getEvent();
SDL_Surface *getMainScreen();
bool isRunning();
void setRunning(bool tempRunning);
} smgaEngine;
#endif
And here's the other one:
#ifndef STATEMANAGER_H
#define STATEMANAGER_H
#include "SplashScreenState.h"
#include <vector>
class GameState;
class StateManager
{
private:
std::vector<GameState*> stateStack;
SplashScreenState *splashState;
public:
StateManager();
~StateManager();
void init();
void changeState( GameState *tempNextState );
void addState( GameState *tempNextState );
void removeState();
//returns the back() element of the stateStack vector..
GameState* getTopState();
void handleEvents();
void handleLogic();
void handleRender();
} gameStateManager;
#endif
I've been trying my best to learn C++ and OOP, but I've really been struggling. It seems that every time I attempt to make clean code with encapsulated classes, I end up with a confusing mess. I'm trying to prevent a high degree of class coupling, but I often end up with either linker errors or a lack of ability to communicate between classes... Is it creation of class instance objects within the header files that is causing these errors or is it something else? And if that is the cause of my linker errors, then where should I be creating these objects?
You have defined two global variables, smgaEngine and gameStateManager in your header files, and you have included those header files in two (or more) source files. So you get multiple definition errors. Include guards don't stop header files being included twice in different source files (how could they?) they stop header files being included twice in the same source file.
You're quite close to the correct answer (at least you have a good understanding of the problem). The right way is this
// header file Engine.h
class Engine
{
};
extern Engine smgaEngine;
// in one source file (say Engine.cpp)
Engine smgaEngine;
What you have now is a declaration in the header file (extern makes it a declaration), but a definition in the source file. You can have as many declarations as you like (as long as they are consistent) but you must have only one definition. So for global variables put declarations in the header file and put a definition in one of the source files.
i have a full static class, using a std::map
thats the simplified case
.h
#ifndef KEYBOARD_H
#define KEYBOARD_H
#include <map>
class Keyboad {
static std::map<char, bool> pressed;
static void keyPressedEvent(char _key);
};
#endif
.cpp
#include "Keyboard.h"
void Keyboard :: keyPressedEvent(char _key) {
Keyboard :: pressed[_key] = true;
}
but there is a problem with the static member variable, because i get
Undefined symbols:
"Keyboard::pressed", referenced from:
__ZN15Keyboard7pressedE$non_lazy_ptr in Keyboard.o
(maybe you meant: __ZN15Keyboard7pressedE$non_lazy_ptr)
ld: symbol(s) not found
collect2: ld returned 1 exit status
when i remove it, it runs ok
why do i get this problem, there should be no problem when using a static variable :/
thanks
You need to define the pressed map in your .cpp file:
#include "Keyboard.h"
std::map<char, bool> Keyboard::pressed;
// The rest as before
You should add this to .cpp file
std::map<char, bool> Keyboad::pressed;
Consider static class members as global variables. Compiler should allocate memory for them inside of the only object file. So you should define them in corresponding source file.
A static member in the class definition is just a declaration. You
still have to provide the definition, exactly like you did for the
function. Just add
std::map<char, bool> Keyboard::pressed;
in a source file somewhere. (For mapping chars, you might also
consider a simple
bool Keyboard::pressed[256];
, indexed with the char converted to unsigned char.)
Consider a simpler case. A global variable counter is declared in multiple header files:
int counter; // This appears in 3 HEADER files.
Few source files do refer it. When you compile and link it, compiler would emit linker error saying that counter is already defined in some set of .OBJ files (Error message is dependent on compiler).
To solve this, you just put extern in front of variable (in all header files):
extern int counter; // This appears in 3 HEADER files.
And when you rebuild it, linker will complain that counter is not defined anywhere.
To solve this issue, you define this variable in one source file (any one):
int counter;
And it resolves the issue.
The static-variable of class is nothing but a global variable, which can be accessed by classname::variablename format. The accessibility is same - global.
i accessed a static function(funA()) in class A (all function in this class is static) but getting Undefined reference error. I included header
Please help.
// H file
Class A
{
static void funA();
};
// Cpp file
void A::funA() { }
Accessed in class B
void B::funB()
{
A::funA()
}
Make sure you have something like this on your header:
// a.h
class A {
static void funA();
};
// a.cpp
void
A::funA() {
// do something on your function
}
From your edit it seems you're missing the public: part before static void FunA().. did you just forget to edit it in or maybe it's really missing in your .cpp?
Have you included the right .lib file, if necessary?
You should always initizalize static functions and variables in cpp file before using
Is it possible that you have double declaration in your code, because this would give you a compiler error.