• com学习3——包容


    com 有两种重要的重用模型—包容和聚合。重用是现在软件开发中很看重的一部分。重用可以大大提高开发效率。com的这两个重用模型非常的经典。包容:有两个com对象,A,B,用户只知道com对象B的存在,并不知道com对象A的存在,而com对象B知道对象A的存在,并且com对象B中的一部分功能com对象A中已经实现,com对象B有这些功能函数但是不去自己实现这部分功能,而是去调用对象A的这部分功能,当用户调用对象B的这部分功能的时候,对象B就去调用对象A的这些功能,并将结果返回给用户。聚合:则重用的更彻底,对象B根本就不去实现那部分功能,连函数都没有,用户调用对象B的那部分功能的时候,对象B直接将对象A的那部分接口暴露给用户,用户直接调用到了对象A。但是对象A受对象B的控制。
    包容:

     
    聚合:
     

    这次只介绍包容的实现,聚合下次再介绍。
     
    包容程序实现:
    com对象A:

     
    接口:ISomefunction.h
     
    #ifndef __ISomefunction_H__
    #define __ISomefunction_H__
     
     
    #include "Unknwn.h"
     
    extern "C" const GUID IID_ISomefunction2;
     
    class ISomefunction : public IUnknown
    {
    public:
    virtual void __stdcall Somefunction() = 0;
    };
     
    #endif
     
     
     
     对象A:A.h
    #ifndef __ISomefunction_H__
    #include "ISomefunction.h"
     
    //#endif
     
    class CA : public ISomefunction
    {
    public:
    CA();
    ~CA();
    public:
    virtual HRESULT __stdcall QueryInterface(const IID& iid,void **ppv);
    virtual ULONG __stdcall AddRef();
    virtual ULONG __stdcall Release();
     
    public:
    virtual void __stdcall Somefunction();
    private:
    int m_Ref;
    };
     
    #endif
     
    A.cpp
    #include "stdafx.h"
     
     
     
     
    #include <comutil.h>
    #include <stdio.h>
    #include "objbase.h"
    #include "olectl.h"
     
     
    #include "A.h"
    #include "Factory.h"
    #include "Registry.h"
     
     
    // {D45EAF90-D34A-4F89-98AD-2084765D711B}
    extern "C" const GUID CLSID_A =
    { 0xd45eaf90, 0xd34a, 0x4f89, { 0x98, 0xad, 0x20, 0x84, 0x76, 0x5d, 0x71, 0x1b } };
    extern "C" const GUID IID_ISomefunction2 =
    { 0xd45eaf92, 0xd34a, 0x4f89, { 0x98, 0xad, 0x20, 0x84, 0x76, 0x5d, 0x71, 0x1b } };
     
    ULONG g_LockNumber = 0;
    ULONG g_ANumber = 0;
    HANDLE g_hModule;
     
     
     
    BOOL APIENTRY DllMain( HMODULE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved
    )
    {
    g_hModule = hModule;
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
    break;
    }
    return TRUE;
    }
     
     
    extern "C" HRESULT __stdcall DllGetClassObject(const CLSID& clsid,const IID& iid,void **ppv)
    {
    if(clsid == CLSID_A)
    {
    //CAFactory *pFactory = new CAFactory;
    CAFactory *pFactory = new CAFactory;
    if(pFactory == NULL) return E_OUTOFMEMORY;
     
    HRESULT result = pFactory->QueryInterface(iid,ppv);
    return result;
    }
    else return CLASS_E_CLASSNOTAVAILABLE;
    }
     
    extern "C" HRESULT __stdcall DllCanUnloadNow(void)
    {
    if((g_ANumber == 0) && (g_LockNumber == 0)) return S_OK;
    else return S_FALSE;
    }
     
    extern "C" HRESULT __stdcall DllRegisterServer()
    {
    char szModule[1024];
    DWORD dwResult = ::GetModuleFileName((HMODULE)g_hModule,szModule,1024);
    if(dwResult == 0) return SELFREG_E_CLASS;
    return RegisterServer(CLSID_A,szModule,"A.Object","A Component",NULL);
    }
     
    extern "C" HRESULT __stdcall DllUnregisterServer()
    {
    return UnregisterServer(CLSID_A,"A.Object",NULL);
    }
     
    CA::CA()
    {
    m_Ref = 0;
    g_ANumber++;
    }
     
    CA::~CA()
    {
     
    }
     
    HRESULT CA::QueryInterface(const IID& iid,void **ppv)
    {
    if(iid == IID_IUnknown)
    {
    *ppv = (ISomefunction *)this;
    ((ISomefunction *)(*ppv)) ->AddRef();
    }
    else if(iid == IID_ISomefunction2)
    {
    *ppv = (ISomefunction *)this;
    ((ISomefunction *)(*ppv)) ->AddRef();
    }
    else
    {
    *ppv = NULL;
    return E_NOINTERFACE;
    }
    return S_OK;
    }
     
    ULONG CA::AddRef()
    {
    m_Ref++;
    return (ULONG)m_Ref;
    }
     
    ULONG CA::Release()
    {
    m_Ref--;
    if(m_Ref == 0)
    {
    g_ANumber--;
    delete this;
    return 0;
    }
    return (ULONG)m_Ref;
    }
     
    void CA::Somefunction()
    {
    printf("********************************\nCall function from A.\n********************************\n");
    }
     
    类厂:Factory.h
    #ifndef __Factory_H__
    #define __Factory_H__
     
    #include "Unknwn.h"
     
     
    class CAFactory : public IClassFactory
    {
    protected:
    ULONG m_Ref;
    public:
    CAFactory();
    ~CAFactory();
     
     
    virtual HRESULT __stdcall QueryInterface(const IID& iid,void **ppv);
    virtual ULONG __stdcall AddRef();
    virtual ULONG __stdcall Release();
    public:
    virtual HRESULT __stdcall CreateInstance(IUnknown *pUnknownOuter,const IID &iid,void **ppv);
    virtual HRESULT __stdcall LockServer(BOOL);
    };
     
    #endif
     
    Factory.cpp
    #include "stdafx.h"
    #include "Factory.h"
    #include "A.h"
     
    extern ULONG g_LockNumber;
    extern ULONG g_ANumber;
     
     
    CAFactory::CAFactory()
    {
    m_Ref = 0;
    }
     
    CAFactory::~CAFactory()
    {
     
    }
     
    HRESULT CAFactory::QueryInterface(const IID& iid,void **ppv)
    {
    if(iid == IID_IUnknown)
    {
    *ppv = (IUnknown *)this;
    ((IUnknown*)(*ppv))->AddRef();
    }
    else if(iid == IID_IClassFactory)
    {
    *ppv = (IClassFactory*)this;
    ((IClassFactory*)(*ppv))->AddRef();
    }
    else
    {
    *ppv = NULL;
    return E_NOINTERFACE;
    }
    return S_OK;
    }
     
    ULONG CAFactory::AddRef()
    {
    m_Ref++;
    return (ULONG)m_Ref;
    }
     
    ULONG CAFactory::Release()
    {
    m_Ref--;
    if(m_Ref == 0)
    {
    delete this;
    return 0;
    }
    return (ULONG)m_Ref;
    }
     
    HRESULT CAFactory::CreateInstance(IUnknown *pUnknownOuter,const IID& iid,void **ppv)
    {
    CA *pObj;
    HRESULT hr;
     
    *ppv = NULL;
    hr = E_OUTOFMEMORY;
    if(NULL != pUnknownOuter) return CLASS_E_NOAGGREGATION;
     
    pObj = new CA();
    if(pObj == NULL) return hr;
     
    hr = pObj->QueryInterface(iid,ppv);
    if(hr != S_OK)
    {
    g_ANumber--;
    delete pObj;
    }
     
    return hr;
    }
     
    HRESULT CAFactory::LockServer(BOOL bLock)
    {
    if(bLock) g_LockNumber++;
    else g_LockNumber--;
     
    return NOERROR;
    }
    Registry.h  Registry.cpp 和 .def文件跟之前的都是一样的,不再介绍。
     
    com对象B
     

     
    代码:
    接口:ISomefunction.h
    #ifndef __ISomefunction_H__
    #define __ISomefunction_H__
     
    #include "Unknwn.h"
     
    extern "C" const GUID IID_ISomefunction;
     
    class ISomefunction : public IUnknown
    {
    public:
    virtual void __stdcall Somefunction() = 0;
    };
     
    #endif
     
    IOtherfunction.h
    #ifndef __IOtherfunction_H__
    #define __IOtherfunction_H__
     
    #include "Unknwn.h"
     
    extern "C" const GUID IID_IOtherfunction;
     
    class IOtherfunction : public IUnknown
    {
    public:
    virtual void __stdcall Otherfunction() = 0;
    };
     
    #endif
     
    对象B:B.h
    #ifndef __ISomefunction_H__
    #include "ISomefunction.h"
     
    #endif
     
    #ifndef __IOtherfunction_H__
    #include "IOtherfunction.h"
     
    #endif
     
    class CB : public ISomefunction,public IOtherfunction
    {
    public:
    CB();
    ~CB();
    public:
    virtual HRESULT __stdcall QueryInterface(const IID& iid,void **ppv);
    virtual ULONG __stdcall AddRef();
    virtual ULONG __stdcall Release();
     
    public:
    virtual void __stdcall Somefunction();
    public:
    virtual void __stdcall Otherfunction();
    public:
    HRESULT Init();
    private:
    int m_Ref;
    ISomefunction *m_pSomefunction;
    };
     
    B.cpp
    #include "stdafx.h"
     
     
     
    #include <comutil.h>
    #include <stdio.h>
    #include "objbase.h"
    #include "olectl.h"
     
    #include "B.h"
    #include "Factory.h"
    #include "Registry.h"
     
     
    extern "C" const GUID CLSID_A =
    { 0xd45eaf90, 0xd34a, 0x4f89, { 0x98, 0xad, 0x20, 0x84, 0x76, 0x5d, 0x71, 0x1b } };
     
     
    extern "C" const GUID IID_ISomefunction2 =
    { 0xd45eaf92, 0xd34a, 0x4f89, { 0x98, 0xad, 0x20, 0x84, 0x76, 0x5d, 0x71, 0x1b } };
     
     
    extern "C" const GUID CLSID_B =
    { 0x67c51297, 0xc0d7, 0x4c58, { 0x85, 0x23, 0x6c, 0xa6, 0x1b, 0x2c, 0xdd, 0x6c } };
     
    extern "C" const GUID IID_ISomefunction =
    { 0x67c51298, 0xc0d7, 0x4c58, { 0x85, 0x23, 0x6c, 0xa6, 0x1b, 0x2c, 0xdd, 0x6c } };
     
    extern "C" const GUID IID_IOtherfunction =
    { 0x67c51299, 0xc0d7, 0x4c58, { 0x85, 0x23, 0x6c, 0xa6, 0x1b, 0x2c, 0xdd, 0x6c } };
     
    ULONG g_LockNumber = 0;
    ULONG g_BNumber = 0;
    HANDLE g_hModule;
     
     
    BOOL APIENTRY DllMain( HMODULE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved
    )
    {
    g_hModule = hModule;
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
    break;
    }
    return TRUE;
    }
     
     
     
    extern "C" HRESULT __stdcall DllGetClassObject(const CLSID& clsid,const IID& iid,void **ppv)
    {
    if(clsid == CLSID_B)
    {
    CBFactory *pFactory = new CBFactory;
    if(pFactory == NULL) return E_OUTOFMEMORY;
     
    HRESULT result = pFactory->QueryInterface(iid,ppv);
    return result;
    }
    else return CLASS_E_CLASSNOTAVAILABLE;
    }
     
    extern "C" HRESULT __stdcall DllCanUnloadNow(void)
    {
    if((g_BNumber == 0) && (g_LockNumber == 0)) return S_OK;
    else return S_FALSE;
    }
     
    extern "C" HRESULT __stdcall DllRegisterServer()
    {
    char szModule[1024];
    DWORD dwResult = ::GetModuleFileName((HMODULE) g_hModule,szModule,1024);
    if(dwResult == 0) return SELFREG_E_CLASS;
    return RegisterServer(CLSID_B,szModule,"B.Object","B Component",NULL);
    }
     
    extern "C" HRESULT __stdcall DllUnregisterServer()
    {
    return UnregisterServer(CLSID_B,"B.Object",NULL);
    }
     
     
    CB::CB()
    {
    m_pSomefunction = NULL;
    m_Ref = 0;
    g_BNumber++;
    }
     
    CB::~CB()
    {
    if(m_pSomefunction != NULL) m_pSomefunction->Release();
    }
     
    HRESULT CB::Init()
    {
    HRESULT result = ::CoCreateInstance(CLSID_A,NULL,CLSCTX_INPROC_SERVER,IID_ISomefunction2,(void **)&m_pSomefunction);
    if(FAILED(result)) return E_FAIL;
    else return S_OK;
    }
     
    void CB::Somefunction()
    {
    m_pSomefunction->Somefunction();
    }
     
    void CB::Otherfunction()
    {
    printf("*************************************\nCall function from B.\n*************************************\n");
    }
     
    HRESULT CB::QueryInterface(const IID& iid,void **ppv)
    {
    if(iid == IID_IUnknown)
    {
    *ppv = (ISomefunction *)this;
    ((ISomefunction *)(*ppv))->AddRef();
    }
    else if(iid == IID_ISomefunction)
    {
    *ppv = (ISomefunction *)this;
    ((ISomefunction *)(*ppv))->AddRef();
    }
    else if(iid == IID_IOtherfunction)
    {
    *ppv = (IOtherfunction *)this;
    ((IOtherfunction *)(*ppv))->AddRef();
    }
    else
    {
    *ppv = NULL;
    return E_NOINTERFACE;
    }
    return S_OK;
    }
     
     
    ULONG CB::AddRef()
    {
    m_Ref++;
    return (ULONG)m_Ref;
    }
     
    ULONG CB::Release()
    {
    m_Ref--;
    if(m_Ref == 0)
    {
    g_BNumber--;
    delete this;
    return 0;
    }
    return (ULONG)m_Ref;
    }
     
    类厂实现:Factory.h
    #ifndef __Factory_H__
    #define __Factory_H__
     
     
    #include "Unknwn.h"
     
    class CBFactory : public IClassFactory
    {
    protected:
    ULONG m_Ref;
    public:
    CBFactory();
    ~CBFactory();
    public:
    virtual HRESULT __stdcall QueryInterface(const IID& iid,void **ppv);
    virtual ULONG __stdcall AddRef();
    virtual ULONG __stdcall Release();
     
    public:
    virtual HRESULT __stdcall CreateInstance(IUnknown *pUnknownOuter,const IID &iid,void **ppv);
    virtual HRESULT __stdcall LockServer(BOOL);
    };
     
    #endif
     
    Factory.cpp
    #include "stdafx.h"
    #include "Factory.h"
    #include "B.h"
     
    extern ULONG g_LockNumber;
    extern ULONG g_BNumber;
     
     
    CBFactory::CBFactory()
    {
    m_Ref = 0;
    }
     
    CBFactory::~CBFactory()
    {
     
    }
     
    HRESULT CBFactory::QueryInterface(const IID& iid,void **ppv)
    {
    if(iid == IID_IUnknown)
    {
    *ppv = (IUnknown *)this;
    ((IUnknown *)(*ppv)) ->AddRef();
    }
    else if(iid == IID_IClassFactory)
    {
    *ppv = (IClassFactory *)this;
    ((IClassFactory *)(*ppv))->AddRef();
    }
    else
    {
    *ppv = NULL;
    return E_NOINTERFACE;
    }
    return S_OK;
    }
     
    ULONG CBFactory::AddRef()
    {
    m_Ref++;
    return (ULONG)m_Ref;
    }
     
    ULONG CBFactory::Release()
    {
    m_Ref--;
    if(m_Ref == 0)
    {
    delete this;
    return 0;
    }
    return (ULONG)m_Ref;
    }
     
    HRESULT CBFactory::CreateInstance(IUnknown *pUnknownOuter,const IID& iid,void **ppv)
    {
    CB *pObj;
    HRESULT hr;
     
    *ppv = NULL;
     
    hr = E_OUTOFMEMORY;
    if(pUnknownOuter != NULL) return CLASS_E_NOAGGREGATION;
     
    pObj = new CB();
     
    if(pObj == NULL) return hr;
    pObj->Init();
    hr = pObj->QueryInterface(iid,ppv);
    if(hr != S_OK)
    {
    g_BNumber--;
    delete pObj;
    }
    return hr;
    }
     
    HRESULT CBFactory::LockServer(BOOL bLock)
    {
    if(bLock) g_LockNumber++;
    else g_LockNumber--;
     
    return NOERROR;
    }
    解释:这里对象B中有个函数Init(),这个函数的作用是调用对象A的接口,将接口指针赋给
    m_pSomefunction。对象B中的ISomefunction接口的功能是通过m_pSomefunction指针去调用对象A中的函数。
     
    客户调用程序:
     

    代码:IOtherfunction.h
    #ifndef __IOtherfunction_H__
    #define __IOtherfunction_H__
     
    #include "Unknwn.h"
     
    extern "C" const GUID IID_IOtherfunction;
     
    class IOtherfunction : public IUnknown
    {
    public:
    virtual void __stdcall Otherfunction() = 0;
    };
     
    #endif
     
    ISomefunction.h
    #ifndef __ISomefunction_H__
    #define __ISomefunction_H__
     
    #include "Unknwn.h"
     
    extern "C" const GUID IID_ISomefunction;
     
    class ISomefunction : public IUnknown
    {
    public:
    virtual void __stdcall Somefunction() = 0;
    };
     
    #endif
     
    call.cpp
    #include "stdafx.h"
     
    #include <stdio.h>
    #include <comutil.h>
     
    #include "ISomefunction.h"
    #include "IOtherfunction.h"
     
     
    extern "C" const GUID CLSID_B =
    { 0x67c51297, 0xc0d7, 0x4c58, { 0x85, 0x23, 0x6c, 0xa6, 0x1b, 0x2c, 0xdd, 0x6c } };
     
    extern "C" const GUID IID_ISomefunction =
    { 0x67c51298, 0xc0d7, 0x4c58, { 0x85, 0x23, 0x6c, 0xa6, 0x1b, 0x2c, 0xdd, 0x6c } };
     
    extern "C" const GUID IID_IOtherfunction =
    { 0x67c51299, 0xc0d7, 0x4c58, { 0x85, 0x23, 0x6c, 0xa6, 0x1b, 0x2c, 0xdd, 0x6c } };
     
     
    /*extern "C" const GUID CLSID_B =
    {0x54bf6567, 0x1007, 0x11d1, {0xb0, 0xaa, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
     
    extern "C" const IID IID_Dictionary =
    { 0x54bf6568, 0x1007, 0x11d1,
    { 0xb0, 0xaa, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} } ;
     
    extern "C" const IID IID_SpellCheck =
    { 0x54bf6569, 0x1007, 0x11d1,
    { 0xb0, 0xaa, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} } ;*/
     
     
     
     
     
    int _tmain(int argc, _TCHAR* argv[])
    {
     
    IUnknown *pUnknown;
    ISomefunction *pSomefunction;
    IOtherfunction *pOtherfunction;
    HRESULT hResult;
     
    if(CoInitialize(NULL) != S_OK) printf("Initialize COM library failed!\n");
     
    hResult = CoCreateInstance(CLSID_B,NULL,CLSCTX_INPROC_SERVER,IID_IUnknown,(void **)&pUnknown);
     
    if(hResult != S_OK) printf("Create object failed!\n");
     
    hResult = pUnknown->QueryInterface(IID_ISomefunction,(void **)&pSomefunction);
    if(hResult != S_OK)
    {
    pUnknown->Release();
    printf("QueryInterface ISomefunction failed!\n");
    return 0;
    }
     
    pSomefunction->Somefunction();
     
    hResult = pSomefunction->QueryInterface(IID_IOtherfunction,(void **)&pOtherfunction);
    pOtherfunction->Release();
    if(hResult != S_OK)
    {
    pUnknown->Release();
    printf("QueryInterface IOtherfunction failed!\n");
    return 0;
    }
    pOtherfunction->Otherfunction();
     
    pOtherfunction->Release();
    CoUninitialize();
    int m;
    scanf("%d",&m);
    return 0;
    }
     
    运行结果:

  • 相关阅读:
    HTTP网页错误代码大全带解释
    记录一下手把手教您做电商网站
    C#中的Attribute
    C#中dynamic的正确用法
    【CSP】最大的矩形
    【CSP】字符与int
    C++数组初始化
    C++中输出字符到文本文档
    C++ 中时钟函数的使用
    各种函数的头文件
  • 原文地址:https://www.cnblogs.com/waterhsu/p/com_contain.html
Copyright © 2020-2023  润新知