我将尽可能简单地描述问题。
好的,这就是问题所在;
让我们假设我们有一个带有3个构造函数的com组件类,其中构造函数至少需要两个参数。我们已经知道我们通过QueryInterface实例化组件而不是调用类的构造函数,因此似乎com客户端不可能设置构造函数的参数。
好的,这就是问题;
允许com客户端实例化一个需要至少初始化两个参数的com组件的最佳实用方法是什么?
答案 0 :(得分:4)
如果它是一个纯COM组件,处理它的标准方法是实现Initialize(foo,bar)方法而不是单独的构造,然后在COM实例化后立即调用它。如果对象没有合理的默认状态,那么可以使它成为COM对象中的成员变量(指针)。从该COM对象中,您将拥有Initialize(foo,bar)函数。在每个初始化函数中,将实例化对象的正确版本。 COM包装器中的每个传递函数都需要检查您的对象是否为NULL并返回适当的HRESULT(如果是)。
答案 1 :(得分:4)
您的QueryInterface
调用可以返回工厂,而不是直接返回对象实例。例如,而不是:
// implements IMyClass1 interface
return new MyClass1();
你会这样做:
// pointer to member that implements IMyClassFactory interface
return &m_myClassFactory;
// this could also be a static class instead of an object instance
IMyClassFactory
接口将有一个create
方法,它接受构造函数参数并返回最终的MyClass1
实例。
答案 2 :(得分:3)
一种选择是使用工厂对象;创建函数将全部放在(无状态)工厂对象上(当然是在不同的接口上),并传回真实对象的初始化实例。
答案 3 :(得分:1)
当我编写COM服务器时,我通常不允许CoCreateInstance
实例化我的组件。相反,我从我的DLL中导出一些裸函数(这些可以在IDL中以及模块中描述),它接受构造函数参数并在输出参数中返回一个指向新创建对象的接口指针。
答案 4 :(得分:0)
我喜欢Ates Goral's回答和Steve's,并对两者都赞不绝口。通常我会把它留在那,但我觉得这次我必须详细说明。
“最佳”,“正确”,“最纯粹”,“规范”的做法无疑是Ates所描述的工厂模式。如果你想创建一个干净的API,那就是道路,放下。
但是......我们大多数人并不忙于为商业产品创建公共API。对于使用非公共API的小型内部项目,我只想完成工作。必须实现一个额外的对象,所以我可以暴露一个工厂方法听起来相当矫枉过正(特别是在C ++中)。在大多数实际情况中,我只想采用史蒂夫描述的Initialize(foo, bar)
方法。然后,我会确保每个非平凡的方法检查对象是否已初始化,如果没有则返回失败HRESULT。