描述:
up and up again
解决方案1:
抱歉,前面说错了,CComCreator是用来创建类厂实例的
AtlModuleGetClassObject函数通过调用CComCreator的CreateInstance方法(静态函数)得到类厂指针并换存在全局结构数组_ATL_OBJMAP_ENTRY[]中以供后用
感谢楼上的说明
CComCreator是ALT中的一个模板类,用来为不同的类创建实例,类厂不可能为服务器中的每一个类实现对应的CreateInstance函数(除非你不怕麻烦),所以类厂通过使用CComCreator来统一的为每个类创建实例。
解决方案3:抱歉,上面有个地方错了——“(其中class就被那个类的类名所替换,在创建类厂时这个class就是CComCreator)”,应为“(其中class就被那个类的类名所替换,在创建类厂时这个class就是要被类厂所创建的对象的类)”
解决方案4: CComCreator只不过是个函数类而已,即它存在的意义就是提供那个函数(不生成实例),而以至于可以使用C++的模板技术很容易地在编译时刻变换代码(即不损失运行时刻的性能)。
下面先说明ATL是怎么创建类厂的(下面的函数都是从ATL源码中copy的,楼主可自己查看其源码),以此说明为什么吃饱了撑了要在中间夹个CComCreator。
在AtlModuleGetClassObject中通过查找由宏BEGIN_OBJECT_MAP、END_OBJECT_MAP及OBJECT_ENTRY创建的一个列表,来获得一个函数指针,此函数指针为某个类的静态成员函数——class::_ClassFactoryCreatorClass::CreateInstance(其中class就被那个类的类名所替换,在创建类厂时这个class就是CComCreator)。
因此AtlModuleGetClassObject通过调用CComCreator::CreateInstance来创建类厂的。之所以使用调用函数指针的形式而不是简单的用个new在那里来创建类厂是因为前者可提供更多的灵活性,前者可以实现在栈上分配类厂,在一个用户(指程序员)自定义的缓冲区中分配用户,甚至可以实现一直只使用一个类厂,而不会每次分配多个类厂(虽然ATL不是使用这种方式实现单件设计模式的)。并且前者可以创建各种类厂(不同的类实现的类厂),如果使用后者就只能在堆上分配类厂,而且只能创建固定形式的类厂(new后面的类名被硬编码进去了),不过可以使用模板在编译时刻改变,但这样AtlModuleGetClassObject就变成了一个模板函数,对于不同的类厂,必须调用不同的AtlModuleGetClassObject,这样编码复杂了,而前者由于使用函数指针,所以编码不会复杂(不同的类厂只是函数指针的值不同,这可以用个数组记录不同类厂的创建函数的地址,仅影响了内存的使用及些许运行效率)。
那么为什么要提供类CComCreator的静态成员函数来实现函数,不直接写个模板函数?原因是可以很容易的使用typedef将一个类和另一个类相关联,但是无法让一个函数(即使是模板函数,相关的类也只是那个当前的实现类,对于类厂的创建就是类厂,但不能和任意的类相关联,在此即类厂要创建的对象的类)和一个类相关联。如下:
class CA
{
typedef ABC _CreateClass;
};
此时代码只要这样写:
CA::_CreateClass::CreateInstance( ... );
只要CA变化(变成CB),上面的代码不变,就能自动地调用CB相关联的_CreateClass,而对于CA的变化,可以简单的使用一个宏来进行(这正是宏OBJECT_ENTRY所做的工作之一)。
com为了不让客户直接创建com组件,所以出现了ClassFactory(类厂)负责创建,类厂有两个成员函数,第一是CreateInstance,第二是LockServer。
CoCreateInstance实际上并没有直接创建com组件,而是创建了一个被称为类厂的组件。