对Vtable错误的奇怪的未定义引用

Strange Undefined Reference to Vtable Error

本文关键字:未定义 引用 错误 Vtable      更新时间:2023-10-16

。。。不管出于什么原因,我似乎都搞不清楚。我也尝试过在Qt中清理我的构建文件,但似乎也不起作用。

首先,让我声明,我很清楚,当C++类继承了一个具有纯虚拟函数的抽象类,而继承类(无论出于何种原因)还没有定义它们时,通常会出现这个错误。

问题是不存在与指定的错误相关的纯虚拟函数。

我有一个称为CoordinateObject的基类,其中有一个抽象类Shape,它继承自该基类,还有一个FirstPersonCamera类,它也继承自CoordinateObject。现在,我的Cubef类继承自Shape,当我尝试编译代码时,我会得到以下错误:

./debugCamera.o:Camera.cpp:(.rdata$_ZTVN6Engine17FirstPersonCameraE[vtable for Engine::FirstPersonCamera]+0x10): undefined reference to `Engine::FirstPersonCamera::InitCoordinates()'
./debugCubef.o:Cubef.cpp:(.rdata$_ZTVN6Engine5CubefE[vtable for Engine::Cubef]+0x1c): undefined reference to `Engine::Cubef::InitCoordinates()'

最初,当CoordinateObject确实有一个纯虚拟函数InitCoordinates时,就会出现这种情况,然而,在尝试在每个选择继承它的类中正确实现它之后,它仍然不起作用。因此,我删除了它(以及除基类本身之外的所有类实现和声明)。

所以,我需要确切地知道我做错了什么。我会发布如下代码:

代码

坐标对象.h

class CoordinateObject
    {
    public:
        CoordinateObject( void );
        virtual ~CoordinateObject( void )
        {
            delete mWorld;
            delete mObject;
            delete mInertial;
        }
        Matrix3fv GetInertialSpace( void );
        Matrix3fv GetObjectSpace( void );
        Matrix3fv GetWorldSpace( void );
        void SetInertialSpace( Matrix3fv* space );
        void SetInertialSpace( Matrix3fv& space );
        void SetObjectSpace( Matrix3fv* space );
        void SetObjectSpace( Matrix3fv& space );
        void SetWorldSpace( Matrix3fv* space );
        void SetWorldSpace( Matrix3fv& space );
    protected:
        Matrix3fv* mWorld;
        Matrix3fv* mObject;
        Matrix3fv* mInertial;
    private:
        void InitCoordinates( void );
    };

形状.h

#pragma once
#include "stdafx.h"
namespace Engine
{
    class Circlef;
    class Shape
            : public CoordinateObject
    {
    public:
        Shape( Vector3f& center, float radius );
        virtual ~Shape( void )
        {
            delete mCenter;
        }
        virtual void Collide( Shape& s ) = 0;
        virtual void Collide( const Circlef& s ) = 0;
        Vector3f* Center( void );
        virtual void Draw( void ) = 0;
        void SetCenter( Vector3f newCenter );
        void SetCenter( Vector3f* newCenter );
        float mRadius;
    protected:
        Vector3f* mCenter;
    private:
        void InitShape( Vector3f& center );
    };
}

立方英尺高度

#pragma once
#include "stdafx.h"
namespace Engine
{
    class Cubef
            : public Shape
    {
    public:
        Cubef( Vector3f center, float radius );
        virtual ~Cubef( void )
        {
            delete mCenter;
        }
        virtual void Collide( Shape& s );
        virtual void Collide( const Circlef& s );
        virtual void Draw( void );
        void Draw( const Vector3f& camPosition );
        void Draw( const Vector3f& newCenter, float radius, const Vector3f& camPosition );
        void DrawFront( void );
        void DrawBack( void );
        void DrawLeft( void );
        void DrawRight( void );
        void DrawTop( void );
        void DrawBottom( void );
        inline double GetEdgeLength( void ) const
        {
            return mEdgeLength;
        }
        inline int GetCubeId( void ) const
        {
            return mCubeId;
        }
        inline double GetSurfaceArea( void ) const
        {
            return mSurfaceArea;
        }
        void Rotatef( float angle, AngleOfRotation aor );
        void Rotatef( float angle, Vector3f* toRotate, AngleOfRotation aor );
    protected:
        static int CubeCount;
        const int mCubeId;
        float mSurfaceArea;
        float mEdgeLength;
    private:
    };
}

最后,Camera.h

namespace Engine
{
    extern const float PI;
    extern const double MOUSE_Y_SENSITIVITY;
    extern const double MOUSE_X_SENSITIVITY;
    extern const int FP_CAM_QUAT_ARR_LEN;
    class FirstPersonCamera
            : public CoordinateObject
    {
    public:
        FirstPersonCamera( void );
        ~FirstPersonCamera( void );
        void Rotate( SDL_Event*& event );
        inline Vector3f GetPosition( void ) const
        {
            return *mPosition;
        }
        inline Matrix3fv GetRotation( void ) const
        {
            return *mRotation;
        }
        void MoveCamera( const SDL_KeyboardEvent& event );
        void UpdateCamera( void );
        void UpdateCamera( const Vector3f& coords );
    private:
        void InitCamera( void );
        Matrix3fv* mRotation;
        Vector3f* mPosition;
        float mAngle;
    };
}

我甚至尝试过在任何派生类的初始化列表中初始化CoordinateObject的ctor的默认构造函数,但老实说,我怀疑这有什么不同。

示例

(来自Shape.h

Shape::Shape( Vector3f& center, float radius )
    : CoordinateObject(),
      mRadius( radius )
{
    InitShape( center );
}

正如您所看到的,CoordinateObject的构造函数在这里被调用,初始化列表中,尽管它是默认的。

我不知道该怎么办。

暂停?

从错误消息来看,您肯定有过时的debug\Camer.o和debug\Cubef.o文件(InitCoordinates()是虚拟的时遗留下来的)。

不要相信你的make clean-查看那些.o文件上的时间戳或手动删除它们。

通常,当构建在Debug中工作而在Release中失败时,原因是:

  • 陈旧文件(makefile问题,特别是makedependent不准确)
  • #在一个构建中被触发但在另一个中没有被触发的ifdef(硬编码或来自-D标志)

根据我的经验,我遇到过这两种类型的错误。

更新

我在MinGW的Debug下编译了它,但现在我切换到Release(无论出于什么原因),它成功了!

为什么会这样,我不太确定。也许是Qt(甚至MinGW)出现了故障?