我从这里读到了调整器thunk .这是一些引用:
现在,只有一个QueryInterface方法,但有两个条目,每个vtable一个.请记住,vtable中的每个函数都接收相应的接口指针作为其"this"参数.这对于QueryInterface(1)来说很好; 它的接口指针与对象的接口指针相同.但这对于QueryInterface(2)来说是个坏消息,因为它的接口指针是q,而不是p.
这是调节器雷声进来的地方.
我想知道为什么" vtable中的每个函数都接收相应的接口指针作为其"this"参数 "?它是接口方法用于在对象实例中定位数据成员的唯一线索(基址)吗?
这是我最新的理解:
实际上,我的问题不是关于这个参数的目的,而是关于为什么我们必须使用相应的接口指针作为this参数.对不起我的含糊不清.
除了使用界面指针作为对象布局中的定位器/立足点.只要您是组件的实现者,当然还有其他方法可以做到这一点.
但对于我们组件的客户来说情况并非如此.
当组件以COM方式构建时,组件的客户端对组件的内部结构一无所知.客户端只能占用接口指针,这是将作为this参数传递给接口方法的指针.在这种期望下,编译器别无选择,只能根据这个特定的this指针生成接口方法的代码.
因此上述推理导致了以下结果:
必须确保vtable中的每个函数必须将相应的接口指针作为其" this "参数接收.
在"this pointer adjustor thunk"的情况下,单个QueryInterface()方法存在2个不同的条目,换句话说,可以使用2个不同的接口指针来调用QueryInterface()方法,但编译器只生成1个副本QueryInterface()方法.因此,如果编译器选择其中一个接口作为this指针,我们需要将另一个调整为所选择的接口.这就是这个调节器thunk诞生的原因.
BTW-1,如果编译器可以生成2个不同的QueryInterface()方法实例呢?每一个都基于相应的接口指针.这不需要调整器thunk,但是需要更多空间来存储额外但相似的代码.
BTW-2:似乎有时问题从实施者的角度来看缺乏合理的解释,但可以从用户的指针视角更好地理解.
Dav*_*eas 11
从问题中this
删除COM部分,指针调整器thunk是一段代码,用于确保每个函数都获得this
指向具体类型子对象的指针.该问题出现了多重继承,其中基础对象和派生对象未对齐.
请考虑以下代码:
struct base {
int value;
virtual void foo() { std::cout << value << std::endl; }
virtual void bar() { std::cout << value << std::endl; }
};
struct offset {
char space[10];
};
struct derived : offset, base {
int dvalue;
virtual void foo() { std::cout << value << "," << dvalue << std::endl; }
};
Run Code Online (Sandbox Code Playgroud)
(并且无视初始化的缺乏).所述base
子对象derived
不与对象的开始对齐,有一个offset
之间在[1] .当指针指向derived
一个指针base
(包括隐式转换,但不重新解释会导致UB和潜在死亡的转换)时,指针的值会被偏移,以便(void*)d != (void*)((base*)d)
对于假定d
的类型对象derived
.
现在考虑一下用法:
derived d;
base * b = &d; // This generates an offset
b->bar();
b->foo();
Run Code Online (Sandbox Code Playgroud)
从base
指针或引用调用函数时会出现问题.如果虚拟调度机制发现最终的覆盖器在base
,则指针this
必须引用该base
对象,如b->bar
,其中隐式this
指针是存储在其中的相同地址b
.现在,如果最终覆盖在派生类中,b->foo()
则this
指针必须与找到最终覆盖的类型的子对象的开头对齐(在本例中derived
).
编译器所做的是创建一段中间代码.当调用虚拟调度机制时,在调度到derived::foo
中间调用之前,获取this
指针并将偏移量减去derived
对象的开头.此操作与向下转换相同static_cast<derived*>(this)
.请记住,此时,this
指针是类型的base
,因此它最初是偏移的,这有效地返回原始值&d
.
[1] 即使在接口的情况下也存在偏移- 在Java/C#意义上:仅定义虚拟方法的类 - 因为它们需要将表存储到该接口的vtable.
归档时间: |
|
查看次数: |
2774 次 |
最近记录: |