c++ COM接口继承

Posted

技术标签:

【中文标题】c++ COM接口继承【英文标题】:c++ COM interface inheritance 【发布时间】:2017-07-23 10:50:16 【问题描述】:

我想知道在 COM 应用程序中通过继承实现代码重用的最佳方法是什么。

问题

据我了解,C++ 的虚拟继承模型不能在 COM 环境中使用,因为它不是语言独立的。

在纯 C++ 中,类层次结构可能如下所示:

interface IBase 
    virtual void BaseMethod() = 0;
;

interface IDerived : virtual IBase 
    virtual void DerivedMethod() = 0;
;

class CBase : public virtual IBase 
public:
    virtual void BaseMethod() override  /* Do something */ 
;

class CDerived : public IDerived, public CBase 
public:
    virtual void DerivedMethod() override  /* Do something */ 
;

这会产生以下层次结构:

IDerivedCBase 都实际上继承自 IBase

由于虚拟继承在 COM 中不可用,因此类层次结构更倾向于如下所示:

interface IBase 
    virtual void BaseMethod() = 0;
;

interface IDerived : IBase 
    virtual void DerivedMethod() = 0;
;

class CBase : public IBase 
public:
    virtual void BaseMethod() override  /* Do something */ 
;

class CDerived : public IDerived, public CBase 
public:
    virtual void DerivedMethod() override  /* Do something */ 
;

这会产生以下层次结构:

乍一看,IBase 的歧义似乎有问题。这可以通过实现IUnknown::QueryInterface 方法轻松解决。

真正的问题是,CDerived如何从CBase继承IBase的实现方法,即CBase::BaseMethod

在虚拟继承的情况下,CBase::BaseMethod 可以通过显性继承,但如果没有虚拟继承,这不会发生:在CDerived 中,定义了方法CBase::IBase::BaseMethod,但没有定义方法IDerived::IBase::BaseMethod,导致在 CBase 类中仍然是抽象的,因此不适合实例化。

解决此问题的一种方法是再次覆盖 CDerived 中的方法 BaseMethod

class CDerived : public IDerived, public CBase 
public:
    virtual void BaseMethod() override  CBase::BaseMethod(); 
    virtual void DerivedMethod() override  /* Do something */ 
;

这对性能有影响吗?有没有更好的方法来实现我想要的? CDerived 中函数的重复覆盖不是破坏了继承的整个想法吗?

【问题讨论】:

这个问题是基于一个非常错误的假设。 COM 通过只看到接口的客户端代码来实现语言独立性。该实现是完全不可见的。这允许你做任何你想做的事情来实现接口,实际上使用非虚拟多重继承是样板方法。对于所有已实现的接口,只有一个函数来实现 QueryInterface、AddRef、Release 正是您想要的。任何 COM 基础教程都会向您展示如何做到这一点。 【参考方案1】:

ATL 广泛使用如下技术:

template <typename Itf>
class IBaseImpl : public Itf 
public:
  void BaseMethod() override;
;

class CBase : public IBaseImpl<IBase> ;

class CDerived : public IBaseImpl<IDerived> 
public:
  void DerivedMethod() override;
;

现在你有了直线继承:IBase IDerived IBaseImpl<IDerived> CDerived。

【讨论】:

以上是关于c++ COM接口继承的主要内容,如果未能解决你的问题,请参考以下文章

使用 COM 互操作从非托管 C++ 访问 c# 属性

在 Windows 环境中从 C 或 C++ 访问 COM 接口

如何使用 C++ 封装的 COM 接口部署 C# 库?

在 C++ 中使用多继承声明接口并实现接口

使用 COM 接口 C# 从 c++ 访问会产生错误

C++ 继承、接口