对vtable的未定义引用 当我构建我的C++程序时,我得到了错误信息
对“vtable”的未定义引用 这个问题的原因是什么?我怎么修理它对vtable的未定义引用 当我构建我的C++程序时,我得到了错误信息,c++,gcc,g++,C++,Gcc,G++,对“vtable”的未定义引用 这个问题的原因是什么?我怎么修理它 碰巧我得到了以下代码的错误(所讨论的类是CGameModule),我一辈子都无法理解问题是什么。起初,我认为这与忘记给一个虚拟的身体赋予功能有关,但据我所知,一切都在这里。继承链有点长,但下面是相关的源代码。我不确定我还应该提供什么信息 注意:构造函数似乎是发生此错误的地方 我的代码: class CGameModule : public CDasherModule { public: CGameModule(Dashe
碰巧我得到了以下代码的错误(所讨论的类是CGameModule),我一辈子都无法理解问题是什么。起初,我认为这与忘记给一个虚拟的身体赋予功能有关,但据我所知,一切都在这里。继承链有点长,但下面是相关的源代码。我不确定我还应该提供什么信息 注意:构造函数似乎是发生此错误的地方 我的代码:
class CGameModule : public CDasherModule {
public:
CGameModule(Dasher::CEventHandler *pEventHandler, CSettingsStore *pSettingsStore, CDasherInterfaceBase *pInterface, ModuleID_t iID, const char *szName)
: CDasherModule(pEventHandler, pSettingsStore, iID, 0, szName)
{
g_pLogger->Log("Inside game module constructor");
m_pInterface = pInterface;
}
virtual ~CGameModule() {};
std::string GetTypedTarget();
std::string GetUntypedTarget();
bool DecorateView(CDasherView *pView) {
//g_pLogger->Log("Decorating the view");
return false;
}
void SetDasherModel(CDasherModel *pModel) { m_pModel = pModel; }
virtual void HandleEvent(Dasher::CEvent *pEvent);
private:
CDasherNode *pLastTypedNode;
CDasherNode *pNextTargetNode;
std::string m_sTargetString;
size_t m_stCurrentStringPos;
CDasherModel *m_pModel;
CDasherInterfaceBase *m_pInterface;
};
继承自
class CDasherModule;
typedef std::vector<CDasherModule*>::size_type ModuleID_t;
/// \ingroup Core
/// @{
class CDasherModule : public Dasher::CDasherComponent {
public:
CDasherModule(Dasher::CEventHandler * pEventHandler, CSettingsStore * pSettingsStore, ModuleID_t iID, int iType, const char *szName);
virtual ModuleID_t GetID();
virtual void SetID(ModuleID_t);
virtual int GetType();
virtual const char *GetName();
virtual bool GetSettings(SModuleSettings **pSettings, int *iCount) {
return false;
};
private:
ModuleID_t m_iID;
int m_iType;
const char *m_szName;
};
- 您确定
具有析构函数的主体吗?它肯定不在这里-问题是它是否在.cc文件中CDasherComponent
- 从样式的角度来看,
应该明确定义其析构函数CDasherModule
virtual
- 看起来,
在末尾有一个额外的CGameModule
(在}
};//类的后面)
是否与定义CGameModule
和CDasherModule
的库相链接CDasherComponent
virtual ~CDasherModule()
{ }
所以,我发现了这个问题,这是一个糟糕的逻辑和不完全熟悉汽车制造/自动工具世界的组合。我将正确的文件添加到Makefile.am模板中,但我不确定构建过程中的哪个步骤实际创建了Makefile本身。所以,我是用一个旧的makefile编译的,它根本不知道我的新文件
感谢您的回复和GCC常见问题的链接。我一定会读到,为了避免这个问题出于真正的原因而发生。不管怎样,忘记虚拟析构函数上的实体会产生以下结果: 对“CYourClass的vtable”的未定义引用
我添加了一个注释,因为错误消息具有欺骗性。(这是在gcc版本4.6.3中出现的。)由于以下情况,可能会出现未定义的vtable引用。试试这个: A类包括:
virtual void functionA(parameters)=0;
virtual void functionB(parameters);
B类包括:
virtual void functionA(parameters)=0;
virtual void functionB(parameters);
function
定义为纯虚拟,其定义在B类中提供。
functionB
被定义为虚拟的(不是纯虚拟的),因此它试图在类A中找到它的定义,但您在类B中提供了它的定义
解决方案:
虚空函数b(参数)=0代码>
(经过测试后,该系统工作正常)
我只是因为.cpp文件不在makefile中而出现这个错误
通常,如果您忘记编译或链接到包含定义的特定对象文件,您将遇到此错误。如果所有其他操作都失败,请查找重复。在我读到另一篇文章中的引用之前,我一直被对构造函数和析构函数的明确的初始引用误导。这是任何未解决的方法。在我的例子中,我认为我已经将使用
char*xml
作为参数的声明替换为使用不必要的麻烦const char*xml
的声明,但是相反,我创建了一个新的声明,并保留了另一个声明。不是交叉发布,而是。如果你处理的是继承问题,那么第二次谷歌点击就是我错过的,即所有虚拟方法都应该被定义
例如:
virtual void fooBar() = 0;
有关详细信息,请参见answare。刚刚意识到上面已经提到了它,但它可能会帮助某些人。如果您正在使用Qt,请尝试重新运行qmake。如果此错误在小部件的类中,qmake可能没有注意到应该重新生成ui类vtable。这就为我解决了这个问题。 < p>在你定义了一个对象的虚拟函数的定义时,GNU C++编译器必须在哪里放置“代码”> vtab>代码(例如,一些对象的虚拟函数定义是在.CPP文件中的,其他的是在另一个.CPP文件中,等等)。p> 编译器选择将
vtable
放在定义第一个声明的虚拟函数的相同位置
现在,如果您出于某种原因忘记为对象中声明的第一个虚拟函数提供定义(或者错误地忘记在链接阶段添加编译后的对象),您将得到此错误
作为一个副作用,请注意,只有对于这个特定的虚拟函数,您不会得到传统的链接器错误,就像您缺少函数foo一样。我刚刚遇到了这个错误的另一个原因,您可以检查一下 基类将纯虚函数定义为:
virtual int foo(int x = 0);
而这个子类
int foo(int x) override;
问题在于输入错误,“=0”
应该在括号外:
virtual int foo(int x) = 0;
因此,如果你向下滚动这么远,你可能找不到答案-这是需要检查的其他内容。这里有很多关于各种答案的推测。下面我将给出一个相当小的代码来重现这个错误,并解释它发生的原因 M
#pragma once
class IBase {
public:
virtual void action() = 0;
};
#pragma once
#include "IBase.hpp"
class Derived : public IBase {
public:
Derived(int a);
void action() override;
};
#include "Derived.hpp"
Derived::Derived(int a) { }
void Derived::action() {}
#include <memory>
#include "Derived.hpp"
class MyClass {
public:
MyClass(std::shared_ptr<Derived> newInstance) : instance(newInstance) {
}
void doSomething() {
instance->action();
}
private:
std::shared_ptr<Derived> instance;
};
int main(int argc, char** argv) {
Derived myInstance(5);
MyClass c(std::make_shared<Derived>(myInstance));
c.doSomething();
return 0;
}
g++ -std=c++11 -o a.out myclass.cpp Derived.cpp
~/.../catkin_ws$ g++ -std=c++11 -o /tmp/m.out /tmp/myclass.cpp /tmp/Derived.cpp
/tmp/cclLscB9.o: In function `IBase::IBase(IBase const&)':
myclass.cpp:(.text._ZN5IBaseC2ERKS_[_ZN5IBaseC5ERKS_]+0x13): undefined reference to `vtable for IBase'
/tmp/cc8Smvhm.o: In function `IBase::IBase()':
Derived.cpp:(.text._ZN5IBaseC2Ev[_ZN5IBaseC5Ev]+0xf): undefined reference to `vtable for IBase'
/tmp/cc8Smvhm.o:(.rodata._ZTI7Derived[_ZTI7Derived]+0x10): undefined reference to `typeinfo for IBase'
collect2: error: ld returned 1 exit status
add_executable(myclass src/myclass.cpp src/Derived.cpp)
add_dependencies(myclass theseus_myclass_cpp)
target_link_libraries(myclass ${catkin_LIBRARIES})
#ifdef something
class Foo
{
public:
virtual void StartFooing();
};
#include "Foo.hpp"
void Foo::StartFooing(){ //fooing }
g++ Foo.cpp -c
#include "Foo.hpp"
int main()
{
Foo foo;
}
g++ main.cpp -o main
virtual ~A() = default;
virtual ~A() {}
virtual ~A();
A::~A() {}
# CMakeLists.txt
cmake_minimum_required(VERSION 3.12)
project (space_engine)
add_library (CelestialBody SHARED CelestialBody.cpp)
add_library (Planet SHARED Planet.cpp)
target_include_directories (CelestialBody PRIVATE ${CMAKE_CURRENT_LIST_DIR})
target_include_directories (Planet PRIVATE ${CMAKE_CURRENT_LIST_DIR})
target_link_libraries (Planet PUBLIC CelestialBody)
# hardened linker flags to catch undefined symbols
target_link_options(Planet
PRIVATE
-Wl,--as-needed
-Wl,--no-undefined
)