我读过两篇将 COM 对象描述为基本上是C++ 类的文章。这是真的?这是我正在阅读的一篇文章:http: //www.codeproject.com/Articles/13601/COM-in-plain-C
它描述了一种在 C 中创建 COM 对象的方法。COM 强制该结构的第一个成员是某些函数指针。
我没有看到 COM 对象和 C++ 之间的具体关联,尽管我可以理解这种关系很容易理解。
我读过两篇将 COM 对象描述为基本上是C++ 类的文章。这是真的?这是我正在阅读的一篇文章:http: //www.codeproject.com/Articles/13601/COM-in-plain-C
它描述了一种在 C 中创建 COM 对象的方法。COM 强制该结构的第一个成员是某些函数指针。
我没有看到 COM 对象和 C++ 之间的具体关联,尽管我可以理解这种关系很容易理解。
COM 准确地指定了它的对象的布局方式:将虚函数表指针(又名 vtable 指针)作为对象中的第一个成员。它的设计使布局与 Microsoft 编译器布局 C++ 对象的方式相同,因此您可以拥有一个与手动定义的 C 结构相同编译的 C++ 类。
只要您使用的是 Microsoft 编译器,那么是的,COM 对象基本上就是一个 C++ 类实例。但是,如果您使用不同的编译器,则需要特别注意确保它以相同的方式布置 C++ 对象。只要您不使用多重继承或虚拟继承,大多数编译器都会将 vtable 放在首位,因此通常可以正常工作,但有些编译器会将 vtable 放在最后。确保阅读编译器的文档并确定它是否与 COM 兼容。
IMO,这在一定程度上取决于您如何定义 COM 对象。如果 COM 对象是与 COM 二进制接口兼容的任何对象,那么该对象是否在 C++ 内部实现是一个实现细节。它可以用C++实现,但也可以用各种其他方式实现,只要你通过COM接口访问它,它基本上是无关紧要的。
话虽如此,正如 Adam 和 WhozCraig 指出的那样,COM 的二进制接口在设计时考虑了 MSVC 的 C++ 编译器。在 MSVC C++ 中编写 COM 对象是创建 COM 对象的“原始”方式。所以这两者肯定有着交织的历史,而且确实 COM 二进制接口规范与 MSVC 如何布置 C++ 对象有很多共同之处。但是,MSVC 编译器仍然必须生成 COM 绑定作为“额外”编译步骤(例如,COM 类型库和 C++ 导入头文件,以便其他 C++ 项目可以导入 COM 库)。
COM 对象规范旨在利用 C++ 对象的现有二进制布局,因此从这个意义上说,它们基于 C++ 类。
创建 IDispatch 接口是为了更容易从不能使用 C++ vtables 的语言中使用 COM。它为 COM 调用添加了额外的间接层。
COM 代表组件对象模型。它是使用由类 ID (CLSID) 标识的不同类型的组件构建的库,这些组件是全局唯一标识符 (GUID)。每个 COM 组件都通过一个或多个接口公开其功能。组件支持的不同接口使用接口 ID (IID) 相互区分,IID 也是 GUID。
添加另一个答案,因为我认为关于 COM 和 C++ 有一些非常有用的事情需要了解,而其他答案没有涵盖。
或许要得到三件重要的事情是:
COM 对象实际上是COM 接口的集合,它们相互协作以呈现具有共享 COM 对象身份的外观(您可以从任何接口 QI 到任何其他接口,其中一个接口就是您在 QI 时随时返回的接口对于 IUnknown,又名“规范未知”)。
COM 接口恰好与 MSVC 和所有(AFAIK)Windows 编译器实现的 C++ 对象的 vtable 具有相同的布局。
COM 更侧重于接口。C++ 更侧重于类。
第二个是使在 C++ 中实现 COM 对象变得简单的原因。但其中的第一个意味着主题有很多变化。所以你可以有:
在 C++ 中作为实现一个接口的类实现的单接口 COM 对象
具有多个接口的单个 COM 对象,它被实现为使用 C++ 的多重继承实现多个接口的 C++ 类。
具有多个接口的单个 COM 对象,它实现了一组协作的 C++ 对象实例,可能每个 COM 接口一个 C++ 类;或者一个 C++ 类实现了 COM 对象的大部分接口,并使用辅助 C++ 类来实现不常用的接口,也许只在需要时动态创建这些辅助 C++ 类!(请注意,这又与 COM 聚合分开。)
最后一种情况特别有趣,因为它说明了单个 COM 对象可以映射到实现中的多个 C++ 对象。COM 不在乎,只要你遵循它的规则(特别是关于引用计数,QI 应该是关联的、自反的和传递的,并且所有 COM 对象都应该有一个 Canonical IUnknown。)
尽管在 C++ 中实现一个 COM 对象相当简单,但你不能假设你得到的任何 COM 对象实际上都是一个 C++ 类:它可以用 C、汇编程序实现,或者是一个动态生成的一段代码,它是一些 C# 代码的包装器。
请记住,RTTI 和 C++ 异常等 C++ 功能不是 COM 的一部分,因此您不能将它们用于任意 COM 对象 - 除非您当然知道它实际上是您自己的 C++ 类之一,在这种情况下,您是真正将对象用作 C++ 类,而不是 COM 对象。