Inside Com学习笔记(一)

来源:互联网 发布:swing java 教程 编辑:程序博客网 时间:2024/05/17 04:21

以前总是接触C/C++的一些皮毛的东西,或者说是基础的东西。一直都没有完成从中级程序员向高级程序员的过渡。现在越来越发现新的知识需求量很大。准备好好研究下COM、STL、Templete。好好学习天天向上。

(*^__^*) 嘻嘻……   

 

****************************************************学习笔记一***************************************************

使用组件的种种优点直接来源于可以动态地将他们插入或卸出应用程序。
为了实现这种功能,组件必须满足:第一,组件必须动态链接。第二,他们必须隐藏或封装其内部实现细节。信息隐藏是动态链接的一个必要条件。

动态链接:最终目标是使用户在应用程序的运行过程中能够将组件替换掉。

如果一个应用程序或组件,如果它使用了其他组件。那么我们称之为一个客户,客户通过接口同其他组件进行链接。如果某个组件发生了变化而其接口没有发生任何变化,那么它的客户不需要进行任何修改。那么也不需要进行重新编译。因此为了充分发挥动态链接的功能,组件及客户都应尽量不要改变其接口。

这种将客户同组件实现相隔离开来的要求对于组件有了一些限制
1.组件必须将其实现所有的编程语言封装起来。任一客户都能使用任一组件,不论它们是什么编程语言实现的;
2.组件必须以二进制的形式发布;
3.组件必须可以在不妨碍已有用户的情况下被升级;
4.组件在网络上的为幌子必须可以被透明地重新分配。组件及使用它的程序应能够在同一进程、不同进程中或不同的机器上运行。客户对远程组件的处理方式与本地组件的处理方式是一样的;

COM规范是一套为组件价格设置的标准稳定。

COM组件
COM组件是以WIN32动态链接库或者可执行文件的形式发布的可执行代码组成的。
COM组件是动态链接的,COM使用DLL将组件动态链接起来。但是DLL并不满足对于组件架构的需求,为满足这些需求,DLL还必须进行封装。


COM
COM不是一种语言。COM也不等同与DLL。实际上COM是使用了DLL来给组件提供动态链接的能力。COM不是像WIN32 API那样的一个函数集。也不是类似于MFC的类库。COM给开发人员提供一种开发与语言无关的组件类库的方法。

COM库
COM库提供的是对所有客户及组件都非常有用的组件管理服务。

COM方法
一种编写程序的方法。组织软件的方法。不必依赖WINDOWS OS。

接口

接口提供了两个不同对象间的一种链接。实际上计算机程序是通过一组函数而链接起来的。DLL接口就是它所输出的函数;C++接口就是该类的一个成员函数集。
COM接口涉及到一组由组件实现并提供给客户使用的函数。
对COM来说,接口是一个包含一个函数指针数组的内存结构。每一个数组元素包含的是一个由组件所实现的函数的地址。对COM而言,接口就是此内存地址。


常见接口定义的由来
我们知道常见的接口定义为如下:

interface IX
{
 
virtual void Fx1()=0;
 
virtual void FX2()=0;
}

 

实际上可以写为:

class IX //interface
{
 
public:
 
virtual void Fx1()=0;
 
virtual void Fx2()=0;
}
//纯虚基类

 

class IY // interface
{
 
public:
 
virtual void Fy1()=0;
 
virtual void Fy2()=0;
}
;//纯虚基类


class CA: public IX, public IY // components
{
 
public:
 
virtual void Fx1(){cout << "FX1"<<endl;}
 
virtual void Fx2(){cout << "FX2"<<endl;}
 
virtual void Fy1(){cout << "Fy1"<<endl;}
 
virtual void Fy2(){cout << "Fy2"<<endl;}
}


在WIN32 SDK中OBJBASE.H中定义了:

#define interface struct


因为struct成员将自动具有公共的属性,因此不需要在定义中加上PUBLIC关键字。

由于COM是与语言无关的,对于什么是接口,它有一个二进制的标准。表示一个接口的内存块必须具有一定的结构。当使用纯抽象基类时候,C++编译器可以将其生成具有这种结构的内存块。

一个完整的程序用例

输出为:

client:Create an instance of the component.
client:Use the IX 
interface
CA::Fx1
CA::Fx2
client:Use the IY 
interface
CA::Fy1
CA::Fy2
client:Delete the componet

 

在这个例子实际上存在这违背接口通信的地方:
1.客户和组件的通信是通过一个指向类CA的指针而不是通过一个指向接口的指针完成的;那么在这里客户需要类CA的声明;
2.在客户程序中使用了new和delete,这些操作控制组件的声明期,不属于任何接口的一部分,是C++才有的特定操作。 

 

//
// Iface.cpp
// To compile, use: cl Iface.cpp
//
#include <iostream.h>
#include 
<objbase.h>   // Define interface.

void trace(const char* pMsg) {cout << pMsg << endl ;}

// Abstract interfaces
interface IX
{
 
virtual void __stdcall Fx1() = 0 ;
 
virtual void __stdcall Fx2() = 0 ;
}
 ;

interface IY
{
 
virtual void __stdcall Fy1() = 0 ;
 
virtual void __stdcall Fy2() = 0 ;
}
 ;

// Interface implementation
class CA : public IX, 
           
public IY
{
public:

 
// Implement interface IX.
 virtual void __stdcall Fx1() {cout << "CA::Fx1" << endl ;}
 
virtual void __stdcall Fx2() {cout << "CA::Fx2" << endl ;}

 
// Implement interface IY.
 virtual void __stdcall Fy1() {cout << "CA::Fy1" << endl ;}
 
virtual void __stdcall Fy2() {cout << "CA::Fy2" << endl ;}

}
 ;


// Client
int main()
{
 trace(
"Client: Create an instance of the component.") ;
 CA
* pA = new CA ;

 
// Get an IX pointer.
 IX* pIX = pA ;

 trace(
"Client: Use the IX interface.") ;
 pIX
->Fx1() ;
 pIX
->Fx2() ;

 
// Get an IY pointer.
 IY* pIY = pA ;

 trace(
"Client: Use the IY interface.") ;
 pIY
->Fy1() ;
 pIY
->Fy2() ;

 trace(
"Client: Delete the component.") ;
 delete pA ;

 
return 0 ;
}