模板化类的接口

时间:2009-08-10 15:25:12

标签: c++ inheritance templates

我正在开发一个插件框架,它支持基础插件类CPlugin : IPlugin的多个变体。我使用boost::shared_ptr<IPlugin>来插件的所有引用,除非子系统需要插件类型的特定接口。我还需要能够将插件克隆到另一个seprate对象中。这必须返回PluginPtr。这就是CPlugin是模板而不是直接类的原因。 CPlugin::Clone()是使用模板参数的地方。以下是我正在使用的类定义:

IPlugin.h

#include "PluginMgr.h"
class IPlugin;
typedef boost::shared_ptr<IPlugin> PluginPtr;

class IPlugin
{
public:
  virtual PluginPtr Clone() =0;
  virtual TYPE Type() const =0;
  virtual CStdString Uuid() const =0;
  virtual CStdString Parent() const =0;
  virtual CStdString Name() const =0;
  virtual bool Disabled() const =0;

private:
  friend class CPluginMgr;
  virtual void Enable() =0;
  virtual void Disable() =0;
};

CPlugin.h

#include "IPlugin.h"
template<typename Derived>
class CPlugin : public IPlugin
{
public:
  CPlugin(const PluginProps &props);
  CPlugin(const CPlugin&);
  virtual ~CPlugin();
  PluginPtr Clone();

  TYPE Type() const { return m_type; }
  CStdString Uuid() const { return m_uuid; }
  CStdString Parent() const { return m_guid_parent; }
  CStdString Name() const { return m_strName; }
  bool Disabled() const { return m_disabled; }

private:
  void Enable() { m_disabled = false; }
  void Disable() { m_disabled = true; }

  TYPE        m_type;
  CStdString  m_uuid;
  CStdString  m_uuid_parent;
  bool        m_disabled;
};

template<typename Derived>
PluginPtr CPlugin<Derived>::Clone()
{
  PluginPtr plugin(new Derived(dynamic_cast<Derived&>(*this)));
  return plugin;
}

示例具体类CAudioDSP.h

#include "Plugin.h"
class CAudioDSP : CPlugin<CAudioDSP>
{
  CAudioDSP(const PluginProps &props);
  bool DoSomethingTypeSpecific();
  <..snip..>
};

我的问题(最后)是CPluginMgr需要更新具体类的m_disabled,但是当它传递PluginPtr时它无法确定类型并且表现不同根据模板参数。我无法看到如何避免将::Enable()::Disable()声明为IPlugin的私有成员,但这立即意味着应用程序的每个部分现在都需要知道{{1} } class,因为它在标题中被声明为朋友。随之而来的是循环依赖。我看到另一个选项,将启用/禁用功能声明为CPlugin的私有成员,而是使用CPluginMgr

boost::dynamic_pointer_cast<CVariantName>

然而,这导致许多重复代码,其中包含基本void CPluginMgr::EnablePlugin(PluginPtr plugin) { if(plugin->Type == PLUGIN_DSPAUDIO) { boost::shared_ptr<CAudioDSP> dsp = boost::dynamic_pointer_cast<CAudioDSP>(plugin); dsp->Enable(); } } 模板的多个变体。如果有人有更好的建议,请分享!

2 个答案:

答案 0 :(得分:2)

您可以轻松地写下:

class CPluginMgr;

class IPlugIn ..
{
    friend CPluginMgr;
    ...
};

朋友只需要预定义。

答案 1 :(得分:0)

我认为您在尝试在clone方法中返回shared_ptr时遇到了麻烦。为什么不使用 协变返回类型 ?你正在做的是一个常见的习语,叫做 Virtual Constructor

class IPlugin
{
public:
    virtual IPlugin* clone() = 0;
    // ...
}

class CPluginMgr;

class CPlugin : public IPlugin
{
public:
    virtual CPlugin* clone() = 0;
    friend CPluginMgr; // as @Christopher pointed out
    void Enable(bool enable) { m_disabled = !enable; }
    // ...
}

class CAudioDSP : public CPlugin 
{
public:
    virtual CAudioDSP* clone();
    // ...
}

CAudioDSP* CAudioDSP::clone()
{
    return new CAudioDSP(*this); // assume copy constructors are properly implemented
}

返回shared_ptr可能会导致出错(因为早期破坏了临时对象),我认为这通常不是一个好主意。