在真实的代码中,我遇到了一些“非虚拟的thunk”功能:
c++filt说:

; `non-virtual thunk to'QTextCodecPlugin::create(QString  const&)
    EXPORT _ZThn8_N16QTextCodecPlugin6createERK7QString
_ZThn8_N16QTextCodecPlugin6createERK7QString
   SUB.W   R0, R0, #8
   B.W     _ZN16QTextCodecPlugin6createERK7QString; QTextCodecPlugin::create(QString  const&)

; End of function `non-virtual thunk to'QTextCodecPlugin::create(QString  const&)


; `non-virtual thunk to'QTextCodecPlugin::~QTextCodecPlugin()
    EXPORT _ZThn8_N16QTextCodecPluginD1Ev

_ZThn8_N16QTextCodecPluginD1Ev
    SUB.W  R0, R0, #8
    B.W    _ZN16QTextCodecPluginD2Ev; QTextCodecPlugin::~QTextCodecPlugin()

; End of function `non-virtual thunk to'QTextCodecPlugin::~QTextCodecPlugin()


这些“非虚拟重击”的作用和原因为何?

#1 楼

这些是用于实现多重继承的对象虚拟表条目。简而言之,sub指令与将正确的派生类对象大小偏移到虚拟表有关;但是以下(冗长的)文章的解释工作要比我这里能做的更好:http://thomas-sanchez.net/computer-sciences/2011/08/15/what-every-c-programmer-should- know-the-hard-part /

更新:
上面的链接不再起作用,但是在webarchive.org上有此页面的副本:
http:// web.archive.org/web/20131210001207/http://thomas-sanchez.net/computer-sciences/2011/08/15/what-every-c-programmer-should-know-the-hard-part/

#2 楼

答案应该真正说明虚拟的thunk和非虚拟的thunk之间的区别。它们在操作上相同,但名称不同。虚拟继承的基类的重击称为虚拟重击,而基础对象将在对象的末尾,而对象不在对象开头的常规继承类的重击称为非虚拟重击。

如果您有C继承自A和B,则A和C的虚拟指针将被粘贴到相同的地址,而B将被偏移。 B的虚拟表将必须包含非虚拟thunk,这将偏移指向对象开始的指针,因为实际上被调用的方法是C的一种,它接受指向C对象的指针,并且如果使用了此虚拟表那么它将接收到指向B的多态指针,因此需要在表中进行大量调用。

如果D继承自B和C,而B和C则实际上继承自B A,那么这意味着D和B虚拟指针将粘贴在同一位置C将处于偏移位置,并且需要非虚拟重击,而A将在对象的末尾并需要虚拟思考。

虚拟thunk通过以下方式使对象地址偏移-32,并且非虚拟thunk将对象地址偏移例如。 -16.