开发者

C++ virtual functions.Problem with vtable [duplicate]

This question already has answers here: Closed 11 years ago.

Possible Duplicate:

GCC C++ Linker errors: Undefined reference to 'vtable for XXX', Undefined reference to 'ClassName::ClassName()'

I'm doing a little project in C++ and I've come into some problems regarding virtual functions.

I have a base class with some virtual functions:

#ifndef COLLISIONSHAPE_H_
#define COLLISIONSHAPE_H_


namespace domino
{
class CollisionShape : public DominoItem
{
public:
// CONSTRUCTOR
//-------------------------------------------------

// SETTERS
//-------------------------------------------------

// GETTERS
//-------------------------------------------------

    virtual void GetRadius() = 0;
    virtual void GetPosition() = 0;
    virtual void GetGrowth(CollisionShape* other) = 0;
    virtual void GetSceneNode();

// OTHER
//-------------------------------------------------

    virtual bool overlaps(CollisionShape* shape) = 0;

};
}

#endif /* COLLISIONSHAPE_H_ */

and a SphereShape class which extends Co开发者_运维百科llisionShape and implements the methods above

/* SphereShape.h */

#ifndef SPHERESHAPE_H_
#define SPHERESHAPE_H_

#include "CollisionShape.h"

namespace domino
{
class SphereShape : public CollisionShape
{

public:
// CONSTRUCTOR
//-------------------------------------------------
    SphereShape();
    SphereShape(CollisionShape* shape1, CollisionShape* shape2);

// DESTRUCTOR
//-------------------------------------------------

    ~SphereShape();

// SETTERS
//-------------------------------------------------
    void SetPosition();
    void SetRadius();

// GETTERS
//-------------------------------------------------

    void GetRadius();
    void GetPosition();
    void GetSceneNode();
    void GetGrowth(CollisionShape* other);

// OTHER
//-------------------------------------------------

    bool overlaps(CollisionShape* shape);
};
}

#endif /* SPHERESHAPE_H_ */

and the .cpp file:

/*SphereShape.cpp*/
 #include "SphereShape.h"

#define max(a,b) (a>b?a:b)

namespace domino
{

// CONSTRUCTOR
//-------------------------------------------------

SphereShape::SphereShape(CollisionShape* shape1, CollisionShape* shape2)
{
}

// DESTRUCTOR
//-------------------------------------------------

SphereShape::~SphereShape()
{
}

// SETTERS
//-------------------------------------------------

void SphereShape::SetPosition()
{
}

void SphereShape::SetRadius()   
{
}

// GETTERS
//-------------------------------------------------

void SphereShape::GetRadius()   
{

}

void SphereShape::GetPosition()   
{  
}


void SphereShape::GetSceneNode()
{
}

void SphereShape::GetGrowth(CollisionShape* other)
{
}

// OTHER
//-------------------------------------------------

bool SphereShape::overlaps(CollisionShape* shape)
{
     return true;
}

}

These classes, along some other get compiled into a shared library.

Building libdomino.so
g++ -m32 -lpthread -ldl -L/usr/X11R6/lib -lglut -lGLU -lGL -shared     -lSDKUtil  -lglut  -lGLEW  -lOpenCL   -L/home/adrian/AMD-APP-SDK-v2.4-lnx32/lib/x86  -L/home/adrian/AMD-APP-SDK-v2.4-lnx32/TempSDKUtil/lib/x86 -L"/home/adrian/AMD-APP-SDK-v2.4-lnx32/lib/x86"   -lSDKUtil  -lglut  -lGLEW  -lOpenCL -o build/debug/x86/libdomino.so build/debug/x86//Material.o build/debug/x86//Body.o build/debug/x86//SphereShape.o build/debug/x86//World.o build/debug/x86//Engine.o build/debug/x86//BVHNode.o

When I compile the code that uses this library I get the following error:

../../../lib/x86//libdomino.so: undefined reference to `vtable for domino::CollisionShape'
../../../lib/x86//libdomino.so: undefined reference to `typeinfo for domino::CollisionShape'

