我正在开发一个插件框架,它支持基础插件类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();
}
}
模板的多个变体。如果有人有更好的建议,请分享!
答案 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可能会导致出错(因为早期破坏了临时对象),我认为这通常不是一个好主意。