I am new to c++. I started now playing with classes and I am having a noob problem with statics.
class Test
{
public:
Test(){};
~Test(){};
static void test();
static Helper* helper;
};
void Test::test()
{
Object obj = Test::helper->getObject();
//...
}
When I try to compile it gives the error:
main.obj : error LNK2001: unresolved external symbol "public: static class Helper* Test::helper" (?helper#Test##2PAVHelper##A)
What is wrong with my code?
The first answer is correct. The reason behind this is that you need to allocate memory for static objects outside the class definition. If you define the the class in a header file, and include it in several cpp files, the compiler doesn't know where and how you want to create the object that 'helper' points to.
you need to define Test::helper. Write something like this outside the class:
Helper* Test::helper = new Helper;
Related
I'm using the bullet 3 physics library, which has the following struct definition inside one of the cpps:
struct btSingleContactCallback : public btBroadphaseAabbCallback
{
btCollisionObject* m_collisionObject;
btCollisionWorld* m_world;
btCollisionWorld::ContactResultCallback& m_resultCallback;
btSingleContactCallback(btCollisionObject* collisionObject, btCollisionWorld* world,btCollisionWorld::ContactResultCallback& resultCallback)
:m_collisionObject(collisionObject),
m_world(world),
m_resultCallback(resultCallback)
{
}
virtual bool process(const btBroadphaseProxy* proxy)
{
btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
if (collisionObject == m_collisionObject)
return true;
//only perform raycast if filterMask matches
if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
{
btCollisionObjectWrapper ob0(0,m_collisionObject->getCollisionShape(),m_collisionObject,m_collisionObject->getWorldTransform(),-1,-1);
btCollisionObjectWrapper ob1(0,collisionObject->getCollisionShape(),collisionObject,collisionObject->getWorldTransform(),-1,-1);
btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(&ob0,&ob1);
if (algorithm)
{
btBridgedManifoldResult contactPointResult(&ob0,&ob1, m_resultCallback);
//discrete collision detection query
algorithm->processCollision(&ob0,&ob1, m_world->getDispatchInfo(),&contactPointResult);
algorithm->~btCollisionAlgorithm();
m_world->getDispatcher()->freeCollisionAlgorithm(algorithm);
}
}
return true;
}
};
The problem is, the struct is never declared in any of the headers, I need to be able to create an object of this type however. The bullet libraries are statically linked, so I figured I should just be able to declare it myself in my main program as such:
struct btSingleContactCallback
: public btBroadphaseAabbCallback
{
btCollisionObject *m_collisionObject;
btCollisionWorld *m_world;
btCollisionWorld::ContactResultCallback &m_resultCallback;
btSingleContactCallback(btCollisionObject *collisionObject,btCollisionWorld *world,btCollisionWorld::ContactResultCallback &resultCallback);
virtual bool process(const btBroadphaseProxy *proxy);
};
This actually works fine, as long as I'm compiling in debug mode. However, when trying to compile in release mode, I'm getting an unresolved symbol error:
physenvironment.obj : error LNK2001: unresolved external symbol "public: __cdecl btSingleContactCallback::btSingleContactCallback(class btCollisionObject *,class btCollisionWorld *,struct btCollisionWorld::ContactResultCallback &)" (??0btSingleContactCallback##QEAA#PEAVbtCollisionObject##PEAVbtCollisionWorld##AEAUContactResultCallback#2##Z)
Could this have anything to do with c++'s name mangling? Is there a way to avoid it, without having to start making modifications in the library itself?
From a five minute look at the library code, you actually should use ContactResultCallback which is public, letting the implementation of btCollisionWorld::contactTest create and use the private btSingleContactCallback for you.
You did not implement the constructor.
This is best explained by the code itself. I want to use a QList<MyStruct> as a static member, but get a linker error 2001 (LNK2001). The code is in the same order in file MyClass.h
struct MyStruct{
double x;
...
};
typedef QList<MyStruct> MyStructList;
class MyClass
{
....
private:
static MyStructList _myValues; // does not work => LNK2001
MyStructList _myValues; // Test 1 OK
static QList<int> _myValues; // Test 2 OK
Any hints? Eran's answer (see comment below) is the right hint. SOLVED
LNK2001:
error: LNK2001: unresolved external symbol "private: static class QList<struct>
Yet another case of forgotten static member definition... MyStructList MyClass::_myValues should have been placed in one of the project's .cpp files.
class PossibilisticShellClustering
{
public:
PossibilisticShellClustering(void);
~PossibilisticShellClustering(void);
static void SetParameters(double deltaDistance);
static double deltaDistance
};
and i wanto to initialize static variable deltaDistance in function SetParameters. So in *.cpp file I wrote
void PossibilisticShellClustering::SetParameters(double deltaDistance)
{
PossibilisticShellClustering::deltaDistance = deltaDistance;
}
however I get linker erros
unresolved external symbol "public:
static double
PossibilisticShellClustering::deltaDistance"
(?deltaDistance#PossibilisticShellClustering##2NA)
Could somebody tell me why ?
PossibilisticShellClustering.obj
You need to defined PossibilisticShellClustering::deltaDistance in a source file somewhere in your program, usually a .cc or .cpp file.
double PossibilisticShellClustering::deltaDistance;
What you have in the class body (or would have if it was terminated with a ;) is only a declaration. Static data members also need a definition.
I have a class that has a static member, which I want to use in the class constructor, but the code doesn't compile, and I'm left with these errors:
fatal error LNK1120: 1 unresolved externals
error LNK2001: unresolved external symbol "protected: static class Collection A::collection"
Any help will be appreciated.
Thanks.
a.h:
class A
{
protected:
static Collection<A*> collection;
};
a.cpp:
A::A() {
A::collection.push_back(this);
}
You need to add
Collection<A*> A::collection;
to your a.cpp file.
In your .cpp you need to add:
Collection<A*> A::collection;
The .h only declared that there would be a copy somewhere. You need to provide that copy in the .cpp.
alternatively, if you don't want to put that line in a cpp file, you can use a static method which returns a reference to a static instance... i.e.
class A
{
public:
static Collection<A*>& collection()
{
static Collection<A*> singleInstance;
return singleInstance;
}
};
I was trying to incorporate the Singleton design pattern into my code, but I started getting a weird error:
main.obj : error LNK2005: "private: static class gameState * gameState::state" (?state#gameState##0PAV1#A) already defined in gameState.obj
If you're not familiar with the singleton pattern, it is basically used to enforce only 1 instance of a certain object in the entire program.
Here is the relevant code:
gameState.h:
class gameState
{
public:
static gameState* Instance() {return state;}
.
.
.
private:
gameState();
static gameState* state;
};
gameState* gameState::state = new gameState();
and right now I'm just using the instance of that object in the main.cpp file:
gameState *currState = gameState::Instance();
.
.
.
for_each(currState->getHumanPieces().begin(),currState->getHumanPieces().end(), drawPieces);
It would seem I am trying to redefine gameState::state, but can't figure out why... help anyone?
that solved that, but one error still remains, which I didn't actually post before as I thought it was just part of the other one:
error LNK2019: unresolved external symbol "private: __thiscall gameState::gameState(void)" (??0gameState##AAE#XZ) referenced in function "void __cdecl `dynamic initializer for 'private: static class gameState * gameState::state''(void)" (??__E?state#gameState##0PAV1#A##YAXXZ)
any good tip on how to fix that one as well?
Thanks both of you, its fixed :D
You need to put the definition of the static gameState* into exactly one source file, i.e. this line:
gameState* gameState::state = new gameState();
If you put it in a header which is included by multiple source files, each has a definition of gameState::state which leads to errors at link-time.
For the follow-up problem, use Vadakkumpadaths advice: you need to provide a definition for gameStates constructor, not only a declaration.
Add definition for your constructor to fix second linker error.
private:
gameState()
{
}
Use a header guard macro for the redefinition problem, and explicitly define your private constructor.