嵌套类和C ++中的多重继承之间的内存布局差异?

时间:2011-01-05 20:37:35

标签: c++ com object-layout

我试图理解COM如何指定其对象的布局,以便想要使用COM对象的客户端知道如何做到这一点。

我已经读过一个实现多个接口的COM对象可以用不同的方式完成它,包括使用嵌套类或多重继承。

我的理解是两种技术都必须生成相同的内存布局(符合COM规范),以便想要使用COM对象的客户端(例如在C中)知道如何操作。

所以我的具体问题是:使用多重继承与嵌套类实现的c ++对象的内存布局是否存在差异。

有人可以指出我指定COM对象布局的位置吗?

4 个答案:

答案 0 :(得分:8)

COM完全不知道对象的内存布局。所有它想要和需要的是一个函数指针表,当它调用IUnknown::QueryInterface()时。你如何实现它完全取决于你。 MFC使用嵌套类,几乎任何其他东西都利用C ++编译器中对多重继承的内置支持。 MSVC ++编译器实现它的方式与COM所需的完全兼容。这不是偶然的。使用您在书中列出的有关COM的样板代码,该代码显示了如何正确实现IUnknown。

答案 1 :(得分:5)

COM中指定的唯一“布局”是与每个接口关联的vtable(虚函数指针表)。每个接口都派生自IUnknown,因此无论客户端指向哪个对象接口,他都可以调用QueryInterface来获取同一对象上的不同接口。

对象没有强制布局。实际上,COM中对象的整体思想与OO语言中的类实例非常不同:了解同一COM对象是否暴露两个接口的唯一方法是在两个接口上调用IUnknown接口的QueryInterface - 当且仅当它们返回相同的接口指针时,它们才是同一对象的接口。

这是一个非常灵活的想法:

    例如,
  • 可能只有部分内部状态的COM对象被加载到内存中:当其他接口被请求时,其状态的其他部分可能会被延迟加载/分配。
  • COM对象的状态可能分布在几个非连续的内存区域中。

答案 2 :(得分:1)

我不相信单个COM接口可以具有多重继承,但是类可以通过多重继承实现多个接口。所以多继承布局是无关紧要的 - 每个接口都有一个独特的布局,由编译器提供指向正确布局的指针。

对于单继承,编译器将父类定义放在前面,然后是子类。这是由数据元素的标准定义的,但这又是无关紧要的,因为接口没有数据。该标准没有说明vtable的存在或布局,但是对于多态性的工作,它必须以相同的方式布局 - 父母优先,儿童优先。

如果通过多重继承实现多个接口,您将发现一个令人惊讶的事实。当您从一个接口向另一个接口转换指向类对象的指针时,地址将会改变!这是因为不同的接口(vtable)必须与接口声明匹配,因此必须有不同的布局。这些布局都包含在同一个对象中,但编译器在转换时会执行指针操作以使其到达正确的子集。

答案 3 :(得分:0)

如果混合中涉及虚函数,特别是如果大多数派生的类添加了它自己的任何一个,那么两种方法的内存布局都会有所不同。