gpt4 book ai didi

c++ - 为什么在具有多个接口(interface)() 的对象中实现 QueryInterface() 时我需要显式向上转换

转载 作者:IT老高 更新时间:2023-10-28 22:33:26 25 4
gpt4 key购买 nike

假设我有一个实现两个或多个 COM 接口(interface)的类:

class CMyClass : public IInterface1, public IInterface2 {
};

我看到的几乎所有文档都表明,当我为 IUnknown 实现 QueryInterface() 时,我明确地将 this 指针向上转换为其中一个接口(interface):

if( iid == __uuidof( IUnknown ) ) {
*ppv = static_cast<IInterface1>( this );
//call Addref(), return S_OK
}

问题是为什么我不能直接复制这个

if( iid == __uuidof( IUnknown ) ) {
*ppv = this;
//call Addref(), return S_OK
}

文档通常说,如果我这样做,我将违反对同一对象的任何 QueryInterface() 调用必须返回完全相同的值的要求。

我不太明白。他们的意思是,如果我对 IInterface2 进行 QI() 并通过该指针调用 QueryInterface(),C++ 将传递 this 与如果我对 IInterface2 进行 QI() 略有不同,因为 C++ 每次都会使 this 指向一个子对象?

最佳答案

问题是 *ppv 通常是一个 void* - 直接将 this 分配给它只会简单地采用现有的 this 指针并给 *ppv 它的值(因为所有指针都可以转换为 void*)。

这不是单继承的问题,因为对于单继承,所有类的基指针总是相同的(因为 vtable 只是为派生类扩展)。

但是 - 对于多重继承,您实际上最终会得到多个基指针,具体取决于您正在谈论的类的“ View ”!这样做的原因是,通过多重继承,您不能只扩展 vtable - 您需要多个 vtable,具体取决于您正在谈论的分支。

因此您需要强制转换 this 指针以确保编译器将正确的基指针(用于正确的 vtable)放入 *ppv

这是一个单继承的例子:

class A {
virtual void fa0();
virtual void fa1();
int a0;
};

class B : public A {
virtual void fb0();
virtual void fb1();
int b0;
};

A 的 vtable:

[0] fa0
[1] fa1

用于 B 的 vtable:

[0] fa0
[1] fa1
[2] fb0
[3] fb1

注意,如果你有 B vtable 并且你把它当作一个 A vtable 它只是工作 - A 的成员的偏移量> 正是您所期望的。

这是一个使用多重继承的示例(使用上面的 AB 的定义)(注意:只是一个示例 - 实现可能会有所不同):

class C {
virtual void fc0();
virtual void fc1();
int c0;
};

class D : public B, public C {
virtual void fd0();
virtual void fd1();
int d0;
};

用于 C 的 vtable:

[0] fc0
[1] fc1

用于 D 的 vtable:

@A:
[0] fa0
[1] fa1
[2] fb0
[3] fb1
[4] fd0
[5] fd1

@C:
[0] fc0
[1] fc1
[2] fd0
[3] fd1

以及D的实际内存布局:

[0] @A vtable
[1] a0
[2] b0
[3] @C vtable
[4] c0
[5] d0

请注意,如果您将 D vtable 视为 A 它将起作用(这是巧合 - 您不能依赖它)。但是 - 如果您在调用 c0 时将 D vtable 视为 C (编译器期望在 vtable 的插槽 0 中),您'会突然调用a0!

当你在 D 上调用 c0 时,编译器实际上会传递一个假的 this 指针,该指针有一个看起来像C.

所以当你在 D 上调用 C 函数时,它需要调整 vtable 以指向 D 对象的中间(在@C vtable) 在调用函数之前。

关于c++ - 为什么在具有多个接口(interface)() 的对象中实现 QueryInterface() 时我需要显式向上转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1742848/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com