1

我有一个非常奇怪的问题:

我使用我的一个基类:IEventlistener(),它被许多其他类实现。大多数情况下,系统都在工作。但是现在出现了一个非常奇怪的问题。

一旦类(CGUIService)实现了接口,一种方法(VGetListenerName)按预期工作,另一种方法(VHandleMessage)在我检查调用堆栈时得到一个纯调用,我不明白为什么-.-(似乎vtable不知何故被覆盖或超出范围...)

我做了一个截图,这样你就可以在我调用 VHandleMessage 之前看到变量,这当然会导致调试断言 R6025 - 纯虚函数调用,因为不知何故,实现的方法没有输入到 IEventlistener() 的 vtable 中。

高分辨率:www.fantasyhaze.com/cb/Error_purecall.png www.fantasyhaze.com/cb/Error_purecall.png

我希望有人能给我一个提示:)

编辑1。)

所以只是为了解释一下,我创建了一个新的屏幕截图,显示了相同的过程,但现在我已经包含了另外 2 个不纯的虚函数并且有一个实现(由于时间原因,我没有时间在使用该接口的每个类中再次实现所有方法)

紫色的是新的,红色的是不起作用的,橙色的是以前的方法,现在有效,现在仍然有效

您可以在左侧看到 VGetListenerName,VHandleEvent1,VHandleEvent2 工作(调试点 + 当前位置)并且这 3 个在 vtable 中......但不是重要的一个(红色)

高分辨率:www.fantasyhaze.com/cb/Error_purecall2.png vtable问题2

编辑2。)

解决方案:

主要问题是,CGUIService 继承自 IBase。为了访问该服务,我使用了一个存储每个服务的服务定位器。因此,它在 Instance Getters Service::GetServiceInstance() 中执行 static_cast,并且还执行了 static_cast 以将服务存储为 IBase。但是 IEventListener 没有在 IBase 中实现,而且服务在没有 IEventListener 的情况下被强制转换回 IBase 并且 vtable 不正常。现在 IBase 实现了 IEventListener 并且它可以工作,因为 static_cast 正确地转换了 IEventListener :)

谢谢你的提示:)

4

3 回答 3

2

通常纯虚调用是由在已经销毁的对象上调用虚函数引起的。当一个对象被销毁时,每个基类析构函数都将虚拟表指针设置为类的虚拟表。如果一个函数是纯虚拟的并且没有实现,则将纯虚拟调用处理程序地址放在虚拟表中。

于 2011-01-26T08:30:27.077 回答
1

很难从一个屏幕截图中判断,但从你给出的信息来看,我的第一个猜测是一个悬空指针——也许你试图在一个已经被销毁的对象上调用虚拟方法?另一种可能性是对象尚未完全构造,但这不太可能,因为这很可能需要多个线程中的一些竞争条件。

什么会导致 C++ 中的纯虚函数调用?相当详尽。

于 2011-01-26T08:30:51.510 回答
0

purecall 意味着无论出于何种原因,实现接口的类的虚函数都比它实现的接口少。这通常发生在以下情况:

  • 您将方法添加到接口中
  • 在调用者中使用新方法
  • 重新编译调用者,但不要重新编译实现(或重新编译实现并忘记重新链接它)

所以这很可能是构建过程的问题。检查您是否重新编译了调用者所依赖的所有内容,并在必要时重新链接调用者。

于 2011-01-26T08:29:38.837 回答