ATL Internals 2ed复习.chapter 6.interface map tricks

来源:互联网 发布:上海知楚 编辑:程序博客网 时间:2024/06/06 09:12

Handling Name Conflicts

接口定义有时会遇到命名冲突,例如:

interface ICowboy : IUnknown {    HRESULT Draw();};interface IArtist : IUnknown {   HRESULT Draw();};


 

// Ace Powell was a cowboy/artist who lived in the western US// from 1912 to his death in 1978. I'd like to thank Tim Ewald// for this fabulous example, which I have used to death// for years.class CAcePowell :    public CComObjectRootEx<CComSingleThreadModel>,    public ICowboy,    public IArtist{public:BEGIN_COM_MAP(CAcePowell)  COM_INTERFACE_ENTRY(ICowboy)  COM_INTERFACE_ENTRY(IArtist)END_COM_MAP()...  STDMETHODIMP Draw() { /* Act as a cowboy or an artist? */ }};

上述代码中,Draw()不同的接口表现完全不同

微软解决方案

class CAcePowell :    public CComObjectRootEx<CComSingleThreadModel>,    public ICowboy,    public IArtist {public:BEGIN_COM_MAP(CAcePowell)  COM_INTERFACE_ENTRY(ICowboy)  COM_INTERFACE_ENTRY(IArtist)END_COM_MAP()...  STDMETHODIMP IArtist::Draw() {    /* Draw like an artist */    return S_OK;  }  STDMETHODIMP ICowboy::Draw() {    /* Draw like a cowboy */    return S_OK;  }};


上述代码只能用在头文件中,而且并非标准cpp,只能用在微软编译器

forwarding shims解决方案

struct _IArtist : public IArtist {  STDMETHODIMP Draw() { return ArtistDraw(); }  STDMETHOD(ArtistDraw)() =0;};struct _ICowboy : public ICowboy {  STDMETHODIMP Draw() { return CowboyDraw(); }  STDMETHOD(CowboyDraw)() =0;};


_IArtist和_ICowboy被称为shim class

class CAcePowell :    public CComObjectRootEx<CComSingleThreadModel>,    public _ICowboy,    public _IArtist {public:BEGIN_COM_MAP(CAcePowell)  COM_INTERFACE_ENTRY(ICowboy)  COM_INTERFACE_ENTRY(IArtist)END_COM_MAP()...  STDMETHODIMP ArtistDraw();  STDMETHODIMP CowboyDraw();};

上述代码使用额外的vtable来解决问题,如果不想要这个负担,例子:

template <typename Deriving>struct ATL_NO_VTABLE _IArtist : public IArtist {  STDMETHODIMP Draw() {    return static_cast<Deriving*>(this)->ArtistDraw();  }};template <typename Deriving>struct ATL_NO_VTABLE _ICowboy : public ICowboy {  STDMETHODIMP Draw() {    return static_cast<Deriving*>(this)->CowboyDraw();  }};class ATL_NO_VTABLE CAcePowell :    public CComObjectRootEx<CComSingleThreadModel>,    public _ICowboy<CAcePowell>,    public _IArtist<CAcePowell> {public:BEGIN_COM_MAP(CAcePowell)  COM_INTERFACE_ENTRY(ICowboy)  COM_INTERFACE_ENTRY(IArtist)END_COM_MAP()...  HRESULT ArtistDraw();  HRESULT CowboyDraw();};

下面的代码是错误的:

template <typename Deriving>struct ATL_NO_VTABLE _ICowboy : public ICowboy {  STDMETHODIMP Draw() {    return static_cast<Deriving*>(this)->CowboyDraw();  }};class ATL_NO_VTABLE CAcePowell :    public CComObjectRootEx<CComSingleThreadModel>,    public _ICowboy<CAcePowell>,    public IArtist {public:BEGIN_COM_MAP(CAcePowell)  COM_INTERFACE_ENTRY(ICowboy)  COM_INTERFACE_ENTRY(IArtist)END_COM_MAP()...  HRESULT Draw();       // Use for both IArtist::Draw and                        // ICowboy::Draw  HRESULT CowboyDraw(); // Never called!};


Interface Coloring

利用CPP的漏洞,统计各个接口的调用,在ATL7中已经为_ALT_DEBUG_INTERFACES所实现