2010-11-03 85 views
3

我有一個類 - PluginLoader,它處理另一個類Plugin來執行其功能。 Plugin類使用PluginLoader中的某些功能。這兩個類都是抽象基類,所以我不能聲明Plugin作爲PluginLoader的朋友。我不希望Plugin功能在PluginLoader的公共界面中可用,因爲它們與PluginLoader的用戶無關。這是個常見的問題嗎?如何解決它?如何將一個公共接口的子集公開到一個類

編輯:代碼示例

class PluginLoader 
{ 
    public: 
     virtual void RegisterPlugin(Plugin*) = 0; 
     virtual void RegisterFunction(int, Plugin*) = 0; 
}; 

class Plugin 
{ 
    public: 
     virtual void Load(PluginLoader&) = 0; 
} 

class PlugImp : public Plugin 
{ 
    public: 
     virtual void Load(PluginLoader& oPLoader) 
     { 
     //Do stuff 
     oPLoader.RegisterPlugin(this); 
     } 
} 

雖然我想RegisterPlugin可用的Plugin類,沒有一點離開它可見PluginLoader類的其他用戶。

EDIT2:@chubsdad

#include <iostream> 

using namespace std; 

class PluginLoader; 
class Plugin 
{ 
    public: 
     virtual void Register(PluginLoader&) = 0; 
     virtual ~Plugin() = 0; 
}; 

class PluginLoader 
{ 
    public: 
     virtual void Load() = 0; 

     virtual ~PluginLoader() = 0; 

    private: 
     friend class Plugin; 
     virtual void RegisterPlugin(Plugin&) = 0; 
}; 

class PluginImp : public Plugin 
{ 
    public: 
     void Register(PluginLoader& oPLoader) 
     { 
      oPLoader.RegisterPlugin(*this); 
     } 
}; 

class PluginLoaderImp : public PluginLoader 
{ 
    public: 
     void Load() 
     { 
      Plugin* pP = new PluginImp(); 
      pP->Register(*this); 
     } 

    private: 
     void RegisterPlugin(Plugin& oP) 
     { 
      cout << "PluginLoaderImp::RegisterPlugin" << endl; 
     } 
}; 

int main() 
{ 
    PluginLoader* pPLoader = new PluginLoaderImp(); 
    pPLoader->Load(); 
} 

這將引發編譯器錯誤:

main.cpp: In member function ‘virtual void PluginImp::Register(PluginLoader&)’: 
main.cpp:22: error: ‘virtual void PluginLoader::RegisterPlugin(Plugin&)’ is private 
main.cpp:30: error: within this context 

這給我們帶來了一圈。還是有什麼我失蹤?

回答

1

但在插件和加載器之間提供單獨的通信通道,您可以簡單地創建另一個接口,也許它將具有公共方法Register...

在您的插件加載器中從它私下繼承,並將Register...方法作爲加載器中的私有函數實現。沒有人可以通過插件類訪問Register...方法,他們需要通過PluginRegistra接口訪問它們,只有加載器可以將其自身轉換爲該類型,因爲繼承是私有的。

現在只需將加載器以完全相同的方式傳遞給插件;該插件的Load()方法現在需要一個PluginRegistra接口。沒有友誼需要。由於私有繼承,只有插件加載器可以作爲PluginRegistra的實例。

一個例子,根據要求,請注意這沒有看到一個編譯器。

class PluginLoader 
{ 
    public: 
     virtual void LoadPlugin(Plugin*) = 0; 
}; 

class PluginRegistra 
{ 
    public: 
     virtual void RegisterPlugin(Plugin*) = 0; 
     virtual void RegisterFunction(int, Plugin*) = 0; 
}; 

class Plugin 
{ 
    public: 
     virtual void Load(PluginRegistra&) = 0; 
} 

class PlugImp : public Plugin 
{ 
    public: 
     virtual void Load(PluginRegistra& oPLoader) 
     { 
     //Do stuff 
     oPLoader.RegisterPlugin(this); 
     } 
} 

class LoaderImp : public PluginLoader : private PluginRegistra 
{ 
    public : 
     virtual void LoadPlugin(Plugin* plugin) 
     { 
     plugin.Load(this); 
     } 

    private : 

     virtual void RegisterPlugin(Plugin*) 
     { 
     } 

     virtual void RegisterFunction(int, Plugin*) 
     { 
     } 
} 
+0

漂亮做作:)。你能提供一個代碼示例嗎? – nakiya 2010-11-03 09:14:26

+0

任何人都可以向我詳細解釋這一點嗎? :(我試圖做它看起來像在要求我做什麼沒有結果 – nakiya 2010-11-03 09:41:16

+0

它根本沒有作出任何設計從邏輯上說,你有兩個單獨的接口到你的插件加載器,它暴露在插件允許自己的接口註冊以及它暴露給世界的界面,所以這樣實現它。 – 2010-11-03 09:55:26

1

將函數從PluginLoader中移出。

編輯:考慮到問題的模糊性,我應該提及您可以通過傳遞一個提供函數的對象來傳遞一堆相關函數作爲參數。你可以從提供函數的類繼承。等等。

乾杯&心連心,

2

響應的OP有過的代碼片斷

我看不出這個問題與你指出的朋友。兩個抽象類可以是彼此的朋友。它絕對沒有問題。

這裏是我猜你是說明假設你PluginLoader接口包含的不僅僅是Register...方法更多,你想通過這個接口來操作裝載機...(只是一個樣本illustratory代碼)

struct pluginloader; 

struct plugin{ 
public: 
    void publicm(pluginloader &r); 
    virtual ~plugin() = 0;    // abstract 
private: 
    void privatem(pluginloader &r); // may be virtual in real code 
}; 

struct pluginloader{ 
public: 
    void publicm(){}; 
    virtual ~pluginloader() = 0;  // abstract 
private: 
    void privatem(){}     // may be virtual in real code 
    friend struct plugin;    // friend declaration 
}; 

void plugin::publicm(pluginloader &r){ 
    r.privatem();      // use private methods of pluginloader 
} 

void plugin::privatem(pluginloader &r){ 
    r.privatem();      // use private methods of pluginloader 
} 

plugin::~plugin(){} 
pluginloader::~pluginloader(){} 

struct APlugin : plugin{ 
    ~APlugin(){} 
}; 

struct ALoader : pluginloader{ 
    ~ALoader(){} 
}; 

int main(){ 
    APlugin apl; 
    ALoader ald; 

    apl.publicm(ald); 
} 
+0

你的例子現在工作。但是當你從'Plugin'和'PluginInfo'派生時會發生什麼? – nakiya 2010-11-03 07:14:41

+0

@nakiya:這不是問題。請參閱更新代碼 – Chubsdad 2010-11-03 07:18:04

+0

順便說一句,我認爲你的意思是PluginLoader而不是PluginINfo? – Chubsdad 2010-11-03 07:21:43

相關問題