我从这里了解了关于adjustor thunk的信息。以下是一些引述:
现在,只有一个QueryInterface方法,但有两个入口,每个vtable都有一个。请记住,vtable中的每个函数都将对应的接口指针作为其“this”参数接收。对于QueryInterface(1)来说,它的接口指针与对象的接口指针相同,这很好。但对于QueryInterface(2)来说,情况就不一样了,因为它的接口指针是q,而不是p。
这就是adjustor thunk发挥作用的地方。
我想知道为什么vtable中每个函数都将对应的接口指针作为其“this”参数接收?这是接口方法在定位对象实例内的数据成员时所使用的唯一线索(基地址)吗?
更新
这是我最新的理解:
实际上,我的问题不是关于这个参数的目的,而是为什么我们必须使用相应的接口指针作为这个参数。抱歉我表达得不清楚。除了在对象的布局中使用接口指针作为定位器/支撑点之外,当然还有其他方法可以做到这一点,只要你是组件的实现者。
但对于我们组件的客户端来说,情况并非如此。
当组件以COM方式构建时,我们组件的客户端对我们组件的内部一无所知。客户端只能掌握接口指针,这正是将作为this参数传递到接口方法中的精确指针。在这种期望下,编译器别无选择,只能基于这个特定的this指针生成接口方法的代码。
因此,以上推理导致结果是:
必须确保vtable中的每个函数都接收相应的接口指针作为其“this”参数。
在“this指针调整thunk”的情况下,单个QueryInterface()方法存在两个不同的条目,换句话说,可以使用2个不同的接口指针来调用QueryInterface()方法,但编译器只会生成1份QueryInterface()方法。因此,如果编译器选择其中一个接口作为this指针,我们需要将另一个接口调整为所选接口。这就是this adjustor thunk的作用。
顺便说一下-1,如果编译器可以生成2个不同的QueryInterface()方法实例呢?每个方法基于相应的接口指针。这就不需要adjustor thunk,但需要更多的空间来存储额外但相似的代码。
顺便说一下-2:有时候问题从实现者的角度缺乏合理的解释,但从用户的角度来看可能更容易理解。