2009-08-10 8 views
1

私はプラグインフレームワークで作業しています。これは、ベースプラグインクラスの複数のバリエーションをサポートしています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..> 
}; 

私の問題(最後に)は、PluginPtrが渡されるので、具体的なクラスのm_disabledを更新する必要があるということです(PluginPtr)。それは型を決定し、テンプレートのパラメータに従って異なる動作をする方法がありません。 ::Enable()::Disable()をプライベートメンバーとしてIPluginの代わりに宣言しないようにする方法はわかりませんが、これは即座にアプリケーションの各セクションがヘッダーのフレンドとして宣言されたCPluginMgrクラスについて知る必要があることを意味します。円の依存関係が続いている。別のオプションが表示され、CPluginのプライベートメンバーとしてEnable/Disable機能を宣言し、代わりに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(); 
    } 
} 

しかし、これはベースCPluginテンプレートの多くの複数の亜種と重複したコードの多くにつながります。誰かより良い提案があれば、それを共有してください!

+0

なぜ 'CPlugin'はテンプレート化されていますか?クラスは非テンプレートでもテンプレート化されたメンバ関数(この場合はクローン)を持つことができます。 –

+0

たぶん私は何かを手に入れているかもしれませんが、プラグインのタイプが 'PluginPtr'の場合、' plugin-> Enable(); 'を実行することはできません。それはインターフェイスのポイントのようなものです... –

+0

CPluginMgr以外のクラスではプラグインを無効/有効にすることはできません – AlasdairC

答えて

2

あなたは簡単に書くことができます。

class CPluginMgr; 

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

のみ事前定義は、友人のために必要とされています。

+0

私は 'それはとてもシンプルだと信じていますが、それはまだあります:) Thanks Christopher! – AlasdairC

+0

クリストファーの解決策を受け入れることを忘れないでください... – neuro

+0

err私は、そのことについて申し訳ありません – AlasdairC

0

私はあなたの問題がクローンメソッドで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 
} 
(tempararyオブジェクトの早期破壊として)エラーを作るためにあなたを導くことのshared_ptrを返す

とは、通常は良いアイデアではありません。

関連する問題