Command used to compile the demo that uses the library:

g++ -o build/debug/x86/startdemo build/debug/x86//CMesh.o build/debug/x86//CSceneNode.o build/debug/x86//OFF.o build/debug/x86//Light.o build/debug/x86//main.o build/debug/x86//Camera.o -m32 -lpthread -ldl -L/usr/X11R6/lib -lglut -lGLU -lGL  -lSDKUtil  -lglut  -lGLEW  -ldomino  -lSDKUtil  -lOpenCL   -L/home/adrian/AMD-APP-SDK-v2.4-lnx32/lib/x86  -L/home/adrian/AMD-APP-SDK-v2.4-lnx32/TempSDKUtil/lib/x86  -L../../../lib/x86/ -L"/home/adrian/AMD-APP-SDK-v2.4-lnx32/lib/x86" 

(the -ldomino flag)

And when I run the demo, I manually tell it about the library:

LD_LIBRARY_PATH=../../lib/x86/:$AMDAPPSDKROOT/lib/x86:$LD_LIBRARY_PATH bin/x86/startdemo 

After reading a bit about virtual functions and virtual tables I understood that virtual tables are handled by the compiler and I shouldn't worry about it, so I'm a little bit confused on how to handle this issue.

I'm using gcc version 4.6.0 20110530 (Red Hat 4.6.0-9) (GCC)

Later edit: I'm really sorry, but I wrote the code by hand directly here. I have defined the return types in the code. I apologize to the 2 people that answered below.

I have to mention that I am a beginner at using more complex project layouts in C++.By this I mean more complex makefiles, shared libraries, stuff like that.


My problem was caused by the fact that I didn't define the body of virtual void CollisionShape::GetSceneNode().

The way to fix this is to either define the above function, or declare it as pure virtual as such:

virtual void CollisionShape::GetSceneNode() = 0;


Any non-pure virtual function must be defined, even if it's never used. A missing definition will often result in the 'vtable undefined' linker error, especially when the very first non-pure, non-inline virtual function of a class is left undefined. In your case, CollisionShape::GetSceneNode() is left undefined.

On an unrelated note, every class that has a virtual function needs a virtual destructor, every time, absolutely no exceptions whatsoever. The language unfortunately doesn't enforce this, so it's your responsibility. G++ has a flag, -Weffc++, which enables warnings for this and other common pitfalls, described in the Scott Meyers's book "Effective C++". I strongly recommend using this flag all the time. Using -Werror by default is also a good habit. Suppress individual warnings one by one, and only if there's no possibility to fix the code.


I can't say for certain whether this will fix your compilation error, but in any case you need to declare a virtual destructor (virtual ~CollisionShape()) in your CollisionShape class. Failure to do so will result in undefined runtime behavior when SphereShape is deleted through its base class pointer (a pointer to CollisionShape). Of course, since a virtual constructor is indeed added to a class's vtbl, I guess it's not beyond the realm of possibility that this is the culprit behind your error.

In Effective C++, Scott Meyers has the following to say.

The C++ language standard is unusually clear on this topic. When you try to delete a derived class object through a base class pointer and the base class has a nonvirtual destructor [...], the results are undefined. That means compilers may generate code to do whatever they like: reformat your disk, send suggestive mail to your boss, fax source code to your competitors, whatever. (What often happens at runtimme is that the derived class's destructor is never called. [...])


Due to the conflicting declarations of GetSceneNode, in your current code

virtual void GetSceneNode();

in the base class, and

SceneNode* GetSceneNode();

in the derived class, your code should not compile. You should not get to the linking stage. I'm pretty sure that the code that you're presenting is not your real code.

Hence, I downvoted the question.

But regarding the error that you evidently produced with some other code, it has been asked before on SO, and answered for example here.

Hence, I also voted to close the question.

Cheers & hth.,


This may not be the whole problem, but you are missing a return type on those functions. ie

virtual double GetPosition() = 0;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