COM学习笔记

来源:互联网 发布:注册身份证号码软件 编辑:程序博客网 时间:2024/05/21 09:24

有人说COM是一种更好的C++,这句话也就表明了COM的确与C++是有关系的。
(因为说这话的人实在太重要了,所以这句话才能成为我后面观点的一个基石,或重要根据)
我认为COM的这种编程方式就是把C++(或者说面象对象)中默认的东西,给说明了,强制了。
我认为COM应该是面象对象编程的一个子集,是面象对象编程的其中一种方法。

关于最近在书上看的那那句话:
一个系统是一系列组件的集合;每个组件提供了一个接口集;而每一个接口则包含一系列函数;
改用C++或面象对象的方式说:
一个系统是一系列对象的集合;每个对象提供了一个接口集;而每一个接口则包含一系列函数;
再改回原来我理解的方式:
一个系统是一系列对象的集合;每个对象提供了一组方法(函数)。

其中的差别就是:COM强调了接口,这就是关键所在,COM只不过是面象对象中强调了接口。然后使得程序员们必须面对它。


随便说说我原来理解的C++,或者说面象对象的方法的描述:
一个系统是一个虚拟世界,里面包含了各种对象,对象本身与及它们之间的关系组成了这个虚拟世界。
当这个虚拟世界完成的时候,问题就解决了。


举个列子:
现在有一群狗,狗都会叫,其中有大狗,小狗等等的狗。我现在收集一下这些狗叫的信息。
#define interface struct
interface Dog
{ virtual int Wanwan() = 0; }

class BigDog : public Dog
{
    virtual int Wanwan() { return 10; }
}

class SmallDog : public Dog
{
    virtual int Wanwan() { return 1; }
}
.....

void GetInfo(Dog *pDog) {....}

如果是原来的方式就会这样:
BigDog *dog1 = new BigDog;
SmallDog *dog2  = new SmallDog;
GetInfo (dog1);          //ok
GetInfo (dog2);          //ok

而如果是COM的话:
IUnknow *dog1 = CoInstance(CLSID_BIGDOG);
IUnknow *dog2  = CoInstance(CLSID_SMALLDOG);
GetInfo (dog1->QueryInterface(GUID_DOG));    
GetInfo (dog2->QueryInterface(GUID_DOG));

另外也可能是这样:
IUnknow *dog1 = CoInstance(CLSID_BIGDOG);                             //原来应该是
IUnknow *dog2  = CoInstance(CLSID_SMALLDOG);
BigDog *bigdog = dog1->QueryInterface(GUID_BIGDOG);
SmallDog *smalldog = dog2->QueryInterface(GUID_SMALLDOG);

GetInfo (bigdog->QueryInterface(GUID_DOG));     //看到没,就算BIGDOG里面有dog的方法,最好还是要用这样方式!
GetInfo (smalldog->QueryInterface(GUID_DOG)); //强制面象接口!

 

思考方式的转变:
C++:
 之所以大狗能用狗的方法操作是因为大狗是一种狗。
COM:
 之所以大狗能用狗的方法操作是因为大狗提供了狗的介面。

面象对象中多态的是一种关系在COM中变成了有什么接口的关系。

其它的转变:
在面象对象中只能从子类到父类的转变,反之则要用RTTI进行转换。
比如要从狗转换为大狗则可能要用 BIGDOG *bogdog = dynamic_cast <BigDog>(dog);
从语意上来说是对的,因为我们从这句话我们并不知道Dog这原来是不是BIGDOG,所以要强制转换(查表)。

但是COM的这种行为相对就一致一些,因为他的语意是:我有没有这个接口,所以并不需要特殊的方法
把接口转换过去。另外,COM的这种方式把查询工作显式的交给了程序员,所以程序员可以考虑是否使用自已的方法来实现。
(C++中的dynamic_cast只有在RTTI开启的时候才有效,所以很可能程序员会用static_cast进行转换,但这种方式并不保正安全性)

总结:
COM强制使用接口,把面向对象中,对象的观念弱化了,接口的观念强化了。
(语意:我之所以能这么做,并不是因为这类对象能这么做,而是它提供了这么做的方法(接口))

原创粉丝点击